Nginx 以高并發(fā)、低消耗而聞名,這個特點使其很適合作為一個負(fù)載均衡器 (Load Balancer),有策略地分發(fā)請求給不同的后端服務(wù)器。避免單點故障之余,亦增強(qiáng)整個系統(tǒng)的可用性,簡單說不容易宕機(jī)。負(fù)載均衡是反代的其中一個用途。本文介紹 Nginx 常用的幾個負(fù)載均衡策略。
?? 假設(shè)有一組名為 backend 的 upstream,那么調(diào)用方式是 proxy_pass http://backend。
在此例中,平時使用 www.example.com 提供服務(wù),bad.example.com 則暫時下線,bak.example.com 作為發(fā)生故障時兜底的一臺機(jī)器。又稱故障轉(zhuǎn)移 (failover)。
upstream backend { server www.example.com; server bad.example.com down; server bak.example.com backup; }
介個是經(jīng)(mò)典(rèn)的負(fù)載均衡算法。理論上會跳過不能用的 server,但預(yù)設(shè)的超時太長,實務(wù)上可改成 proxy_connect_timeout 1、proxy_read_timeout 1 和 proxy_send_timeout 1。
按照時間先后來分發(fā)請求。在此例中,顧名思義第 1 個 request 走 srv1.example.com,第 2 個走 srv2.example.com,第 3 個走 srv3.example.com,第 4 個走 srv1.example.com……以此類推。
upstream backend { server srv1.example.com; server srv2.example.com; server srv3.example.com; }
因應(yīng)忙閑不均、負(fù)載不均的問題而生。在此例中,Nginx 將試圖減輕已經(jīng)很忙的服務(wù)器的壓力,把新請求分發(fā)至沒那么忙的主機(jī)。
若對動態(tài)負(fù)載均衡的算法感興趣,還有一插件 nginx-upstream-fair 可以實現(xiàn)最快響應(yīng)法。
upstream backend { least_conn; server srv1.example.com; server srv2.example.com; server srv3.example.com; }
Session 用于跟蹤用戶操作,涉及身份認(rèn)證時 (用戶系統(tǒng)) 往往能派上用場,而通常情況下會話信息保存在單機(jī)上,這就使得有些需求得在同一臺服務(wù)器上完成,不能換到其他的服務(wù)器 (姑且不談分布式 Session)。
Sticky Sessions (粘滯會話) 將保證一個用戶對應(yīng)一臺服務(wù)器,從而解決 Session 不一致的問題 (通常表現(xiàn)為無法登錄)。出于容災(zāi)理由,不建議大量使用。
upstream backend { ip_hash; server srv1.example.com; server srv2.example.com; server srv3.example.com; }
集群中難免有算力不均的情況。不同服務(wù)器處理速度有快有慢,不問性能的齊頭式平等,很可能觸發(fā)木桶原理的副作用——讓配置最差的那個服務(wù)器決定整個服務(wù)器集群的性能??膳芤淮?nbsp;bench.sh,再依據(jù)測試結(jié)果給服務(wù)器排個序。
在此例中,每 10 個新請求有 6 個被分配至 srv1.example.com,然后各有 2 個被分配至 srv2.example.com 和 srv3.example.com。此例演示的輪詢法,事實上最小連接和源地址哈希法也可以分配權(quán)重。
upstream backend { server srv1.example.com weight=3; server srv2.example.com; server srv3.example.com; }
根據(jù) Nginx 的文檔,max_fails 缺省值是 1,fail_timeout 缺省值是 10s。
在此例中,www.example.com 的健康檢查會被關(guān)閉,一直都標(biāo)記為可用;www2.example.com 連不上時先重試 2 次,如果還不行就退出服務(wù),下線 1 天,方便運維人員排障。
upstream backend { server www.example.com max_fails=0; server www2.example.com max_fails=2 fail_timeout=1d; }
根據(jù) Nginx 的文檔,proxy_next_upstream 含括下列數(shù)種情況:
error 建立連接 / 發(fā)送請求 / 接收響應(yīng)時出錯(缺省值之一); timeout 建立連接 / 發(fā)送請求 / 接收響應(yīng)時超時(缺省值之一); invalid_header 上游返回空白或無效響應(yīng); http_500 上游返回 500 Internal Server Error; http_501 上游返回 501 Not Implemented; http_502 上游返回 502 Bad Gateway; http_503 上游返回 503 Service Unavailable; http_504 上游返回 504 Gateway Timeout; http_404 上游返回 404 Not Found; http_429 上游返回 429 Too Many Requests; non_idempotent 解除對非冪等請求 (POST, LOCK, PATCH) 的封印,小心造成重復(fù)提交; off 不得轉(zhuǎn)給下一臺服務(wù)器。
一般來說,即使某一臺后端服務(wù)器返回了 500,這臺服務(wù)器也會參與負(fù)載均衡,畢竟能收到 HTTP 狀態(tài)碼,就表示它還活著。但這樣的結(jié)果在用戶眼里跟 Connection Refused 以及 Operation Timed Out 可沒啥區(qū)別,所以在此例中,把 500 一并納入“在下一臺服務(wù)器重試”的機(jī)制里。
location / { ... proxy_pass http://backend; proxy_next_upstream error timeout http_500; ... }