標籤:style blog http tar com get
概述
我們在上一篇Windows平台分布式架構實踐 - 負載平衡中討論了Windows平台下通過NLB(Network Load Balancer) 來實現網站的負載平衡,並且通過壓力測試示範了它的效果,可以說還是非常的理想的。同時我們也收集到了不少的問題,比如說如何在這種分布式的架構下使用Session,NLB中有一台伺服器掛掉了會導致對外暴露的地址無法訪問,如果實現伺服器之間的同步,如果更好的進行熱修複等等,還有我們在上一篇中也提到了NLB所提供的功能是非常簡單的,為了回答我們前面提到的問題,也為了提供一個比較全面完整的負載平衡方案,我們來看看Windows平台下負載平衡的另一種實現APR (Application Request Router + Web Farm + Url Rewriter),希望可以為大家解決一些實現的問題。
目錄
- 安裝配置負載平衡
- 網站部署與同步
- 安裝程式與運行環境的同步
- 網站內容與配置的同步
- 配置入口伺服器
- 驗證負載平衡
- Session在APR分布式環境下的應用
- 搭建多台APR 伺服器來提升可用性
- 小結
安裝配置負載平衡安裝相關組件
話不多說,為了實現一個比較完整的負載平衡,我們要引入以下5個組件。
- Web Deploy V3.0
- Web Platform installer V5.0
- Web Fram 2 for IIS7
- Applicaiton Request Router 3 for IIS
- Url Rewriter 2 for IIS7
安裝Web Fram 必須要先安裝Web Deploy 和Web Platform,所以我把它們倆放在最前面,你也可以參考上面的順序來安裝,當然你首先得自己把IIS和ASP.NET 模組給裝上。我們這次不會對這5個組件的原理做詳細的介紹,大家知道怎麼操作就可以了,如果有興趣的同學可以繼續深入。安裝過程非常的簡單,基本上每一個組件只需要點一下按鈕就可以了,全部安裝完之後,你就會在當前那台機器上的IIS下看到一個Server Farms的結點。
配置負載平衡
如果大家還有印象,在使用NLB配置負載平衡的時候,我們是不需要一台單獨的機器來作為主入口的。 我們給所有的WEB伺服器都安裝上NLB,然後選擇任意一台將其它的WEB伺服器加進入同時設定一個單獨的IP作為入口地址即可。 但是換成APR,情況就有點不一樣了。我們需要一台單獨的入口伺服器來接收所有的請求,由它再把所有的請求根據配置的規則轉寄給其它真實的WEB伺服器。
3 台Web 服務器我們還是用我們上次做過實驗的那三台,我們再添加一台配置一樣的虛擬機器,然後給這4台伺服器全部安裝上APR(包括我們上面列出的5個組件)之後,我們就可以開始配置了。我們首先在我們的入口伺服器上建立一個Web Farm。在IIS中右擊Server Farms -> Create Server Farm,
我們勾上“Server farm is available for load balancing(在Web Fram中使用負載平衡)” ,下面的“Provision server farm”,我們也勾上,並為它輸入一個賬戶,這個賬戶要求有許可權可以訪問這個Web Farm裡面的所有伺服器。Provision 主要是用來實現主-從伺服器同步的,我們暫時先忽略它,後面再具體講。
我們將192.168.1.130設定我們的主Web 服務器,一會我們結合Provision(俺不知道這個翻成中文該叫什麼,直譯“提供”好像很彆扭) 功能就可以實現在主伺服器上部署和更改配置就會被自動同步到其它的伺服器上。完成建立Web Farm之後,我們就可以在IIS中進行後面的配置了。我們通過點擊每一個Web Farm下的Servers來查看每一個Web伺服器的狀態,是不是串連正常等等 。
同時我們還可以點擊每一個Web farm來進行以下功能的管理,這裡我們就點擊Mono。
配置Load Balance 演算法
我們首先要做的就是進入 “Load Balance”,在這裡你可以選擇負載平衡的演算法 :輪轉調度,隨機分配,URL參數,要求標頭等。如果不瞭解這些演算法幹什麼 的,那就去複習上一篇吧。APR為我們提供了以下7種演算法:
- Weighted round robin 根據權重按照請求資料進行分配
- Weighted total traffic 根據權重按照請求和響應位元組大小進行分配
- Least current request 優先轉寄給那個當前處理最少請求的伺服器
- Least response time 優先轉寄給那個當前響應最快的伺服器
- Server variable hash 根據伺服器變數的hash來分配請求,這裡面的伺服器變數包括Cookie, URL,頭資訊等 ,詳情點這裡。
- Query string hash 根據URL查詢字串的hash來分配請求,如果查詢字串包含多個參數(?name=jesse&location=sh),則是用整個查詢字串的hash來作判斷。
- Request hash 根據伺服器變數或者是URL的hash來分配請求,比如說伺服器變數是QUERY_STRING,那麼hash的值就是query string中對應的那個值。
大家可以已經猜到,後面3種演算法是可以利用來實現這種分布式環境下session的訪問的,但是由於要涉及到其它的配置,所以我們後面再講,讓我們先專註於把這個負載平衡配置完,所以我們就裡就先選擇比較簡單的Least response time,誰當前返迴響應最快我們就把請求給它,驗證了那句話,“能者多勞啊”。
配置轉寄規則
APR的機制是做為一個Proxy 伺服器,它負責接收請求,但是不做任何處理,而是直接將請求分發給具體的WEB伺服器。同時我們還可以配置一些規則,有一些請求轉寄,有一些請求不轉寄,這就要感謝我們的url rewrite組件了。我們可以進入“Routing Rules”來進行相關的配置。
網站部署與同步安裝程式和運行環境同步
在實際的環境中,如果我們使用NLB在第一次部署的時候,就需要一個伺服器一個伺服器的部署,而且如果要對IIS進行其它的一些配置就會顯得很煩瑣。在APR中給我們提供的Provision功能,就可以協助實現這樣的同步功能。
在Server Farm的功能視圖中,我們可以找到以下兩種類型的Provision:
- Application Provisioning: 主要是用來同步網站相關包括內容,配置等等,Web Deploy就是用在這裡了。
- Platform Provisioning:主要是用來同步安裝程式的,其實這裡面的Platform是指我們上面安裝的 Web Platform Installer,也就是說我們在主伺服器上通過Web Platform安裝的程式或者組件,如果啟用了Platform Provisioning的話,其它所有的伺服器也會自動安裝上。
我們可以來做一個Platform Provisioning的例子,點擊我們的Server Farm -> 在右邊的功能視圖中雙擊Platform Provisioning -> 勾選下面兩個選項。
然後我們點擊左右的Servers,選中我們的主伺服器(Primary),在右邊的巨集指令清單中選擇 “Install Product”,在彈出的表單中安裝的程式就會被自動安裝到當前Server Farm中的所有其它伺服器中。
網站內容同步
和上面的思路一樣,我們不需要每一個程式都部署一遍,我們只需要在主伺服器上部署一遍就可以了,所有的內容以及IIS的設定都會被自動同步到其它伺服器上,這就是Application Provisioning來幫我們實現的。我們可以通過點擊我們的Server Farm ->在右邊的功能視圖中雙擊 “Applicaiton Provisioning” 然後勾選下面的兩項即可。
接下來,我們只需要在我們的主伺服器上建立我們的網站然後部署我們的網站即可,包括對網站進行一些應用程式集區的配置也是只需要在主伺服器上完成的,我們就不需要到每一台伺服器上都去布置一遍了。
配置入口伺服器
既然入口伺服器不做任何處理只是轉寄請求的話,那我們還需要把我們的網站的內容放在入口伺服器的IIS下嗎?這個就取決於不同的情境了,你可以建一個空的網站什麼也沒有,你也可以用它來做一個簡單的檔案伺服器,在上一步中將靜態檔案不轉寄即可,讓我們Web Farm中的伺服器只處理動態請求,也可以減輕他們的壓力。當然如果你有單獨的檔案伺服器那就更好了。作為測試用途我們在入口伺服器上就不建任何網站了,直接使用安裝IIS內建的那個預設網站即可。
有人可能會有疑問,因為我在配置Server Farm的時候同樣也有這樣的一個疑問。“所有的請求都是由入口伺服器接收,然後再分發給Farm中具體的伺服器的,那入口伺服器的那個網站該如何配置呢? 是用80還是8080連接埠,如果我建了好幾個網站,那到底哪一個網站的請求會被Farm拿到再進行轉寄呢?”
我在入口伺服器中沒有做任何網站的配置,也就是說本地有一個http://localhost的網站是可以訪問的,對於外部來說它的地址就是 http://192.168.1.129/,那麼為什麼當外部存取 192.168.1.129的時候,它就會被Farm 中的伺服器處理呢? 這就要多虧我們的Url Rewrite模組了,我們可以點擊我們的Farm Mono,進入到功能視圖->然後點擊 Routing Rules -> 在Routing Rules 右側的巨集指令清單中點擊 URL Rewrite... 對Routing Rules進行更詳細的管理。
在我們的URL Rewrite視窗,我們就會看到已經為我們預設建立了一條入站的規則。
我們可以雙擊那條規則查看詳細,或者進行編輯,我們可以看到這條規則實際上是用萬用字元匹配了所有的入站請求,然後轉寄給我們的Server Farm: Mono。原來是URL Rewrite在這裡起了作用,當然我們也可能把 *改成 其它的萬用字元,以及使用Regex來匹配都是可以的,這些都是URL Rewite裡面的功能,是可以直接搬過來用的。
URL Rewrite協助我們匹配入站請求,然後轉寄給Farm,在Farm層面 APR根據 我們配置的負載平衡演算法將請求轉寄給具體的伺服器去處理請求。現在我們再回過頭來看看我們最開始安裝的5個組件都分別起到了什麼作用。
- Web Deploy : 參與Application Provisioning(網站內容及配置同步)
- Web Platform Installer: 參與Platform Provisioning( 應用環境同步)
- Web Farm: 主要召集人及容器
- Application Request Router: 負載平衡處理
- URL Rewrite: 入站請求匹配等
驗證負載平衡
到這裡為止,我們用 APR + Web Farm搭建的負載平衡就完成了,最終結果是我們在外面訪問 http://192.168.1.129的時候,實際上是由我們Farm中的3台Web 服務器處理的,口說無憑,我們來驗證一下。驗證的方法很簡單,我們在每個伺服器下放不同的檔案用來標識當前是哪個伺服器在處理響應(記得在部署檔案的時候要先把Application provisioning關閉掉,不然主伺服器上的檔案會被同步到其它的伺服器上去的)。
在web-02和 web-03上,分別返回不前的伺服器的名字就可以了。但是在測試上可能會遇到一點小問題,那就是當我們訪問http://192.168.1.129的時候,總是由web-01處理的,因為我們的頁面幫簡單,又只有一個使用者在訪問,所有後面兩台伺服器壓根沒有發揮作用。這時候我們就可以把web-01和 web-02從 Farm中移除掉,那麼所有的請求就會被web-01來處理了。
就是這麼簡單,Web Farm給我們提供的這個功能非常的實用,我們可以在運行時隨時動態添加或移除伺服器。還記得以前我們只有一台伺服器的時候,為了儘可能的不影響使用者,發布都選擇在晚上的10點以後,所以經常是一發布就通宵。想想如果有這個功能,白天也發行就緒了,只要先把一些機器從Web Farm中拿下來,發布好測試通過之後再放上去並且把別外那一些也拿下來發布就好了。當然這種情境只適合一些中小型的網站,一旦網站大了,那發布將會是一個非常嚴格的流程,而且一般會有專門的發布人員或者工具。
Session在APR 分布式環境下的應用
關於Session在分布式環境下的使用其實是有爭議的,有人說老師都不讓用Session了,但是有人又想方設法的想要使用它。我們暫且不討論它的正確與否,因為沒有最好的架構,只有最合適的架構,正所謂存在即合理。我們都不得不承認Session在很多管理系統,以及一些小型的網站的開發上帶來了很大的便利性,開發快速同時又可以帶來看得見的效能提升。所有個人認為,用還是不用那就看情境吧。但是我們從學習的角度出發,還是應該考慮到各種可行性,以及他們之間的利與弊,這樣才能協助我們在真實情況下做出最合適的決策。
Server Affinity(伺服器關聯性)
在Farm的功能視圖中,有一個Server Affinity的功能可以用來跟蹤請求或者說提供一種伺服器和用戶端之間的粘性,當第一個請求被處理之後,這個請求所在用戶端後面發起的所有請求都會交給同樣的伺服器來處理,這就是Server Affinity。APR為我們提供了兩種選項:
- Client Affinity: 會給來自不同用戶端的請求分配一個cookie,然後根據這個cookie來識別請求應該由哪個伺服器來處理。
- Host Name Affinity:根據Host name來作粘性處理,它還有兩種provider可以採用:
- Microsoft.Web.Arr.HostNameRoundRobin: 保證盡量平均分配到伺服器
- Microsoft.Web.Arr.HostNameMemory: 根據記憶體使用量情況來分配,保證各個伺服器的記憶體使用量情況達到均衡。
原來在APR這種分布式架構下使用Session是這麼的簡單,而且我們可以根據實際情況,Client Affinitt 和 Host Name Affinity一起使用。
搭建多台APR伺服器來提升可靠性
還記得我們在上一篇中提到的,引入負載平衡幫提高了兩點:可靠性和可擴充性。多台伺服器共同處理的情況下,哪怕其中部分出了問題也不會導致整個網站無法訪問,提高了我們的可靠性。隨時動態添加和移除伺服器而不影響網站的訪問,提供了我們的可擴充性。但是這裡還有一個問題,但是如果APR所在的那個伺服器出了問題怎麼辦?雖然這種可能性比較低,因為我們的APR伺服器只是做了很簡單的轉寄請求的功能,並沒有運行真實的網站,但仍然不排隊會有其它的異常導致IIS或者Web Farm停止運行,對於像這樣的問題,我們就可以通過部署多台APR伺服器來再一次提升我們網站的可靠性。
一台APR伺服器可以將請求分發給具體的伺服器,如果是多台APR伺服器,那誰來決定請求是由哪台APR伺服器處理呢?
還記得我們上篇講的NLB嗎?它不需要一台單獨的伺服器配置,只需要給目標機器都裝上NLB,然後配置一個暴露給外部的地址就可以了。所以這次當我們訪問外部地址的時候會有接下來的幾步動作:
- NLB最先拿到請求資訊,然後具體的APR伺服器再去響應請求
- 當某台APR響應請求的時候會根據配置好的負載平衡演算法交給後面具體的Web伺服器去處理
- Web伺服器請求完之後,再把響應資訊返回給用戶端
小結
第二篇稍微來的晚了一點,對一直關注的朋友說聲抱歉,最近個人的事情有點多,也是想把APR盡量呈現的全面一點:)。使用APR相對於NLB來說給我們提供了更全面的負載平衡功能,結合APR和NLB一起使用帶來更高的可用性,但是由於APR採用的是代理的方式,所以效能會比NLB低一些,但是有時候穩定更重要,不是嗎?當然還有很多其它的方案我們都是可以去嘗試的,比如說Ngnix很久以前就已經在開源社區獲得了很好的聲譽。我們這兩篇算是讓大家對負載平衡有一個比較感性的認識,真實的項目過程中還要考慮我們代碼的架構,如何保證我們的系統能夠在分布式環境下完美運行,並真正發揮分布式的力量,我們還有很長的一段路要走,用分布式緩衝替代Session方案,資料庫群集,服務群集和隊列等,我們一個一個的攻破,歡迎大家持續關注!最後祝大家上班編碼快樂 :)