nginx 簡(jiǎn)單實(shí)踐:負(fù)載均衡【nginx 實(shí)踐系列之四】
〇、前言
本文為 nginx 簡(jiǎn)單實(shí)踐系列文章之一,主要簡(jiǎn)單實(shí)踐了負(fù)載均衡,僅供參考。
關(guān)于 Nginx 基礎(chǔ),以及安裝和配置詳解,可以參考博主過(guò)往文章:
http://www.rzrgm.cn/hnzhengfy/p/Nginx.html
注意:可以使用測(cè)試域名,但前提是要修改 hosts 文件。
路徑和重啟:Linux(/etc/hosts)(重啟命令:/etc/init.d/network restart);Windows(C:\Windows\System32\drivers\etc\hosts)。
例如:192.168.1.1 www.testczzj.com
一、關(guān)于負(fù)載均衡
1.1 簡(jiǎn)介
負(fù)載均衡(Load Balance,簡(jiǎn)稱 LB)是高并發(fā)、高可用系統(tǒng)必不可少的關(guān)鍵組件,目標(biāo)是盡力將網(wǎng)絡(luò)流量平均分發(fā)到多個(gè)服務(wù)器上,以提高系統(tǒng)整體的響應(yīng)速度和可用性。
主要的作用:
- 高并發(fā):負(fù)載均衡通過(guò)算法調(diào)整負(fù)載,盡力均勻的分配應(yīng)用集群中各節(jié)點(diǎn)的工作量,以此提高應(yīng)用集群的并發(fā)處理能力(吞吐量)。
- 伸縮性:添加或減少服務(wù)器數(shù)量,然后由負(fù)載均衡進(jìn)行分發(fā)控制。這使得應(yīng)用集群具備伸縮性。
- 高可用:負(fù)載均衡器可以監(jiān)控候選服務(wù)器,當(dāng)服務(wù)器不可用時(shí),自動(dòng)跳過(guò),將請(qǐng)求分發(fā)給可用的服務(wù)器。這使得應(yīng)用集群具備高可用的特性。
- 安全防護(hù):有些負(fù)載均衡軟件或硬件提供了安全性功能,如:黑白名單處理、防火墻,防 DDos 攻擊等。
1.2 載體維度分類:硬件
硬件負(fù)載均衡,一般是在定制處理器上運(yùn)行的,獨(dú)立負(fù)載均衡服務(wù)器,價(jià)格昂貴。
硬件負(fù)載均衡的主流產(chǎn)品有:F5 和 A10。F5 擁有更廣泛的附加功能和服務(wù),而 A10 則在某些特定領(lǐng)域如 IPv6 轉(zhuǎn)換或 SSL 檢查方面表現(xiàn)出色。
優(yōu)點(diǎn):
- 功能強(qiáng)大:支持全局負(fù)載均衡并提供較全面的、復(fù)雜的負(fù)載均衡算法。
- 性能強(qiáng)悍:硬件負(fù)載均衡由于是在專用處理器上運(yùn)行,因此吞吐量大,可支持單機(jī)百萬(wàn)以上的并發(fā)。
- 安全性高:往往具備防火墻,防 DDos 攻擊等安全功能。
缺點(diǎn):
- 成本昂貴:購(gòu)買和維護(hù)硬件負(fù)載均衡的成本都很高。
- 擴(kuò)展性差:當(dāng)訪問(wèn)量突增時(shí),超過(guò)限度不能動(dòng)態(tài)擴(kuò)容。
1.3 載體維度分類:軟件
軟件負(fù)載均衡是指,使用軟件工具或解決方案來(lái)分配網(wǎng)絡(luò)流量或計(jì)算任務(wù)到多個(gè)服務(wù)器,以實(shí)現(xiàn)資源的有效利用、提高系統(tǒng)性能和增強(qiáng)服務(wù)的可用性。
與硬件負(fù)載均衡器相比,軟件負(fù)載均衡更加靈活、成本效益更高,并且可以輕松部署在標(biāo)準(zhǔn)的服務(wù)器硬件上。
軟件負(fù)載均衡通常位于客戶端和服務(wù)器之間,它接收來(lái)自客戶端的請(qǐng)求,并根據(jù)預(yù)先設(shè)定的算法決定將這些請(qǐng)求轉(zhuǎn)發(fā)到哪一個(gè)后端服務(wù)器。通過(guò)這種方式,它可以確保工作負(fù)載均勻分布,避免任何單一服務(wù)器過(guò)載。
優(yōu)點(diǎn):
- 擴(kuò)展性好:適應(yīng)動(dòng)態(tài)變化,可以通過(guò)添加軟件負(fù)載均衡實(shí)例,動(dòng)態(tài)擴(kuò)展到超出初始容量的能力。
- 成本低廉:軟件負(fù)載均衡可以在任何標(biāo)準(zhǔn)物理設(shè)備上運(yùn)行,降低了購(gòu)買和運(yùn)維的成本。
缺點(diǎn):
- 性能略差:相比于硬件負(fù)載均衡,軟件負(fù)載均衡的性能要略低一些。
1.4 網(wǎng)絡(luò)通信分類:七層負(fù)載均衡
1.4.1 DNS 負(fù)載均衡
DNS(Domain Name System 域名解析系統(tǒng))負(fù)載均衡一般用于互聯(lián)網(wǎng)公司,復(fù)雜的業(yè)務(wù)系統(tǒng)不適合使用。大型網(wǎng)站一般使用 DNS 負(fù)載均衡作為第一級(jí)負(fù)載均衡手段,然后在內(nèi)部使用其它方式做第二級(jí)負(fù)載均衡。
什么是 DNS?它是 OSI 第七層網(wǎng)絡(luò)協(xié)議。DNS 被設(shè)計(jì)為一個(gè)樹(shù)形結(jié)構(gòu)的分布式應(yīng)用,自上而下依次為:權(quán)威服務(wù)器,頂級(jí)服務(wù)器,根域名服務(wù)器,遞歸服務(wù)器,本地DNS服務(wù)器。
下邊簡(jiǎn)單列舉下:
| DNS服務(wù)器的種類 | ||
| 本地DNS服務(wù)器 (Local DNS Server) |
通常是用戶設(shè)備或網(wǎng)絡(luò)中的默認(rèn) DNS 服務(wù)器,它接收用戶的 DNS 查詢請(qǐng)求。 | 首先檢查自己的緩存中是否已有該域名的對(duì)應(yīng)IP地址。如果有,直接返回結(jié)果;如果沒(méi)有,則向上級(jí) DNS 服務(wù)器發(fā)送查詢請(qǐng)求。 |
| 遞歸域名服務(wù)器 (Recursive DNS Server) |
主要任務(wù)是代表客戶端執(zhí)行完整的解析過(guò)程,從而簡(jiǎn)化了客戶端的工作流程。 | 通過(guò)遞歸方式完成查詢。這意味著如果本地沒(méi)有所需的信息,它會(huì)依次向根域名服務(wù)器、頂級(jí)域名服務(wù)器以及權(quán)威域名服務(wù)器發(fā)起查詢,直到找到目標(biāo)域名對(duì)應(yīng)的 IP 地址。 |
| 根域名服務(wù)器 (Root DNS Server) |
是整個(gè) DNS 系統(tǒng)的最頂層,提供頂級(jí)域名(TLD)服務(wù)器的信息。 | 當(dāng)本地 DNS 服務(wù)器無(wú)法在緩存中找到答案時(shí),它會(huì)向根域名服務(wù)器發(fā)出查詢請(qǐng)求。根域名服務(wù)器不會(huì)直接提供最終的 IP 地址,而是返回負(fù)責(zé)特定頂級(jí)域名(如 .com、.org 等)的頂級(jí)域名服務(wù)器的地址。 |
| 頂級(jí)域名服務(wù)器 (Top-Level Domain DNS Server, TLD Server) |
管理特定頂級(jí)域名下的所有子域名信息。 | 根據(jù)來(lái)自本地 DNS 服務(wù)器的請(qǐng)求,頂級(jí)域名服務(wù)器會(huì)提供負(fù)責(zé)特定二級(jí)域名(例如 example.com 中的 example 部分)的權(quán)威域名服務(wù)器的地址。 |
| 權(quán)威域名服務(wù)器 (Authoritative DNS Server) |
存儲(chǔ)并維護(hù)特定域名的實(shí)際 DNS 記錄,包括 A 記錄(指向IPv4地址)、AAAA 記錄(指向 IPv6 地址)、MX 記錄(郵件服務(wù)器信息)等。 | 這是最后一個(gè)層級(jí)的 DNS 服務(wù)器,它能提供所查詢域名的確切 IP 地址或其他所需信息。一旦本地 DNS 服務(wù)器接收到權(quán)威域名服務(wù)器提供的答案,就會(huì)將該信息返回給客戶端,并且通常會(huì)在本地緩存一段時(shí)間以供后續(xù)查詢使用。 |
DNS 負(fù)載均衡的工作原理就是:基于 DNS 查詢緩存,按照負(fù)載情況返回不同服務(wù)器的 IP 地址。
如下圖,針對(duì)服務(wù)集群中的兩個(gè)服務(wù)地址 127.0.0.1、127.0.0.2,在 DNS 服務(wù)器中都配置為指向域名 www.xxx.com,當(dāng)用戶通過(guò)域名訪問(wèn)時(shí),請(qǐng)求到 DNS 服務(wù)器,然后隨機(jī)返回一個(gè)實(shí)際請(qǐng)求的服務(wù)器 IP 地址。

優(yōu)點(diǎn):
簡(jiǎn)易部署與管理:無(wú)需改變應(yīng)用程序的代碼,僅通過(guò)配置DNS即可實(shí)現(xiàn)負(fù)載分發(fā),簡(jiǎn)化了服務(wù)器集群的管理。
地理分布優(yōu)化:支持基于地理位置的流量分配,能夠?qū)⒂脩粽?qǐng)求定向到距離最近的數(shù)據(jù)中心或服務(wù)器,從而減少延遲,提高訪問(wèn)速度。
擴(kuò)展性強(qiáng):可以輕松地向服務(wù)器池中添加新的服務(wù)器,以應(yīng)對(duì)增加的流量需求,提高了系統(tǒng)的可伸縮性。
成本效益高:通過(guò)更有效的資源利用減少了硬件投資和運(yùn)營(yíng)成本。
缺點(diǎn):
緩存問(wèn)題:由于DNS解析結(jié)果會(huì)被客戶端及中間DNS服務(wù)器緩存,當(dāng)某個(gè)服務(wù)器出現(xiàn)故障時(shí),已緩存該服務(wù)器IP地址的用戶仍然可能被導(dǎo)向至故障服務(wù)器,直到緩存過(guò)期。這可能導(dǎo)致服務(wù)中斷或性能下降。
負(fù)載平衡精度有限:DNS負(fù)載均衡通常基于簡(jiǎn)單的算法(如輪詢)進(jìn)行分配,無(wú)法實(shí)時(shí)感知各服務(wù)器的實(shí)際負(fù)載情況,導(dǎo)致負(fù)載分配不夠精準(zhǔn)。
安全性考慮:盡管DNSSEC等技術(shù)增強(qiáng)了DNS的安全性,但DNS本身仍可能存在被攻擊的風(fēng)險(xiǎn),例如DDoS攻擊,可能會(huì)對(duì)整個(gè)系統(tǒng)造成影響。
不支持會(huì)話持久化:如果應(yīng)用需要保持用戶的會(huì)話狀態(tài),單純的DNS負(fù)載均衡無(wú)法保證用戶在多次請(qǐng)求間總是被導(dǎo)向到同一臺(tái)服務(wù)器,除非結(jié)合其他機(jī)制來(lái)實(shí)現(xiàn)。
雖然 DNS 負(fù)載均衡提供了一種簡(jiǎn)單且有效的方法來(lái)分散網(wǎng)絡(luò)流量,但它也存在一定的局限性。因此,在實(shí)際應(yīng)用中,常常需要結(jié)合使用其他技術(shù)和策略,如健康檢查、自動(dòng)故障轉(zhuǎn)移以及會(huì)話保持機(jī)制等,以克服其固有的不足。
1.4.2 HTTP 負(fù)載均衡
HTTP 負(fù)載均衡是基于 HTTP 重定向?qū)崿F(xiàn)的。HTTP 負(fù)載均衡屬于七層負(fù)載均衡。
HTTP 重定向原理是:根據(jù)用戶的 HTTP 請(qǐng)求計(jì)算出一個(gè)真實(shí)的服務(wù)器地址,將該服務(wù)器地址寫入 HTTP 重定向響應(yīng)中,返回給瀏覽器,由瀏覽器重新進(jìn)行訪問(wèn)。

優(yōu)點(diǎn):
高可用性和可靠性:即使某臺(tái)服務(wù)器發(fā)生故障,負(fù)載均衡器也能自動(dòng)將流量分配到其他健康的服務(wù)器上,從而保證服務(wù)的連續(xù)性。
擴(kuò)展性:可以輕松添加更多的服務(wù)器到池中以應(yīng)對(duì)增加的負(fù)載,提高了系統(tǒng)的可伸縮性。
性能提升:通過(guò)智能地選擇最佳的服務(wù)器來(lái)處理每個(gè)請(qǐng)求,可以減少響應(yīng)時(shí)間和提高用戶體驗(yàn)。
安全性增強(qiáng):負(fù)載均衡器可以充當(dāng)額外的安全層,提供諸如 SSL 終止、DDoS 防護(hù)等功能,保護(hù)后端服務(wù)器免受攻擊。
會(huì)話持久化支持:一些高級(jí)負(fù)載均衡器支持會(huì)話持久化功能,確保用戶在整個(gè)會(huì)話過(guò)程中總是被導(dǎo)向到同一臺(tái)服務(wù)器。
缺點(diǎn):
性能較差:每次訪問(wèn)需要兩次請(qǐng)求服務(wù)器,增加了訪問(wèn)的延遲。
降低搜索排名:使用重定向后,搜索引擎會(huì)視為 SEO 作弊。
復(fù)雜性和成本:實(shí)現(xiàn)和維護(hù) HTTP 負(fù)載均衡需要一定的技術(shù)知識(shí)和投入,包括硬件成本、軟件許可證費(fèi)用以及維護(hù)成本。
單點(diǎn)故障風(fēng)險(xiǎn):如果負(fù)載均衡器本身出現(xiàn)故障,則可能導(dǎo)致整個(gè)系統(tǒng)不可用。雖然可以通過(guò)設(shè)置主備負(fù)載均衡器來(lái)緩解這一問(wèn)題,但這增加了架構(gòu)的復(fù)雜度。
潛在的瓶頸:在高并發(fā)情況下,如果負(fù)載均衡器本身的處理能力不足,可能會(huì)成為系統(tǒng)的瓶頸。
由于其缺點(diǎn)比較明顯,所以這種負(fù)載均衡策略實(shí)際應(yīng)用較少。
1.4.3 反向代理
反向代理(Reverse Proxy)方式是指以 代理服務(wù)器 來(lái)接受網(wǎng)絡(luò)請(qǐng)求,然后 將請(qǐng)求轉(zhuǎn)發(fā)給內(nèi)網(wǎng)中的服務(wù)器,并將從內(nèi)網(wǎng)中的服務(wù)器上得到的結(jié)果返回給網(wǎng)絡(luò)請(qǐng)求的客戶端。反向代理負(fù)載均衡屬于七層負(fù)載均衡。
反向代理服務(wù)的主流產(chǎn)品:Nginx、Apache。
如下圖,看下 Nginx 如何實(shí)現(xiàn)負(fù)載均衡:

首先,在代理服務(wù)器上設(shè)定好負(fù)載均衡規(guī)則。
然后,當(dāng)收到客戶端請(qǐng)求,反向代理服務(wù)器攔截指定的域名或 IP 請(qǐng)求,根據(jù)負(fù)載均衡算法,將請(qǐng)求分發(fā)到候選服務(wù)器上。
其次,如果某臺(tái)候選服務(wù)器宕機(jī),反向代理服務(wù)器會(huì)有容錯(cuò)處理,比如分發(fā)請(qǐng)求失敗 3 次以上,將請(qǐng)求分發(fā)到其他候選服務(wù)器上。
優(yōu)點(diǎn):
多種負(fù)載均衡算法:支持多種負(fù)載均衡算法,以應(yīng)對(duì)不同的場(chǎng)景需求。
可以監(jiān)控服務(wù)器:基于 HTTP 協(xié)議,可以監(jiān)控轉(zhuǎn)發(fā)服務(wù)器的狀態(tài),如:系統(tǒng)負(fù)載、響應(yīng)時(shí)間、是否可用、連接數(shù)、流量等,從而根據(jù)這些數(shù)據(jù)調(diào)整負(fù)載均衡的策略。
缺點(diǎn):
額外的轉(zhuǎn)發(fā)開(kāi)銷:反向代理的轉(zhuǎn)發(fā)操作本身是有性能開(kāi)銷的,可能會(huì)包括創(chuàng)建連接,等待連接響應(yīng),分析響應(yīng)結(jié)果等操作。
增加系統(tǒng)復(fù)雜度:反向代理常用于做分布式應(yīng)用的水平擴(kuò)展,但反向代理服務(wù)存在以下問(wèn)題,為了解決以下問(wèn)題會(huì)給系統(tǒng)整體增加額外的復(fù)雜度和運(yùn)維成本。
反向代理服務(wù)如果自身宕機(jī),就無(wú)法訪問(wèn)站點(diǎn),所以需要有高可用方案,常見(jiàn)的方案有:主備模式(一主一備)、雙主模式(互為主備)。
反向代理服務(wù)自身也存在性能瓶頸,隨著需要轉(zhuǎn)發(fā)的請(qǐng)求量不斷攀升,需要有可擴(kuò)展方案。
1.5 網(wǎng)絡(luò)通信分類:四層負(fù)載均衡
1.5.1 IP 負(fù)載均衡
IP 負(fù)載均衡是在網(wǎng)絡(luò)層通過(guò)修改請(qǐng)求目的地址進(jìn)行負(fù)載均衡。

如上圖,大致流程為:
1. 客戶端請(qǐng)求 192.168.137.10,由負(fù)載均衡服務(wù)器接收到報(bào)文。
2. 負(fù)載均衡服務(wù)器根據(jù)算法選出一個(gè)服務(wù)節(jié)點(diǎn) 192.168.0.1,然后將報(bào)文請(qǐng)求地址改為該節(jié)點(diǎn)的 IP。
3. 真實(shí)服務(wù)節(jié)點(diǎn)收到請(qǐng)求報(bào)文,處理后,返回響應(yīng)數(shù)據(jù)到負(fù)載均衡服務(wù)器。
4. 負(fù)載均衡服務(wù)器將響應(yīng)數(shù)據(jù)的源地址改負(fù)載均衡服務(wù)器地址,返回給客戶端。
IP 負(fù)載均衡在內(nèi)核進(jìn)程完成數(shù)據(jù)分發(fā),較反向代理負(fù)載均衡有更好的從處理性能。但是,由于所有請(qǐng)求響應(yīng)都要經(jīng)過(guò)負(fù)載均衡服務(wù)器,集群的吞吐量受制于負(fù)載均衡服務(wù)器的帶寬。
1.5.2 數(shù)據(jù)鏈路層通過(guò)修改 mac 地址來(lái)實(shí)現(xiàn)負(fù)載均衡
數(shù)據(jù)鏈路層負(fù)載均衡是指,在通信協(xié)議的數(shù)據(jù)鏈路層修改 mac 地址進(jìn)行負(fù)載均衡。

在 Linux 平臺(tái)上最好的鏈路層負(fù)載均衡開(kāi)源產(chǎn)品是 LVS (Linux Virtual Server)。
LVS 是基于 Linux 內(nèi)核中 netfilter 框架實(shí)現(xiàn)的負(fù)載均衡系統(tǒng)。netfilter 是內(nèi)核態(tài)的 Linux 防火墻機(jī)制,可以在數(shù)據(jù)包流經(jīng)過(guò)程中,根據(jù)規(guī)則設(shè)置若干個(gè)關(guān)卡(hook 函數(shù))來(lái)執(zhí)行相關(guān)的操作。
LVS 的工作流程大致如下:
1. 客戶端請(qǐng)求:當(dāng)客戶端發(fā)起一個(gè)請(qǐng)求到目標(biāo)服務(wù)時(shí),首先會(huì)到達(dá) LVS 配置的虛擬 IP 地址(VIP),這個(gè) VIP 對(duì)外代表了一個(gè)或多個(gè)實(shí)際提供服務(wù)的服務(wù)器集群。
2. 流量分發(fā)的四種模式:
1)IPVS 模塊:LVS 的核心是運(yùn)行在 Linux 內(nèi)核中的 IPVS(IP Virtual Server)模塊,它負(fù)責(zé)根據(jù)預(yù)設(shè)的負(fù)載均衡算法(如輪詢、最少連接數(shù)等)將收到的請(qǐng)求分發(fā)給后端的真實(shí)服務(wù)器(Real Server, RS)。
2)直接路由模式(DR:Direct Routing):在此模式下,LVS 簡(jiǎn)單地重寫數(shù)據(jù)包的目標(biāo) MAC 地址為選定真實(shí)服務(wù)器的 MAC 地址,并將數(shù)據(jù)包發(fā)送回交換機(jī),由交換機(jī)轉(zhuǎn)發(fā)給真實(shí)服務(wù)器。這種方式不需要修改數(shù)據(jù)包的 IP 頭部信息,因此效率很高。
3)NAT 模式(Network Address Translation):在這種模式下,LVS 不僅改變目標(biāo) MAC 地址,還會(huì)修改目標(biāo) IP 地址為目標(biāo)服務(wù)器的實(shí)際 IP 地址,并且處理來(lái)自真實(shí)服務(wù)器的響應(yīng),將其源 IP 地址改為 VIP 后再返回給客戶端。此方法適用于真實(shí)服務(wù)器位于私有網(wǎng)絡(luò)的情況。
4)隧道模式(Tunnel:Tunneling):通過(guò)將原始請(qǐng)求封裝在 IP 隧道中發(fā)送給真實(shí)服務(wù)器,允許真實(shí)服務(wù)器位于不同的物理位置,只要它們能夠與 LVS 通信即可。
3. 真實(shí)服務(wù)器處理請(qǐng)求:被選中的真實(shí)服務(wù)器接收到請(qǐng)求后進(jìn)行處理,并直接將響應(yīng)發(fā)送回客戶端(在直接路由和隧道模式下),或者通過(guò) LVS 返回給客戶端(在 NAT 模式下)。
4. 健康檢查:LVS通常結(jié)合外部工具(如keepalived)來(lái)進(jìn)行真實(shí)服務(wù)器的健康檢查。如果某個(gè)真實(shí)服務(wù)器不可用,LVS將停止向其分配新的請(qǐng)求,直到它恢復(fù)正常。
1.6 負(fù)載均衡算法簡(jiǎn)介
負(fù)載均衡器的實(shí)現(xiàn)可以分為兩個(gè)部分:首先通過(guò)負(fù)載均衡算法在候選服務(wù)器列表選出一個(gè)服務(wù)器;然后,將請(qǐng)求數(shù)據(jù)發(fā)送到該服務(wù)器上。
負(fù)載均衡算法是負(fù)載均衡服務(wù)核心中的核心。
負(fù)載均衡產(chǎn)品多種多樣,但是各種負(fù)載均衡算法原理是共性的。負(fù)載均衡算法有很多種,分別適用于不同的應(yīng)用場(chǎng)景,常用的有:輪詢、隨機(jī)、最小活躍數(shù)、源地址哈希、一致性哈希等等,下文將逐個(gè)簡(jiǎn)單介紹。
- 隨機(jī)算法(Random)
隨機(jī)算法將請(qǐng)求隨機(jī)分發(fā)到候選服務(wù)器。更適合服務(wù)器硬件相同的場(chǎng)景。當(dāng)調(diào)用量較小的時(shí)候,可能負(fù)載并不均勻,調(diào)用量越大,負(fù)載越均衡。
- 加權(quán)隨機(jī)算法(Weighted Random)
加權(quán)隨機(jī)算法在隨機(jī)算法的基礎(chǔ)上,按照概率調(diào)整權(quán)重,進(jìn)行負(fù)載分配。
- 輪詢算法(Round Robin)
輪詢算法的策略是:將請(qǐng)求依次分發(fā)到候選服務(wù)器。
該算法適合場(chǎng)景:各服務(wù)器處理能力相近,且每個(gè)事務(wù)工作量差異不大。如果存在較大差異,那么處理較慢的服務(wù)器就可能會(huì)積壓請(qǐng)求,最終無(wú)法承擔(dān)過(guò)大的負(fù)載。
- 加權(quán)輪詢算法(Weighted Round Robbin)
加權(quán)輪詢算法在輪詢算法的基礎(chǔ)上,增加了權(quán)重屬性來(lái)調(diào)節(jié)轉(zhuǎn)發(fā)服務(wù)器的請(qǐng)求數(shù)目。
性能高、處理速度快的節(jié)點(diǎn)應(yīng)該設(shè)置更高的權(quán)重,使得分發(fā)時(shí)優(yōu)先將請(qǐng)求分發(fā)到權(quán)重較高的節(jié)點(diǎn)上。
- 最少連接數(shù)(Least Connections)
最少連接數(shù)算法將請(qǐng)求分發(fā)到連接數(shù)/請(qǐng)求數(shù)最少的候選服務(wù)器(目前處理請(qǐng)求最少的服務(wù)器)。
它是根據(jù)候選服務(wù)器當(dāng)前的請(qǐng)求連接數(shù),動(dòng)態(tài)分配。
適用于對(duì)系統(tǒng)負(fù)載較為敏感或請(qǐng)求連接時(shí)長(zhǎng)相差較大的場(chǎng)景。
由于每個(gè)請(qǐng)求的連接時(shí)長(zhǎng)不一樣,如果采用簡(jiǎn)單的輪循或隨機(jī)算法,都可能出現(xiàn)某些服務(wù)器當(dāng)前連接數(shù)過(guò)大,而另一些服務(wù)器的連接過(guò)小的情況,這就造成了負(fù)載并非真正均衡。雖然,輪詢或隨機(jī)算法都可以通過(guò)加權(quán)重屬性的方式進(jìn)行負(fù)載調(diào)整,但加權(quán)方式難以應(yīng)對(duì)動(dòng)態(tài)變化。
- 加權(quán)最少連接數(shù)(Weighted Least Connections)
結(jié)合了加權(quán)輪詢和最少連接數(shù)的優(yōu)點(diǎn),在選擇服務(wù)器時(shí)既考慮了服務(wù)器的當(dāng)前連接數(shù)也考慮了其權(quán)重,使得更強(qiáng)大的服務(wù)器可以處理更多的請(qǐng)求。
- 源 IP 地址哈希(Source IP Hash)
根據(jù)客戶端 IP 地址計(jì)算哈希值,并根據(jù)哈希結(jié)果選擇服務(wù)器。
這種方式可以確保來(lái)自同一客戶端的請(qǐng)求總是被發(fā)送到相同的服務(wù)器上,有助于保持會(huì)話狀態(tài)的一致性,用來(lái)實(shí)現(xiàn)會(huì)話粘滯(Sticky Session)。
- 一致性哈希(Consistent Hash)
一致性哈希算法的目標(biāo)是:相同的請(qǐng)求盡可能落到同一個(gè)服務(wù)器上。
一致性哈希可以很好的解決穩(wěn)定性問(wèn)題,可以將所有的存儲(chǔ)節(jié)點(diǎn)排列在首尾相接的 Hash 環(huán)上,每個(gè) key 在計(jì)算 Hash 后會(huì)順時(shí)針找到臨接的存儲(chǔ)節(jié)點(diǎn)存放。而當(dāng)有節(jié)點(diǎn)加入或退出時(shí),僅影響該節(jié)點(diǎn)在 Hash 環(huán)上順時(shí)針相鄰的后續(xù)節(jié)點(diǎn)。
‘相同的請(qǐng)求’是指:一般在使用一致性哈希時(shí),需要指定一個(gè) key 用于 hash 計(jì)算,可能是:用戶 ID、請(qǐng)求方 IP、請(qǐng)求服務(wù)名稱、參數(shù)列表構(gòu)成的串等等。
‘盡可能’是指:服務(wù)器可能發(fā)生上下線,少數(shù)服務(wù)器的變化不應(yīng)該影響大多數(shù)的請(qǐng)求。當(dāng)某臺(tái)候選服務(wù)器宕機(jī)時(shí),原本發(fā)往該服務(wù)器的請(qǐng)求,會(huì)基于虛擬節(jié)點(diǎn),平攤到其它候選服務(wù)器,不會(huì)引起劇烈變動(dòng)。
優(yōu)點(diǎn):加入和刪除節(jié)點(diǎn)只影響哈希環(huán)中順時(shí)針?lè)较虻南噜彽墓?jié)點(diǎn),對(duì)其他節(jié)點(diǎn)無(wú)影響。
缺點(diǎn):加減節(jié)點(diǎn)會(huì)造成哈希環(huán)中部分?jǐn)?shù)據(jù)無(wú)法命中。當(dāng)使用少量節(jié)點(diǎn)時(shí),節(jié)點(diǎn)變化將大范圍影響哈希環(huán)中數(shù)據(jù)映射,不適合少量數(shù)據(jù)節(jié)點(diǎn)的分布式方案。普通的一致性哈希分區(qū)在增減節(jié)點(diǎn)時(shí)需要增加一倍或減去一半節(jié)點(diǎn)才能保證數(shù)據(jù)和負(fù)載的均衡。
參考:https://blog.csdn.net/wanghangzhen/article/details/118554304
二、Nginx 的負(fù)載均衡簡(jiǎn)單測(cè)試
2.1 輪詢【默認(rèn)方式】
輪詢算法是默認(rèn)的一種方式。
當(dāng) nginx 接收到請(qǐng)求后,逐一分配到所配置的服務(wù)列表進(jìn)行訪問(wèn)并返回。
當(dāng)某個(gè)服務(wù)異常時(shí),自動(dòng)跳過(guò),并不會(huì)導(dǎo)致請(qǐng)求失敗。
實(shí)例配置如下:
# 反向代理配置
upstream server_czzj {
server www.testczzj.com:5001;
server www.testczzj.com:5021;
server www.testczzj.com:5031;
}
server {
listen 8888;
server_name www.testczzj.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
index index.html index.htm;
proxy_pass http://server_czzj; # 指定反向代理服務(wù)器列表
}
}
如下圖,刷新同一地址,請(qǐng)求的服務(wù)不同:

2.2 weight【權(quán)重】
權(quán)重用于調(diào)整不同服務(wù)器之間請(qǐng)求分配比例。
它允許管理員根據(jù)每臺(tái)服務(wù)器的實(shí)際處理能力和性能,來(lái)手動(dòng)控制流量分配,從而優(yōu)化資源利用和提高系統(tǒng)的整體效率。
通過(guò)合理設(shè)置權(quán)重,可以根據(jù)實(shí)際需求動(dòng)態(tài)調(diào)整服務(wù)器之間的負(fù)載分布,不僅提高了系統(tǒng)的靈活性和可靠性,還能更好地應(yīng)對(duì)突發(fā)流量和資源限制等問(wèn)題。
配置示例:
# 反向代理配置
upstream server_czzj {
server www.testczzj.com:5001 weight=1; # 默認(rèn)為 1,可不配置
server www.testczzj.com:5021 weight=3;
server www.testczzj.com:5031 weight=6;
}
解釋:例如示例中的權(quán)重總量為 10,那么如果 nginx 接到十個(gè)請(qǐng)求,那么三個(gè)服務(wù)就分別接到 1、3、6 個(gè)請(qǐng)求。但是首次請(qǐng)求進(jìn)入那個(gè)服務(wù)是不固定的,權(quán)重為 6 的服務(wù)概率最大。
實(shí)際效果就類似于:(但是順序是隨機(jī)的)
# 反向代理配置
upstream server_czzj {
server www.testczzj.com:5001;
server www.testczzj.com:5021;
server www.testczzj.com:5021;
server www.testczzj.com:5021;
server www.testczzj.com:5031;
server www.testczzj.com:5031;
server www.testczzj.com:5031;
server www.testczzj.com:5031;
server www.testczzj.com:5031;
server www.testczzj.com:5031;
}
此策略比較適合服務(wù)器的硬件配置差別比較大的情況。
2.3 ip_hash【基于客戶端 IP 來(lái)分配】
指定負(fù)載均衡器按照基于客戶端 IP 的分配方式,這個(gè)方法確保了相同的客戶端的請(qǐng)求一直發(fā)送到相同的服務(wù)器,以保證 session 會(huì)話。這樣每個(gè)訪客都固定訪問(wèn)一個(gè)后端服務(wù)器,可以解決 session 不能跨服務(wù)器的問(wèn)題。
Nginx 使用的 Jenkins hash 函數(shù)對(duì)輸入數(shù)據(jù)(如 IP 地址)進(jìn)行哈希計(jì)算,生成一個(gè) 32 位無(wú)符號(hào)整數(shù)作為哈希值。對(duì)于 IP 地址 127.0.0.1,經(jīng)過(guò) Jenkins hash 計(jì)算后,得到的哈希值為 879045407。
如果有三個(gè)服務(wù)且權(quán)重均為1,則通過(guò)哈希值對(duì)3取余,得到的 0、1、2 分別對(duì)應(yīng)三個(gè)服務(wù)。
如果有多個(gè)權(quán)重不同的服務(wù),則通過(guò)對(duì)權(quán)重總和的值取余,得到序號(hào),對(duì)應(yīng)到不同的服務(wù)上。
實(shí)例配置:
# 反向代理配置
upstream server_czzj {
ip_hash; # 保證每個(gè)客戶端訪問(wèn)同一個(gè)后端服務(wù)
server www.testczzj.com:5001;
server www.testczzj.com:5021;
server www.testczzj.com:5031;
}
注意:在 nginx 版本 1.3.1 之前,不能在 ip_hash 中使用權(quán)重(weight)。
ip_hash 不能與 backup(配置備用服務(wù))同時(shí)使用。
此策略適合有狀態(tài)服務(wù),比如 session。
當(dāng)有服務(wù)器需要剔除,必須手動(dòng)進(jìn)行停服操作。
2.4 least_conn【最少連接】
把請(qǐng)求轉(zhuǎn)發(fā)給連接數(shù)較少的后端服務(wù)。
輪詢算法是把請(qǐng)求平均的轉(zhuǎn)發(fā)給各個(gè)后端,使它們的負(fù)載大致相同;但是,有些請(qǐng)求占用的時(shí)間很長(zhǎng),會(huì)導(dǎo)致其所在的后端負(fù)載較高。這種情況下,least_conn 這種方式就可以達(dá)到更好的負(fù)載均衡效果。
# 反向代理配置
upstream server_czzj {
least_conn; # 把新的請(qǐng)求,轉(zhuǎn)發(fā)到當(dāng)前連接數(shù)最少的服務(wù)
server www.testczzj.com:5001;
server www.testczzj.com:5021;
server www.testczzj.com:5031;
}
此負(fù)載均衡策略適合請(qǐng)求處理時(shí)間長(zhǎng)短不一造成服務(wù)器過(guò)載的情況。
2.5 第三方策略:fair【按照最短響應(yīng)時(shí)間分配請(qǐng)求】
此方式需要單獨(dú)額外的配置,不能直接在 upstream 模塊添加關(guān)鍵字 fair。
大概的思路就是,下載補(bǔ)充包,通過(guò) ./configure 命令,將模塊添加到已安裝的 nginx,重啟下服務(wù)就可以使用關(guān)鍵字 fair 了。
2.5.1 配置步驟和示例
1)先下載第三方包:https://github.com/gnosek/nginx-upstream-fair
文件很簡(jiǎn)單,如下圖:

需要將此文件夾放到 linux 系統(tǒng)中,本示例復(fù)制到路徑:/usr/local/nginx-upstream-fair-master。
2)進(jìn)入 nginx 源文件所在的文件夾(即 nginx 安裝包解壓后的文件夾),本示例的是:/usr/local/nginx-1.20.0。
# 下載 nginx 包并解壓
wget http://nginx.org/download/nginx-1.20.0.tar.gz
tar -zxf nginx-1.20.1.tar.gz && cd nginx-1.20.0/
# 其他一些可能用到的依賴包(按需安裝)
yum -y install gcc gcc-c++ openssl openssl-devel zlib zlib-devel pcre pcre-devel make cmake gperftools perl-devel gd-devel libxml2 libxml2-dev libxslt-devel redhat-rpm-config.noarch
注意:如果源文件找不到了,需要重新下載一個(gè)相同版本安裝包使用。
3)執(zhí)行命令添加模塊:
# 手動(dòng)添加模塊
./configure --add-module=/usr/local/nginx-upstream-fair-master
# 重新進(jìn)行編譯
[root@www nginx-1.20.0]# make
# 添加成功,注意 configure arguments 配置:
[root@www sbin]# nginx -V
nginx version: nginx/1.20.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
configure arguments: --add-module=/usr/local/nginx-upstream-fair-master
4)然后先停止 nginx 服務(wù),再將 nginx 進(jìn)行復(fù)制:
# 先停止 nginx 服務(wù)
[root@www sbin]# ./nginx -s stop
# 復(fù)制 nginx
[root@www nginx-1.20.0]# cp -rp objs/nginx /usr/local/nginx/sbin/nginx
cp: overwrite ‘/usr/local/nginx/sbin/nginx’? yes
[root@www nginx-1.20.0]#
最后,修改 nginx.conf 配置文件,開(kāi)啟服務(wù)測(cè)試一下。
配置示例:
# 反向代理配置
upstream server_czzj {
fair; # 按照最短響應(yīng)時(shí)間分配請(qǐng)求
server www.testczzj.com:5001;
server www.testczzj.com:5021;
server www.testczzj.com:5031;
}
2.5.2 make 執(zhí)行時(shí)報(bào)錯(cuò):‘ngx_http_upstream_srv_conf_t’ has no member named ‘default_port’
ngx_http_upstream_srv_conf_t’沒(méi)有名為‘default_port’的成員。
# 具體提示:
/usr/local/nginx-upstream-fair-master/ngx_http_upstream_fair_module.c: In function ‘ngx_http_upstream_init_fair_rr’:
/usr/local/nginx-upstream-fair-master/ngx_http_upstream_fair_module.c:543:28: error: ‘ngx_http_upstream_srv_conf_t’ has no member named ‘default_port’
if (us->port == 0 && us->default_port == 0) {
^
/usr/local/nginx-upstream-fair-master/ngx_http_upstream_fair_module.c:553:51: error: ‘ngx_http_upstream_srv_conf_t’ has no member named ‘default_port’
u.port = (in_port_t) (us->port ? us->port : us->default_port);
# 解決,執(zhí)行如下命令即可:
# Linux:
sed -i 's/default_port/no_port/g' /usr/local/nginx-upstream-fair-master/ngx_http_upstream_fair_module.c
# macOs:
sed -i '' 's/default_port/no_port/g' /file/ngx_http_upstream_fair_module.c
參考:https://blog.csdn.net/weixin_46152207/article/details/121786162
2.6 第三方策略:url_hash【按訪問(wèn)url的hash結(jié)果來(lái)分配請(qǐng)求】
此方式需要單獨(dú)額外的配置,不能直接在 upstream 模塊添加關(guān)鍵字 url_hash。
大概的思路就是,下載補(bǔ)充包,通過(guò) ./configure 命令,將模塊添加到已安裝的 nginx,重啟下服務(wù)就可以使用關(guān)鍵字 url_hash 了。
1)先下載第三方包:https://github.com/evanmiller/nginx_upstream_hash
文件很簡(jiǎn)單,如下圖:

需要將此文件夾放到 linux 系統(tǒng)中,本示例復(fù)制到路徑:/usr/local/nginx_upstream_hash-master。
2)進(jìn)入 nginx 源文件所在的文件夾(即 nginx 安裝包解壓后的文件夾),本示例的是:/usr/local/nginx-1.20.0。
注意:如果源文件找不到了,需要重新下載一個(gè)相同版本安裝包使用。
# 下載 nginx 包并解壓
wget http://nginx.org/download/nginx-1.20.0.tar.gz
tar -zxf nginx-1.20.1.tar.gz && cd nginx-1.20.0/
# 其他一些可能用到的依賴包(按需安裝)
yum -y install gcc gcc-c++ openssl openssl-devel zlib zlib-devel pcre pcre-devel make cmake gperftools perl-devel gd-devel libxml2 libxml2-dev libxslt-devel redhat-rpm-config.noarch
3)執(zhí)行命令添加模塊:
# 手動(dòng)添加模塊
[root@www nginx-1.20.0]# ./configure --add-module=/usr/local/nginx_upstream_hash-master
# 重新進(jìn)行編譯
[root@www nginx-1.20.0]# make
# 添加成功,查看配置,注意 configure arguments 配置:
[root@www nginx-1.20.0]# nginx -V
nginx version: nginx/1.20.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
configure arguments: --add-module=/usr/local/nginx_upstream_hash-master
4)然后先停止 nginx 服務(wù),再將 nginx 進(jìn)行復(fù)制:
# 先停止 nginx 服務(wù)
[root@www sbin]# ./nginx -s stop
# 復(fù)制 nginx
[root@www nginx-1.20.0]# cp -rp objs/nginx /usr/local/nginx/sbin/nginx
cp: overwrite ‘/usr/local/nginx/sbin/nginx’? yes
[root@www nginx-1.20.0]#
最后,修改 nginx.conf 配置文件,開(kāi)啟服務(wù)測(cè)試一下。
配置示例:
# 反向代理配置
upstream server_czzj {
hash $request_uri; # 相同的 url 定向到同一后端服務(wù)器
# hash $remote_addr; # 也可根據(jù)客戶端 IP 映射
# hash $args; # 也可根據(jù)客戶端攜帶的參數(shù)進(jìn)行映射
server www.testczzj.com:5001;
server www.testczzj.com:5021;
server www.testczzj.com:5031;
}
配置完成后就可以實(shí)現(xiàn),相同的 url 請(qǐng)求到同一個(gè)服務(wù)。
另外,當(dāng)某一個(gè)服務(wù)異常停止后,原來(lái)通過(guò) hash 對(duì)應(yīng)到此服務(wù)的請(qǐng)求,會(huì)自動(dòng)對(duì)應(yīng)到其他服務(wù),并不會(huì)造成請(qǐng)求失敗。
2.7 第三方策略:consistent_hash【采用一致性哈希算法結(jié)果來(lái)分配請(qǐng)求】
此方式需要單獨(dú)額外的配置,不能直接在 upstream 模塊添加關(guān)鍵字 consistent_hash。
大概的思路就是,下載補(bǔ)充包,通過(guò) ./configure 命令,將模塊添加到已安裝的 nginx,重啟下服務(wù)就可以使用關(guān)鍵字 consistent_hash了。
1)先下載第三方包:https://github.com/replay/ngx_http_consistent_hash
文件很簡(jiǎn)單,如下圖:

需要將此文件夾放到 linux 系統(tǒng)中,本示例復(fù)制到路徑:/usr/local/ngx_http_consistent_hash-master。
2)進(jìn)入 nginx 源文件所在的文件夾(即 nginx 安裝包解壓后的文件夾),本示例的是:/usr/local/nginx-1.20.0。
注意:如果源文件找不到了,需要重新下載一個(gè)相同版本安裝包使用。
# 下載 nginx 包并解壓
wget http://nginx.org/download/nginx-1.20.0.tar.gz
tar -zxf nginx-1.20.1.tar.gz && cd nginx-1.20.0/
# 其他一些可能用到的依賴包(按需安裝)
yum -y install gcc gcc-c++ openssl openssl-devel zlib zlib-devel pcre pcre-devel make cmake gperftools perl-devel gd-devel libxml2 libxml2-dev libxslt-devel redhat-rpm-config.noarch
3)執(zhí)行命令添加模塊:
# 手動(dòng)添加模塊
./configure --add-module=/usr/local/ngx_http_consistent_hash-master
# 重新進(jìn)行編譯
[root@www nginx-1.20.0]# make
# 添加成功,查看配置,注意 configure arguments 配置:
[root@www nginx-1.20.0]# nginx -V
nginx version: nginx/1.20.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
configure arguments: --add-module=/usr/local/ngx_http_consistent_hash-master
4)然后先停止 nginx 服務(wù),再將 nginx 進(jìn)行復(fù)制:
# 先停止 nginx 服務(wù)
[root@www sbin]# ./nginx -s stop
# 復(fù)制 nginx
[root@www nginx-1.20.0]# cp -rp objs/nginx /usr/local/nginx/sbin/nginx
cp: overwrite ‘/usr/local/nginx/sbin/nginx’? yes
[root@www nginx-1.20.0]#
最后,修改 nginx.conf 配置文件,開(kāi)啟服務(wù)測(cè)試一下。
配置示例:
# 反向代理配置
upstream server_czzj {
consistent_hash $request_uri; # 一致性哈希算法
# consistent_hash $remote_addr; # 也可根據(jù)客戶端 IP 映射
# consistent_hash $args; # 也可根據(jù)客戶端攜帶的參數(shù)進(jìn)行映射
server www.testczzj.com:5001;
server www.testczzj.com:5021;
server www.testczzj.com:5031;
}
參考:http://www.rzrgm.cn/1214804270hacker/p/9325150.html
https://blog.csdn.net/zpf1813763637/article/details/109455451
本文來(lái)自博客園,作者:橙子家,歡迎微信掃碼關(guān)注博主【橙子家czzj】,有任何疑問(wèn)歡迎溝通,共同成長(zhǎng)!
轉(zhuǎn)載本文請(qǐng)注明原文鏈接:http://www.rzrgm.cn/hnzhengfy/p/18719503/Nginx_Practical4

浙公網(wǎng)安備 33010602011771號(hào)