概敘
網絡模型:OSI七層模型、TCP/IP四層模型、現實的五層模型
應用層:對軟件提供接口以使程序能使用網絡服務,如事務處理程序、文件傳送協議和網絡管理等。(HTTP、Telnet、FTP、SMTP)
表示層:程序和網絡之間的翻譯官,管理數據的解密加密數據轉換、格式化和文本壓縮。(JPEG、ASCII、GIF、DES、MPEG)
會話層:負責在網絡中的兩節點之間建立和維持通信,以及提供交互會話的管理功能。(RPC、SQL、NFS)
傳輸層:提供建立、維護和拆除傳送連接的功能;選擇網絡層提供最合適的服務;在系統之間提供可靠的透明的數據傳送,提供端到端的錯誤恢復和流量控制。(TCP、UDP、SPX)
網絡層:將網絡地址(ip地址)翻譯成對應物理地址(網卡地址),并決定如何將數據從發送方路由到接收方。(IP、ICMP、IGMP、IPX、ARP、RARP)
數據鏈路層:物理地址尋址、數據的成幀、流量控制、數據的檢錯、重發。(IEEE 802.3/.2、HDLC、PPP、ATM)
物理層:物理連網媒介,如電纜連線連接器。(RS232、V.35、RJ-45、FDDI)
為什么要有負載均衡?
????????在高并發的業務場景下,解決單個節點壓力過大,導致Web服務響應過慢,特別是嚴重的情況下導致服務癱瘓,無法正常提供服務的問題,目的就是為了維護系統穩定可靠。而負載均衡技術通過將負載(?工作任務)?平衡、?分攤到多個操作單元上進行運行,?如FTP服務器、?Web服務器等,?從而協同完成工作任務。?這種技術構建在原有網絡結構之上,?提供了一種透明且廉價有效的方法來擴展服務器和網絡設備的帶寬,?加強網絡數據處理能力,?增加吞吐量,?提高網絡的可用性和靈活性。?
????????負載均衡的主要作用是為了保證系統的可用性、?可靠性、?性能和響應時間。?????????
????????具體來說,?負載均衡的作用包括:?
- 提高系統性能:?通過將負載分發到多個資源上,?系統能夠處理更多的并發請求,?從而提高整體的處理能力和性能。?
- 實現高可用性:?當其中一個資源發生故障或不可用時,?負載均衡可以自動將請求轉發到其他可用的資源,?降低單點故障的風險,?提高系統的可靠性和容錯性。?
- 提高系統可伸縮性:?隨著業務的增長,?負載均衡技術可以動態地增加或減少資源的數量,?根據實際負載情況進行擴展或收縮,?實現水平擴展,?滿足不斷增長的需求。?
- 優化資源利用:?根據資源的性能、?可用性和負載情況,?合理地分配請求或任務,?最大限度地利用資源,?避免資源的空閑或過載。?
????????此外,?負載均衡還可以與其他云服務進行集成,?例如容器編排、?數據庫、?網絡服務等,?為用戶提供更全面的云服務。?通過實現這些功能,?負載均衡確保了系統的持續運行,?優化了系統的性能和響應時間,?從而提高了系統的整體效率和用戶體驗
什么是負載均衡?
? ? ? ? 負載均衡(Load Balance)的指將負載(工作任務)進行平衡、分攤到多個操作單元上進行運行,例如FTP服務器、Web服務器、企業核心應用服務器和其它主要任務服務器等,從而協同完成工作任務。負載均衡構建在原有網絡結構之上,它提供了一種透明且廉價有效的方法擴展服務器和網絡設備的帶寬、加強網絡數據處理能力、增加吞吐量、提高網絡的可用性和靈活性。
????????負載均衡重點在于由原來的單個節點承接流量,變成多個節點分擔流量,減少請求響應時間,提高應用程序的可用性和可伸縮性。
????????負載均衡是指將傳入的網絡流量高效分發到一組后端服務器,也稱為“服務器群”或“服務器池”。現代高流量網站必須滿足來自用戶或客戶端的數十萬甚至數百萬的并發請求,并快速、可靠地返回正確的文本、圖像、視頻或應用數據。為了經濟高效地進行擴展以滿足這些海量數據需求,現代計算最佳實踐通常要求添加更多的服務器。
????????負載均衡有兩方面的含義:
????????首先,大量的并發訪問或數據流量分擔到多臺節點設備上分別處理,減少用戶等待響應的時間;????????
????????其次,單個重負載的運算分擔到多臺節點設備上做并行處理,每個節點設備處理結束后,將結果匯總,返回給用戶,系統處理能力得到大幅度提高。
????????通過這種方式,負載均衡器可執行以下功能:
- 在多臺服務器之間高效分配客戶端請求或網絡負載
- 僅向在線服務器發送請求,確保高可用性和可靠性
- 提供按需增減服務器的靈活性
負載均衡適用場景?
負載均衡策略
????????目前有許多不同的負載均衡技術用以滿足不同的應用需求,下面從負載均衡所采用的設備對象(軟、硬件負載均衡),應用的OSI網絡層次(網絡層次上的負載均衡),及應用的地理結構(客戶端和服務端負載均衡)等來分類。
硬件與軟件負載均衡
????????負載均衡器通常有兩種形式:基于硬件和基于軟件。基于硬件的解決方案的廠商將專有軟件加載到其提供的機器(通常搭載專用處理器)上。
????????為了處理日益增加的網站流量,您必須從廠商處購買更多或更大的機器。而軟件解決方案通常在商用硬件上運行,因此更為經濟、更加靈活。您可將軟件安裝到所選硬件上,或者安裝在 AWS EC2 等云環境中。
軟件負載均衡
????????軟件負載均衡解決方案是指在一臺或多臺服務器相應的操作系統上安裝一個或多個附加軟件來實現負載均衡,如DNS Load Balance,Check Point Firewall-1 Connect Control,Keepalive+ IPVS、Nginx、apache、LVS等,它的優點是基于特定環境,配置簡單,使用靈活,成本低廉,可以滿足一般的負載均衡需求。
????????軟件解決方案缺點也較多,因為每臺服務器上安裝額外的軟件運行會消耗系統不定量的資源,越是功能強大的模塊,消耗得越多,所以當連接請求特別大的時候,軟件本身會成為服務器工作成敗的一個關鍵;軟件可擴展性并不是很好,受到操作系統的限制;由于操作系統本身的Bug,往往會引起安全問題。
硬件負載均衡
????????硬件負載均衡解決方案是直接在服務器和外部網絡間安裝負載均衡設備,這種設備通常是一個獨立于系統的硬件,我們稱之為負載均衡器。由于專門的設備完成專門的任務,獨立于操作系統,整體性能得到大量提高,加上多樣化的負載均衡策略,智能化的流量管理,可達到最佳的負載均衡需求。
????????負載均衡器有多種多樣的形式,除了作為獨立意義上的負載均衡器外,有些負載均衡器集成在交換設備中,置于服務器與Internet鏈接之間,有些則以兩塊網絡適配器將這一功能集成到PC中,一塊連接到Internet上,一塊連接到后端服務器群的內部網絡上。
軟、硬件負載均衡的對比
????????軟件負載均衡的優點是需求環境明確,配置簡單,操作靈活,成本低廉,效率不高,能滿足普通的企業需求;缺點是依賴于系統,增加資源開銷;軟件的優劣決定環境的性能;系統的安全,軟件的穩定性均會影響到整個環境的安全。
????????硬件負載均衡優點是獨立于系統,整體性能大量提升,在功能、性能上優于軟件方式;智能的流量管理,多種策略可選,能達到最佳的負載均衡效果;缺點是價格昂貴(F5硬件服務器不低于20萬/臺)。
OSI網絡層次負載均衡
? ? ? ? 按照OSI七層模型劃分方式:根據采用的設備對象區分、根據位于OSI中不同層次的劃分,這里我們主要講根據OSI中的層次劃分。
二層負載均衡(mac地址):數據鏈路層,使用虛擬MAC地址方式,外部請求流量經過虛擬MAC地址,負載均衡收到流量請求后分配后端實際的MAC地址進行響應。
三層負載均衡(ip地址):網絡層,使用虛擬ip地址方式,外部請求流量經過虛擬IP地址,負載均衡收到流量請求后分配后端實際的IP地址進行響應。
四層負載均衡(tcp、udp):傳輸層,使用IP+PORT接收外部流量請求,轉發到對應的機器上。
七層負載均衡(http):應用層,使用虛擬的URL或IP地址接收外部流量請求,轉發到對應的處理服務器。1)二層負載均衡(一般是用虛擬mac地址方式,外部對虛擬MAC地址請求,負載均衡接收后分配后端實際的MAC地址響應);2)三層負載均衡(一般采用虛擬IP地址方式,外部對虛擬的ip地址請求,負載均衡接收后分配后端實際的IP地址響應);3)四層負載均衡(在三次負載均衡的基礎上,用 ip+port 接收請求,再轉發到對應的機器);4)七層負載均衡(根據虛擬的url或是IP,主機名接收請求,再轉向相應的處理服務器)。
二層負載均衡
????????二層負債均衡是基于數據鏈路層的負債均衡,即讓負債均衡服務器和業務服務器綁定同一個虛擬IP(即VIP),客戶端直接通過這個VIP進行請求。
????????那么如何區分相同IP下的不同機器呢?沒錯,通過MAC物理地址,每臺機器的MAC物理地址都不一樣,當負載均衡服務器接收到請求之后,通過改寫HTTP報文中以太網首部的MAC地址,按照某種算法將請求轉發到目標機器上,實現負載均衡。
????????這種方式負載方式雖然控制粒度比較粗,但是優點是負載均衡服務器的壓力會比較小,負載均衡服務器只負責請求的進入,不負責請求的響應(響應是有后端業務服務器直接響應給客戶端),吞吐量會比較高。
三層負載均衡
????????三層負載均衡是基于網絡層的負載均衡,通俗的說就是按照不同機器不同IP地址進行轉發請求到不同的機器上。
????????這種方式雖然比二層負載多了一層,但從控制的顆粒度上看,并沒有比二層負載均衡更有優勢,并且,由于請求的進出都要經過負載均衡服務器,會對其造成比較大的壓力,性能也比二層負載均衡要差。
四層負載均衡
????????四層的負載均衡就是基于IP+端口的負載均衡:在三層負載均衡的基礎上,通過發布三層的IP地址(VIP),然后加四層的端口號,來決定哪些流量需要做負載均衡,對需要處理的流量進行NAT處理,轉發至后臺服務器,并記錄下這個TCP或者UDP的流量是由哪臺服務器處理的,后續這個連接的所有流量都同樣轉發到同一臺服務器處理。
????????對應的負載均衡器稱為四層交換機(L4 switch),主要分析IP層及TCP/UDP層,實現四層負載均衡。
????????此種負載均衡器不理解應用協議(如HTTP/FTP/MySQL等等),常見例子有:LVS,F5。
七層負載均衡
????????七層的負載均衡就是基于虛擬的URL或主機IP的負載均衡:在四層負載均衡的基礎上(沒有四層是絕對不可能有七層的),再考慮應用層的特征,比如同一個Web服務器的負載均衡,除了根據VIP加80端口辨別是否需要處理的流量,還可根據七層的URL、瀏覽器類別、語言來決定是否要進行負載均衡。
????????舉個例子,如果你的Web服務器分成兩組,一組是中文語言的,一組是英文語言的,那么七層負載均衡就可以當用戶來訪問你的域名時,自動辨別用戶語言,然后選擇對應的語言服務器組進行負載均衡處理。
????????對應的負載均衡器稱為七層交換機(L7 switch),除了支持四層負載均衡以外,還有分析應用層的信息,如HTTP協議URI或Cookie信息,實現七層負載均衡。此種負載均衡器能理解應用協議,常見例子有:??haproxy,MySQL Proxy、Nginx、apache。
服務端負載均衡?和?客戶端負載均衡
服務端負載均衡
????????服務端負載均衡可通過硬件設備或軟件來實現,硬件比如:F5、Array等,軟件比如:LVS、Nginx等。通過硬件或軟件實現負載均衡均會維護一個服務端清單,利用心跳檢測等手段進行清單維護,保證清單中都是可以正常訪問的服務節點。當用戶發送請求時,會先到達負載均衡器(也相當于一個服務),負載均衡器根據負載均衡算法(輪訓、隨機、加權輪訓)從可用的服務端列表中取出一臺服務端的地址,接著進行轉發,降低系統的壓力。
服務端負載均衡分類
- DNS負載均衡
- 鏈路層負載均衡
- IP負載均衡
- HTTP負載均衡
- 反向代理負載均衡
DNS域名解析負載均衡
????????利用DNS處理域名解析請求的同時進行負載均衡是一種常用的方案。在DNS服務器中配置多個A記錄,每次域名解析請求都會根據負載均衡算法計算一個不同的IP地址返回,這樣A記錄中配置的多個服務器就構成一個集群,并可以實現負載均衡。
????????DNS域名解析負載均衡的優點是將負載均衡工作交給DNS,省略掉了網絡管理的麻煩,缺點就是DNS可能緩存A記錄,不受網站控制。事實上,大型網站總是部分使用DNS域名解析,作為第一級負載均衡手段,然后再在內部做第二級負載均衡。
數據鏈路層負載均衡(LVS)
????????數據鏈路層負載均衡是指在通信協議的數據鏈路層修改mac地址進行負載均衡。
????????這種數據傳輸方式又稱作三角傳輸模式,負載均衡數據分發過程中不修改IP地址,只修改目的的mac地址,通過配置真實物理服務器集群所有機器虛擬IP和負載均衡服務器IP地址一樣,從而達到負載均衡,這種負載均衡方式又稱為直接路由方式(DR)。
????????在上圖中,用戶請求到達負載均衡服務器后,負載均衡服務器將請求數據的目的mac地址修改為真實WEB服務器的mac地址,并不修改數據包目標IP地址,因此數據可以正常到達目標WEB服務器,該服務器在處理完數據后可以經過網關服務器而不是負載均衡服務器直接到達用戶瀏覽器。
????????使用三角傳輸模式的鏈路層負載均衡是目前大型網站所使用的最廣的一種負載均衡手段。在linux平臺上最好的鏈路層負載均衡開源產品是LVS(linux virtual server)。
IP負載均衡
????????IP負載均衡:即在網絡層通過修改請求目標地址進行負載均衡。
?????????用戶請求數據包到達負載均衡服務器后,負載均衡服務器在操作系統內核進行獲取網絡數據包,根據負載均衡算法計算得到一臺真實的WEB服務器地址,然后將數據包的IP地址修改為真實的WEB服務器地址,不需要通過用戶進程處理。真實的WEB服務器處理完畢后,相應數據包回到負載均衡服務器,負載均衡服務器再將數據包源地址修改為自身的IP地址發送給用戶瀏覽器。
?????????這里的關鍵在于真實WEB服務器相應數據包如何返回給負載均衡服務器,一種是負載均衡服務器在修改目的IP地址的同時修改源地址,將數據包源地址改為自身的IP,即源地址轉換(SNAT),另一種方案是將負載均衡服務器同時作為真實物理服務器的網關服務器,這樣所有的數據都會到達負載均衡服務器。
?????????IP負載均衡在內核進程完成數據分發,較反向代理均衡有更好的處理性能。但由于所有請求響應的數據包都需要經過負載均衡服務器,因此負載均衡的網卡帶寬成為系統的瓶頸。
HTTP重定向負載均衡
????????HTTP重定向服務器是一臺普通的應用服務器,其唯一的功能就是根據用戶的HTTP請求計算一臺真實的服務器地址,并將真實的服務器地址寫入HTTP重定向響應中(響應狀態嗎302)返回給瀏覽器,然后瀏覽器再自動請求真實的服務器。
????????這種負載均衡方案的優點是比較簡單,缺點是瀏覽器需要每次請求兩次服務器才能拿完成一次訪問,性能較差;使用HTTP302響應碼重定向,可能是搜索引擎判斷為SEO作弊,降低搜索排名。重定向服務器自身的處理能力有可能成為瓶頸。因此這種方案在實際使用中并不見多。
反向代理負載均衡
????????傳統代理服務器位于瀏覽器一端,代理瀏覽器將HTTP請求發送到互聯網上。而反向代理服務器則位于網站機房一側,代理網站web服務器接收http請求。
????????反向代理的作用是保護網站安全,所有互聯網的請求都必須經過代理服務器,相當于在web服務器和可能的網絡攻擊之間建立了一個屏障。
????????除此之外,代理服務器也可以配置緩存加速web請求。當用戶第一次訪問靜態內容的時候,靜態內存就被緩存在反向代理服務器上,這樣當其他用戶訪問該靜態內容時,就可以直接從反向代理服務器返回,加速web請求響應速度,減輕web服務器負載壓力。
????????另外,反向代理服務器也可以實現負載均衡的功能。
????????由于反向代理服務器轉發請求在HTTP協議層面,因此也叫應用層負載均衡。優點是部署簡單,缺點是可能成為系統的瓶頸。
客戶端負載均衡
????????對于客戶端負載均衡來說,與服務端負載均衡的主要區分點在于服務清單的存放位置。在客戶端負載均衡中,客戶端自己會存儲一份服務端清單,它是通過從注冊中心進行抓取得到的,同時也需要對此進行維護。
????????在如今的微服務架構中,基本都是采用的這種客戶端負載均衡。相比于服務器端負載均衡,它有一個顯著的優點,就是可以一定程度避免load balancer單點故障。
????????圖中主要包含三個部分:API Gateway、Service Registry Server、微服務。一般來說,為了提高并發處理能力,API Gateway和微服務都需要有多個instance。
基于上面的架構圖,設想兩個典型的場景:
- API Gateway收到一個請求,在完成?認證?和?授權校驗?之后,需要把請求轉發到微服務A去處理,而微服務A有多個instance,那么API Gateway應該如何把請求轉發到微服務A的哪個instance呢?
- 微服務A收到一個請求,處理這個請求時它需要發一個同步請求給微服務B以獲取一些數據,那么這時微服務A應該如何把請求發送到微服務B的哪個instance呢?
????????對于這兩個問題,我們可以利用服務注冊和服務發現模塊(比如說zookeeper、eureka等)來實現。一般來說,服務注冊和服務發現是微服務架構里面非常重要的一個模塊,它主要是用于解決微服務架構內部大量微服務之間相互依賴的問題。通過這個模塊,可以使微服務之間的相互依賴變得簡單和容易維護;同時,也可以實現微服務的負載均衡。
????????服務注冊和服務發現模塊是如何應用到上面兩個場景的呢?
服務注冊的角度:
????????每個微服務的instance在啟動階段就自動地把自己的IP和端口注冊到Service Registry Server;當shutdown的時候,Service Registry Server就自動地把這個instance的IP和端口刪除掉。
服務發現的角度:
????????針對場景1,API Gateway首先去Service Registry Server獲取微服務A所有的instance列表(IP+端口),然后利用某種負載均衡策略選擇一個instance,這時就可以直接把請求轉發到微服務A的這個instance。
????????針對場景2,流程也是類似,微服務A首先去Service Registry Server獲取微服務B所有的instance列表(IP+端口),然后利用某種負載均衡策略選擇一個instance,這時就可以直接把請求轉發到微服務B的這個instance。
客戶端負載均衡是如何避免單點故障的?答:緩存服務端實例列表
????????從負載均衡角度可以看到,負載均衡的邏輯是運行在客戶端的,顧名思義,這就是一種典型的客戶端負載均衡。回到上面提到的,客戶端負載均衡可以避免load balancer的單點故障,如何實現呢?以上面場景2為例,微服務A獲取到微服務B的所有instance列表之后可以緩存到內存中,接下來當微服務A請求微服務B時,都直接從內存中獲取微服務B的所有instance列表,這樣即使Service Registry Server掛了,也不影響微服務A和微服務B正常通訊。
API Gateway的負載均衡
什么是API Gateway?
????????網關是系統的唯一對外的入口,介于客戶端和服務器端之間的中間層,處理非業務功能,提供路由請求、鑒權、監控、緩存、限流、日志記錄等功能。這樣,不同的微服務之間無需重復實現限流、認證等功能,讓微服務每個服務的功能實現更加純粹,減少研發成本。無論你查看任何一個微服務項目架構,你都會發現在客戶端和服務器端之間有一個網關,移動端的任何請求都必須經過網關才能到達服務端。它包括但不限于以下這些特點:
- 豐富的路由策略:API Gateway 工作在七層,所以它可以解析到 HTTP/HTTPS 層的數據。因此它可以根據請求的 Path 或 Domain 甚至是 Header 作為條件,將請求轉發到不同的上游服務器。
- 認證:可以在 API 層面支持多種多樣的認證方式來避免非法請求,比如 OAuth2、JWT 等等,直接將認證這部分服務獨立出來,不侵入或者少侵入業務代碼。
- 限流:支持對不同程度的路由進行細粒度的限流,防止惡意攻擊,防止后端服務雪崩。
- 可觀測性:可觀測性是指從系統外部觀察系統內部程序的運行狀態和資源使用情況的能力。 API Gateway 支持將日志對接到 Kafka、 Google Cloud Logging Service、Elasticsearch 等,支持將相關 metrics 接入到 prometheus、datadog 等。
- 擴展:因為 API Gateway 自身是網關身份,這就注定對它要求是能適配各家公司不同應用場景,比如不同的鑒權、灰度、安全策略、日志收集等,必須允許用戶自由選擇所需擴展或者自定義開發,因此擴展性很強,允許選擇的擴展種類也十分豐富。以 Apache APISIX 舉例,光是認證的擴展就有 13 款,幾乎涵蓋了市面上常見的認證需求。
????????目前市面上有許多 API Gateway,比如 Apache APISIX、Kong、Tyk、Zuul 等,開發者可以根據自己的需求選擇合適的 API Gateway。
go-zero中負載均衡的實現
go-zero中的網關
????????go-zero推薦使用?nginx?做為網關,使用 nginx 的?auth_request?模塊作為統一鑒權,業務內部不做鑒權。由nginx統一接收外部請求,通過匹配 location 將請求轉發到不同的api服務,此時如果需要鑒權,則先調用鑒權api,鑒權通過后,再去調用對應的rpc服務。
Nginx負載均衡
高可用nginx集群
????????為了防止nginx宕機導致整個服務不可用,也可以使用 Keepalived+Nginx 來實現nginx雙機熱備。Master和Backup兩邊都開啟nginx服務,無論Master還是Backup,當其中的一個keepalived服務停止后,vip都會漂移到keepalived服務還在的節點上。對外只暴露一個vip。
具體實現原理:
- Master沒掛,則Master占有vip且nginx運行在Master上
- Master掛了,則backup搶占vip且在backup上運行nginx服務
- 如果master服務器上的nginx服務掛了,則vip資源轉移到backup服務器上
- 檢測后端服務器的健康狀態
Nginx實現四層負載均衡和七層負載均衡
負載均衡工作原理
-
負載均衡分為四層負載均衡和七層負載均衡。
-
四層負均衡是工作在七層協議的第四層-傳輸層,主要工作是轉發。
-
它在接收到客戶端的流量以后通過修改數據包的地址信息(目標地址和端口和源地址)將流量轉發到應用服務器。
-
七層負載均衡是工作在七層協議的第七層-應用層,主要工作是代理。
-
它首先會與客戶端建立一條完整的連接并將應用層的請求流量解析出來,再按照調度算法選擇一個應用服務器,并與應用服務器建立另外一條連接將請求發送過去。
Nginx實現七層負載均衡
Nginx服務器:192.168.2.10
后端服務器1:192.168.2.20
后端服務器2:192.168.2.30
前端服務器主要配置upstream和proxy_pass:
upstream?主要是配置均衡池和調度方法。
proxy_pass?主要是配置代理服務器ip或服務器組的名字。
proxy_set_header?主要是配置轉發給后端服務器的Host和前端客戶端真實ip。
Nginx服務器配置
[root@bogon nginx]# vim ? /usr/local/ngin/conf/nginx.conf
# 在http指令塊下配置upstream指令塊
upstream web {
server 192.168.2.20;
server 192.168.2.30;
}
# 在location指令塊配置proxy_pass
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
proxy_next_upstream error http_404 http_502;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
[root@bogon nginx]# ?/usr/local/nginx/sbin/nginx ?-s reload
proxy_next_upstream error http_404 http_502;??通過這個指令,可以處理后端返回404等報錯時,直接將請求轉發給其他服務器處理,而不是把報錯返回客戶端
proxy_set_header Host $host;? 通過這個指令,把客戶端請求的host,轉發給后端
proxy_set_header X-Real-IP $remote_addr通過這個指令, 把客戶端的IP轉發給后端服務器, 在后端服務器的日志格式中,添加$http_x_real_ip即可獲取原始客戶端的IP了
后端服務器配置
創建兩個靜態頁面,驗證負載均衡效果在后端服務器192.168.2.20配置如下(配置文件不需要修改即可)
vim /usr/local/nginx/html/index.html
this is 2.20 page
在后端服務器192.168.2.30配置如下(配置文件不需要修改即可)
vim /usr/local/nginx/html/index.html
this is 2.30 page
驗證不同的負載均衡策略
1.輪詢:
Nginx服務器 upstream web {
server 192.168.2.20;
server 192.168.2.30;}[root@bogon nginx]# /usr/local/nginx/sbin/nginx ?-s reload
訪問驗證:
[root@localhost ~]# while ?true;do curl ?192.168.2.10;sleep 2;done
this is 2.20 pagethis is 2.30 page
this is 2.20 pagethis is 2.30 page
this is 2.20 pagethis is 2.30 page
#可以看到后端服務器,非常平均的處理請求。
2.輪詢加權重:
upstream web {
server 192.168.2.20 weight=3;
server 192.168.2.30 ?weight=1;
}
默認是weight=1
[root@bogon nginx]# /usr/local/nginx/sbin/nginx ?-s reload
訪問驗證:
[root@localhost ~]# while ?true;do curl ?192.168.2.10;sleep 2;done
this is 2.20 page
this is 2.20 page
this is 2.20 pagethis is 2.30 page
this is 2.20 page
this is 2.20 page
this is 2.20 pagethis is 2.30 page
#后端服務,根據權重比例處理請求,適用于服務器性能不均的環境。
3.最大錯誤連接次數:
-
錯誤的連接由proxy_next_upstream, fastcgi_next_upstream等指令決定,且默認情況下,后端某臺服務器出現故障了,nginx會自動將請求再次轉發給其他正常的服務器(因為默 proxy_next_upstream error timeout)。
-
所以即使我們沒有配這個參數,nginx也可以幫我們處理error和timeout的相應,但是沒法處理404等報錯。
-
為了看清楚本質,可以先將proxy_next_upstream設置為off,也就是不將失敗的請求轉發給其他正常服務器,這樣我們可以看到請求失敗的結果。
vim /usr/local/nginx/conf/nginx.conf
upstream web {
server 192.168.2.20 weight=1 max_fails=3 fail_timeout=9s;
#先將2.20這臺nginx關了。
server 192.168.2.30 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
#proxy_next_upstream error http_404 http_502;
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
[root@bogon nginx]# /usr/local/nginx/sbin/nginx ?-s reload
# 在這里,我們將超時時間設置為9s,最多嘗試3次,
這里要注意,嘗試3次,依然遵循輪詢的規則,并不是一個請求,連接3次,
而是輪詢三次,有3次處理請求的機會
訪問驗證:
[root@localhost ~]# while ?true;do curl -I 192.168.2.10 ?2>/dev/null|grep HTTP/1.1 ;sleep 3;done
HTTP/1.1 502 Bad Gateway
HTTP/1.1 200 OK
HTTP/1.1 502 Bad Gateway
HTTP/1.1 200 OK
HTTP/1.1 502 Bad Gateway
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 502 Bad Gateway
HTTP/1.1 200 OK
我們設置的超時時間為9s,我們是每3s請求一次。
我們可以看到后端一臺服務器掛了后,請求沒有直接轉發給正常的服務器,
而是直接返回了502。嘗試三次后,等待9s,才開始再次嘗試(最后一個502)。
要注意,第二行的200響應,并不是客戶端第一次的請求的響應碼,而是客戶端第二次新的請求。
將proxy_next_upstream開啟
vim /usr/local/nginx/conf/nginx.conf
upstream web {
server 192.168.2.20 weight=1 max_fails=3 fail_timeout=9s;
#先將2.20這臺nginx關了。
server 192.168.2.30 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
proxy_next_upstream error http_404 http_502;
#proxy_next_upstream off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
[root@bogon nginx]# /usr/local/nginx/sbin/nginx ?-s reload
再次測試訪問驗證
[root@localhost ~]# while ?true;do curl -I 192.168.2.10 ?2>/dev/null|grep HTTP/1.1 ;sleep 3;done
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK可以看到現在沒有502報錯,請求都處理了。因為錯誤的響應碼被proxy_next_upstream 獲取,這次請求
被轉發給下一個正常的服務器了。
所以看到都是200,但是你應該清楚,哪個200是響應的上個服務器沒有處理請求,哪個200是正常的響應。
4.ip_hash
-
通過客戶端ip進行hash,再通過hash值選擇后端server 。
vim /usr/local/nginx/conf/nginx.conf
upstream web {
ip_hash;
server 192.168.2.20 weight=1 max_fails=3 fail_timeout=9s;
server 192.168.2.30 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web;
proxy_next_upstream error http_404 http_502;
#proxy_next_upstream off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
[root@bogon nginx]# /usr/local/nginx/sbin/nginx ?-s reload
訪問驗證:
[root@localhost ~]# while ?true;do curl ?192.168.2.10;sleep 2;donethis is 2.30 pagethis is 2.30 pagethis is 2.30 pagethis is 2.30 pagethis is 2.30 pagethis is 2.30 page
[root@localhost ~]# curl 192.168.2.20
this is 2.20 page
#可以看到2.20的服務是正常的,但是卻不轉發給2.20了,請求固定在了2.30的服務器上。
-
在使用負載均衡的時候會遇到會話保持的問題,常用的方法有:
-
ip hash,根據客戶端的IP,將請求分配到不同的服務器上;
-
cookie,服務器給客戶端下發一個cookie,具有特定cookie的請求會分配給它的發布者。
4.url_hash
vim /usr/local/nginx/conf/nginx.conf
upstream web {
hash $request_uri consistent;
server 192.168.2.20;
server 192.168.2.30;
}
[root@bogon nginx]# /usr/local/nginx/sbin/nginx ?-s reload
根據響應時間均衡
# 下載模塊:
wget https://github.com/gnosek/nginx-upstream-fair/archive/master.zip
# 解壓:
unzip master.zip
# 修改源碼bug:
sed -i 's/default_port/no_port/g' ngx_http_upstream_fair_module.c
# 預編譯:
./configure --prefix=/usr/local/nginx --add-module=../echo-nginx-module --withhttp_stub_status_module --add-module=../nginx-upstream-fair-master
# 編譯/安裝:
make && make install
# 配置:
upstream web {
fair;
server 192.168.2.20 weight=1 max_fails=3 fail_timeout=9s;
server 192.168.2.30 weight=1;
}
備用服務器
upstream web {
server 192.168.2.20 weight=1 max_fails=3 fail_timeout=9s;
server 192.168.2.30 weight=1 backup;
}
# 2.30的服務器做備用服務器,只有在2.30得服務器不能提供服務時,才會自動頂上,否則,默認是不提供服務的。
Nginx實現四層負載均衡
前端服務器:192.168.2.10
后端服務器1:192.168.2.20
后端服務器2:192.168.2.30
-
前端服務器主要配置stream和upstream,注意該模塊需要在預編譯時指定,沒有被默認編譯進nginx。
#預編譯:
./configure --prefix=/usr/local/nginx --add-module=../echo-nginx-module --withhttp_stub_status_module --with-stream
# 編譯/安裝:
make && make install
make ?upgrade
# 在main全局配置stream:
events {
worker_connections 1024;
}
stream {
upstream web {
# 必須要指定ip加port
server 192.168.2.20:80;
server 192.168.2.30:80;
}
server {
listen 80;
# 連接上游服務器超時間,超過則選擇另外一個服務器
proxy_connect_timeout 3s;
# tcp連接閑置時間,超過則關閉
proxy_timeout 10s;
proxy_pass web;
}
log_format proxy '$remote_addr $remote_port $protocol $status
[$time_iso8601] '
'"$upstream_addr" "$upstream_bytes_sent"
"$upstream_connect_time"' ;
access_log /usr/local/nginx/logs/proxy.log proxy;
}
后端服務器測試頁面配置
在后端服務器192.168.2.20配置如下(配置文件不需要修改即可)
vim /usr/local/nginx/html/index.html
this is 2.20 page
在后端服務器192.168.2.30配置如下(配置文件不需要修改即可)
vim /usr/local/nginx/html/index.html
this is 2.30 page
訪問前端服務器IP測試
- 在后端2.30上訪問前端IP
[root@localhost ~]# curl 192.168.2.10
this is 2.20 page
- 查看后端2.20日志
[root@bogon nginx]# tail -1 /usr/local/nginx/logs/host.access.log
192.168.2.10 - - [26/Apr/2020:03:16:37 +0800] "GET / HTTP/1.1" 200 18 "-" "curl/7.29.0" "-"
-查看前端2.10日志
[root@bogon nginx]# tail -1 ?/usr/local/nginx/logs/proxy.log
192.168.2.30 45420 TCP 200 [2020-04-25T19:23:35+08:00] "192.168.2.20:80" "76""0.001"
端口轉發
#在前端2.10配置:
[root@bogon nginx]# vim conf/nginx.conf
events {worker_connections ?1024;
}
stream ?{upstream ?web ? {server ?192.168.2.20:22;
# ? ? ? ? ? ? ? server ?192.168.2.30:80;
}server ?{listen ?6666;proxy_connect_timeout ?3s;proxy_timeout ? 10s;proxy_pass ? web;
}log_format proxy '$remote_addr $remote_port $protocol $status [$time_iso8601] ' '"$upstream_addr" "$upstream_bytes_sent""$upstream_connect_time"' ;
access_log /usr/local/nginx/logs/proxy.log proxy;
}
[root@bogon nginx]# /usr/local/nginx/sbin/nginx ?-s reload
#在另外一臺服務器訪問:
[root@localhost ~]# ssh 192.168.2.10 -p 6666
root@192.168.2.10's password:
Last login: Sun Apr 26 03:31:45 2020 from www.ys.com
#可以看到已經登上2.20服務器上了
[root@bogon ~]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:2c:72:99 brd ff:ff:ff:ff:ff:ffinet 192.168.2.20/24 brd 192.168.2.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 fe80::7e7a:cabd:3b11:a545/64 scope link noprefixroute valid_lft forever preferred_lft forever