我們都知道,Nginx支持負載均衡,可以很方便的幫助我們進行水平擴容,然而它究竟是依據什么原則進行請求的分發,其中又有哪些負載均衡算法可供選擇和配置,今天就讓我們好好來了解一下。
負載均衡的定義
什么叫負載均衡,我們可以參考一下圖片中的這種情況:
- 當客戶端發送請求時,會先到Nginx,然后Nginx會將請求分發到后台不同的服務器上。
- 如果后台的服務器群中有一個宕機了,那么Nginx會自動忽略這台服務器,不會將請求再次分發到這台服務器上。
- 如果有新加入的服務器,Nginx也會將請求分發到這台服務器上。
我所理解的負載均衡,就是:
能夠將客戶端的請求均勻地分發到后台各個應用服務器上,從而緩解服務器壓力。
並且當服務器出現宕機或者擴容時,也能正常運行。
負載均衡的方法
上面了解了什么是負載均衡,那么Nginx是怎么實現這個功能的呢?
upstream和server的使用
Nginx中負責與上游交互的模塊,統稱為upstream模塊。
而指定上游服務地址是通過upstream
和server
指令完成的,其關系為:
指定上游服務器的address
時,其地址可以是域名、IP地址或者unix socket地址。
可以在域名或者IP地址后加端口,如果不加端口,那么默認使用80端口
。
在address
后面可以添加一些參數,比如:
backup
:指定當前server為備份服務,僅當非備份server不可用時,請求才會轉發到該server。
down
:標識某台服務已經下線,不再服務。
舉個例子:
upstream upstream-service {
server 127.0.0.1:17002;
server 127.0.0.1:17000;
}
round-robin
在upstream
這個模塊中,它還提供了一個最基本的負載均衡算法round-robin
。
其功能是:
以加權輪詢的方式訪問server指令指定的上游服務。
這個算法是默認集成在Nginx的框架中,無法移除,所以后面講解的所有算法都是基於此,所有算法在某些特殊情況下最終都會變成round-robin
。
涉及到的指令有:
weight
:服務訪問的權重,默認是1。max_conns
:server的最大並發連接數,僅作用於單worker進程。max_fails
:在fail_timeout
時間內,最大的失敗次數。當達到最大失敗時,會在fail_timeout
時間內不允許再次被選擇。fail_timeout
:單位為秒,默認是10秒。指定一段時間內,最大的失敗次數max_fails
。到達max_fails
后,該server不能訪問的時間。
簡單的hash模塊
有的時候,正常的輪詢算法並不能滿足我們的需求,
比如:帶有cookie請求狀態的連接,如果應用服務沒有設置專門的管理cookie的服務器,那么我們就希望同一個用戶能被分配到同一個服務器。
再比如:我們后端應用需要針對請求當中的參數或者URL,將相同的請求放到相同的服務器上進行處理。
針對第一種情況,就可以用upstream_ip_hash
。針對第二種情況,可以使用upstream_hash
。
upstream_ip_hash
功能:
以客戶端的IP地址作為hash算法的關鍵字,映射到特定的上游服務器中。
- 對IPV4地址使用前3個字節作為關鍵字,對IPV6則使用完整地址。
- 可以使用
round-robin
算法的參數。- 可以基於
realip
模塊修改用於執行算法的IP地址。
舉個例子:
upstream upstream-service {
ip_hash;
server 127.0.0.1:17002;
server 127.0.0.1:17000;
}
upstream_hash
功能:
通過制定關鍵字作為hash key,基於hash算法映射到特定的上游服務器中。
- 關鍵字可以含有變量、字符串。
- 可以使用
round-robin
算法的參數。
舉個例子(以請求中的參數username作為hash key):
upstream upstream-service {
hash user_$arg_username;
server 127.0.0.1:17002;
server 127.0.0.1:17000;
}
一致性哈希算法
hash算法在一定程度上已經可以滿足了我們的業務需求,但如果這個時候遇到應用宕機或者應用擴容,那么hash的總數就會變化,這樣很有可能帶來大量請求原本請求的服務器會更換,路由會失效,這樣對於我們的應用服務也會產生極大的影響,這時候就可以采用一致性hash算法。
對於一致性哈希算法的理解,可以參考這篇文章:一致性哈希算法的理解與實踐
它的使用也十分簡單,就是在之前說的upstream_hash
模塊的hash
指令最后,添加參數consistent
,這樣Nginx就可以使用一致性哈希算法了。
舉個例子(仍以請求中的參數username作為hash key):
upstream upstream-service {
hash user_$arg_username consistent;
server 127.0.0.1:17002;
server 127.0.0.1:17000;
}
總結
以上就是Nginx中比較常見的負載均衡方法了,還有一些比如最少連接算法
等,都是在此之上的一些應用。如果大家有什么疑問,歡迎在下方留言。
有興趣的話可以訪問我的博客或者關注我的公眾號、頭條號,說不定會有意外的驚喜。