關於大型網站技術演進的思考(十八):網站靜態化處理—反向代理(10)

發表於2015-03-05

反向代理也是一種可以幫助實現網站靜態化的重要技術,今天我就來講講反向代理這個主題。那麼首先我們要了解下什麼是反向代理。和反向代理相對應的是正向代理,正向代理也就是我們常說的代理服務,正向代理是非常常見的,例如在某些公司裡我們想使用網際網路,那麼我們就得在瀏覽器裡設定一個代理伺服器,通過代理伺服器我們才能正常使用網際網路,而這個代理伺服器就是一個正向代理伺服器。正向代理更加讓人熟悉的使用場景估計還是在FQ技術裡的使用,我們使用一個放置在國外的代理伺服器來訪問那些在國內無法正常訪問的網站,這其實也是在使用一個正向代理服務。

其實不管是正向代理還是反向代理,這兩個概念的定義都是以瀏覽器側為基準進行的,正向代理是代理瀏覽器來訪問網際網路,反向代理是指代理不再是代理瀏覽器側了,而是反過來代理瀏覽器需要訪問的應用伺服器。那為什麼我們要使用正向代理伺服器了?答案當然不是為了FQ了,下面我來列舉些例項來說明這個問題了。

例如公司裡使用代理伺服器主要是為了安全的考慮,很多公司內部都有自己的區域網,一般我們稱之為內網,內網裡有公司的各種資源,如果公司員工的電腦隨意連線到網際網路,假如碰到那些別有用心的黑客,通過攻擊員工的工作電腦擷取了公司重要的檔案資料,那樣就會造成公司的重大損失,正向代理除了能防範外部的黑客攻擊外還能監控和控制公司內部員工將公司重要檔案通過網際網路傳遞給不恰當的人,因此公司讓員工使用代理上網基本都是出於安全的角度來考慮的。

正向代理的合理使用還能幫助一些企業提升自己產品的核心競爭力,例如在移動端有一款非常流行的瀏覽器,它之所以非常受使用者的歡迎,是因為使用該瀏覽器上網速度比其他瀏覽器明顯的快多了,那麼這款瀏覽器是如何做到這點的呢?奧祕就是這家公司為自己的瀏覽器對應建立一個十分強大的代理伺服器叢集,使用者使用該瀏覽器訪問網站時候使用者首先訪問的是該公司的代理伺服器,而這些代理伺服器使用快取技術快取了海量的網站資訊,再加上使用一些web加速的技術例如CDN技術,這就讓該瀏覽器訪問網站的效率明顯快於其他瀏覽器。

反向代理和正向代理從技術角度上基本上是一致的,區別主要是代理的內容不一樣了,反向代理代理的是應用伺服器。反向代理技術也基本上是網際網路公司的一個標配技術,但是反向代理能否正確使用,能否更進一步的發揮它的實用價值,我覺得並不是所有公司都能做好的,下面我來總結一下反向代理的使用目的吧,具體如下:

使用目的一:反向代理可以隱藏真實的應用伺服器。該目的屬於安全的範疇,反向代理隱藏真實的應用伺服器,那麼就可以讓別有用心的黑客很難掌握正確的應用伺服器,從而增加黑客的攻擊難度。

使用目的二:反向代理可以實現負載均衡的功能,例如在java的web開發裡有一種很簡單的實現叢集的手段,這個手段就是使用apache加上tomcat的組合,使用者請求先到達前置的apache伺服器,apache再使用負載均衡策略將請求分配給後臺不同的tomcat伺服器上。

使用目的三:反向代理可以起到動態調節應用伺服器併發數的目的,一般用作反向代理的伺服器都是靜態資源伺服器,這樣的伺服器在併發處理能力上要遠強於後臺的web應用伺服器,那麼可以通過控制web應用伺服器前置的反向代理伺服器,這樣就可以動態調節後臺服務的負載的大小,這個做法的好處可能很多朋友都不太瞭解,這裡我列舉個例子,一個網站最需要穩定性的部分是哪個部分呢?很多朋友會說是資料庫,的確資料庫是最重要的,因為資料庫做分散式很難,很容易形成單點故障,要是資料庫掛了基本一切都沒法玩了,那麼除了資料庫之外還有別的嗎?當然有,那就是用於處理業務的應用伺服器了,應用伺服器如果做了叢集,叢集中其中一臺伺服器掛了其影響面會比資料庫掛掉低多了,但是一個網站的做業務處理的應用伺服器掛掉,對公司的損失還是很大的,而web應用伺服器前面的用作反向代理的靜態資源伺服器掛掉問題就會小多了,至少不會產生公司業務無法正常完成的事情了,因此當網站負載過高,讓過載的請求被反向代理攔截或者阻止,這對應用伺服器的穩定性提升有莫大的好處。當然反向代理調節應用伺服器的負載水平的用途不僅僅這些,有興趣的朋友可以在網路上找找相關的介紹。

使用目的四:反向代理可以快取靜態資料,一般用作反向代理的伺服器都是使用像apache或者是ngnix這樣的靜態資源伺服器,因此我們可以把web應用裡的靜態資源快取在反向代理伺服器上,從而達到提升請求處理的速度問題。反向代理的這個功能就和本系列的主題網站靜態化處理切合了。

分析完反向代理的使用目的後,我們現在將反向代理應用到專案裡,這裡應用的一個前置限定就是將反向代理應用到網站靜態化的處理之上,首先是第一個應用方式,如下圖所示:

第一種反向代理應用方式就是讓反向代理和應用伺服器一一對應,也就是每臺應用服務的部署伺服器上都對應部署一臺反向代理伺服器,這麼做有怎樣的好處呢?首先我們來講第一個好處,如果我們將網頁做了動靜分離,那麼反向代理伺服器就可以負責對請求中的靜態資源訪問進行處理,同時反向代理還可以承擔動靜資源整合的目的。這裡要特別說明下,前文裡我說道動靜資源會因為我們使用的動靜策略而發生轉化,那麼有些動態內容在一定條件被轉化為靜態資源後,我們可以將這些做了轉化的靜態資源在伺服器上快取起來,這個時候上圖展示的架構模型就會發生變化,如下圖所示:

我們看到反向代理伺服器和應用伺服器之間會形成一個cache層,反向代理訪問cache層的效率會比直接訪問應用伺服器要高的多,這等於是給應用伺服器做了一個加速操作,同時通過快取我們可以減少應用伺服器的運算壓力,從而達到提升應用伺服器效能的目的。以前有朋友問我這麼做會不會增加應用伺服器的壓力,因為一臺伺服器上部署了兩臺可以處理web請求的伺服器,那麼它們之間一定會有發生衝突的時候,不過我想產生衝突肯定是我們沒有很好的處理二者關係所致,所以我們要理清在同一臺伺服器上部署反向代理和應用伺服器後,它們之間的關係到底是怎樣的?

其實反向代理和應用伺服器從物理形態角度上它們是兩個不同的東西,但是二者在邏輯上其實是一個整體,它們共同完成一個邏輯性的應用伺服器的功能,只不過二者因為應用場景不同而形成了一種分工合作的關係,反向代理伺服器主要完成對靜態資源請求的處理,而應用伺服器則是負責業務邏輯的處理,它們最終形成一個強大的合力使得整體的邏輯性應用伺服器的效能得到顯著的提升。

除此之外,這個反向代理還可以發揮動態調節應用伺服器的併發數的目的,但是上面的技術方案卻沒有發揮反向代理的負載均衡以及安全性這兩個方面的作用。為了讓反向代理四個使用目的得到充分的發揮,那麼我們該如何來做了?

方法很簡單就是把反向代理的部署地點從應用伺服器所在的物理伺服器上遷移出來,放到一臺獨立的物理伺服器上,但是這個做法會有效能上的損失,同時還會增加整個技術架構的複雜性。為什麼效能會損失呢?因為原來的反向代理伺服器和應用伺服器部署在同一個物理伺服器上,那麼它們之間的通訊都是以記憶體共享的方式進行的,這樣的通訊效率是非常高,現在換成了通過網路通訊進行溝通,而網路通訊是IO裝置裡效率最差,可靠性最差的,因此單獨部署反向代理伺服器或多或少都會造成一定效能的損失。

為什麼說單獨部署反向代理會增加整個網站技術架構的複雜性了?我們把反向代理伺服器單獨部署,那麼單獨部署時候我們還會是使用一一對應的策略嗎?先不談這麼做,從技術和業務角度的好處和壞處,但從成本這個考慮就是會讓很多公司望而卻步,因為這個做法就會導致用於部署應用伺服器的成本翻倍的增加,而增加的伺服器用於反向代理,這樣的做法怎麼體會都不是覺得物有所值,再說用於反向代理的靜態資源伺服器本身處理請求的併發能力是普通應用伺服器的數百倍,一一對應本身也沒有完全發揮反向代理伺服器的潛力,因此最好的解決方法就是把反向代理伺服器做成一個反向代理伺服器叢集,做成叢集問題又來,叢集裡每臺反向代理快取的資料是不是要保持一個同步了?這就好比處理應用伺服器的session同步問題,如果真的這麼做會不會導致反向代理伺服器上快取大量使用率不高的資料從而導致快取的利用率很差,同時同步操作本身也會影響到反向代理叢集的效能,所以要設計一個好的反向代理叢集是一件十分複雜的事情,其實合理的反向代理叢集的做法就是在叢集裡在進行分組,每個分組應該是和後端的SOA服務相匹配,這個時候反向代理叢集的效率才能得到最大的發揮,同時資源利用率也會更加的合理。其實使用反向代理叢集方式,也會給生產部署造成麻煩,如果網站進行了靜態化處理,那麼反向代理需要承擔對靜態資源的處理操作,這個時候反向代理和對應的應用伺服器結合起來才能形成一個完整的應用伺服器,但是現在我們將一個完整的邏輯應用伺服器分開部署了,那麼當我們釋出新應用的時候就得面臨更加複雜的情況,這就增加了部署和運維的風險和難度。

我如此批評單獨部署反向代理的問題,但是我並不是說這種做法完全不可取,而是想告訴大家這種做法其實是一種高階的做法,但是也是一個複雜的做法,要做好這個叢集是很麻煩的一件事情的,我覺得只有當我們的網站業務量和請求量很大的時候,同時原有方案出現了瓶頸時候可以認真考慮反向代理叢集方案的實現,不過將反向代理形成叢集會給網站的安全性帶來莫大的好處,反向代理可以隱藏後臺的應用伺服器,這種隱藏就是客戶端只需要訪問代理伺服器即可,應用伺服器對外都是以反向代理來展示的,但是如果反向代理和應用伺服器一一對應,那麼惡意黑客找準了某臺反向代理伺服器後,對這個反向代理伺服器進行反覆的攻擊,那麼這個攻擊也就等於攻擊與之對應的應用伺服器,這就導致反向代理隱藏真實應用伺服器的作用就沒有得到有效的發揮,而叢集這塊就可以很好的處理這個問題,不過我們如果覺得使用叢集代價太高,我們也有變通的方法,那就是在所有邏輯應用伺服器前面再放置一個反向代理伺服器,這個反向代理伺服器不再承擔快取的功能,而只是用來做負載均衡和安全處理,這樣一一對應的策略安全性也可以得到保證,不過如果公司技術能力好可以考慮使用LVS這種軟體化的負載均衡技術方案,假如公司還很有錢還可以考慮使用更加高階的硬體負載均衡裝置例如F5裝置。

如果我們網站除了使用網站靜態化技術還使用了前後端分離技術,當然這個前後端分離技術應該是使用nodejs的前後端分離技術,那麼nodejs應該放置在生產部署的什麼位置上了?上篇文章裡我曾列舉了一個nodejs的應用實踐場景,在這個實踐場景裡我曾經提到如果在原有的網站生產架構下引入nodejs會增加一個請求處理環節,而nodejs使用主要是為了滿足前後端分離而非增加網站效能,因此增加的環節可能會讓請求處理的效能下降,因此我最後提出一種變通手法,就是nodejs專案釋出時候編譯原始碼,然後將編譯出的javascript和html檔案乾脆推移到瀏覽器端處理,這樣就變相形成了前端MVC框架,這個做法總是有點不倫不類的意味,假如我們真的想把nodejs引入到應用生產的網路架構裡,我們不希望無端的增加請求處理環節,那麼最好是讓nodejs伺服器替換某個部分。按照這個思路思考,那麼我覺得nodejs在生產的引入最好是和反向代理相關,最簡單的方式就是讓nodejs和反向代理一一對應,這樣就可以很好的降低引入nodejs帶來的問題,當然複雜點的就是反向代理叢集對應的應用伺服器應該是nodejs的應用伺服器,而不是用來做業務處理的業務級別的應用伺服器。

不管怎麼說,我認為在網站靜態化方案裡我們一定要考慮反向代理的運用,如果靜態化技術方案裡沒有反向代理的身影,那麼這個網站靜態化處理可能很難達到我們預期的效果。

好了,今天就寫到這裡,最後祝大家晚安。

相關文章