Nginx load balancing - 負(fù)載均衡

介紹

在多個(gè)應(yīng)用實(shí)例間做負(fù)載均衡是一個(gè)被廣泛使用的技術(shù),用于優(yōu)化資源效率,最大化吞吐量,減少延遲和容錯(cuò)。

負(fù)載均衡的幾個(gè)重要的點(diǎn):

  • 上游服務(wù)器配置 :使用upstream server配置多個(gè)上游服務(wù)器。
  • 負(fù)載均衡算法 :配置多個(gè)上游服務(wù)器時(shí)的負(fù)載均衡機(jī)制。
  • 失敗重試機(jī)制 :配置當(dāng)超時(shí)或上游服務(wù)器不存活時(shí),是否需要重試其他上游服務(wù)器。
  • 服務(wù)器心跳檢查 :上游服務(wù)器的健康檢查/心跳檢查。

負(fù)載均衡方法

請(qǐng)求轉(zhuǎn)發(fā)的策略。

  1. round-robin/輪詢(xún)(默認(rèn)): 到應(yīng)用服務(wù)器的請(qǐng)求以round-robin/輪詢(xún)的方式被分發(fā)
  2. least-connected/最少連接:下一個(gè)請(qǐng)求將被分派到活動(dòng)連接數(shù)量最少的服務(wù)器
  3. ip-hash/IP散列: 使用hash算法來(lái)決定下一個(gè)請(qǐng)求要選擇哪個(gè)服務(wù)器(基于客戶(hù)端IP地址)

Nginx 配置

1. 基本配置

http {
    upstream myapp1 {
        // 負(fù)載均衡的方法,默認(rèn)為 round-robin
        // least_conn;
        // ip_hash;
        
        // 均衡的服務(wù)器清單
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://myapp1;
        }
    }
}

2. 權(quán)重配置

可以更具服務(wù)器的性能,進(jìn)行權(quán)重的配置

upstream myapp1 {
    server srv1.example.com weight=3;
    server srv2.example.com;
    server srv3.example.com;
}

在這個(gè)配置中,每5個(gè)新請(qǐng)求將會(huì)如下的在應(yīng)用實(shí)例中分派: 3個(gè)請(qǐng)求分派去srv1,一個(gè)去srv2,另外一個(gè)去srv3.

在最近的nginx版本中,可以類(lèi)似的在最少連接和IP哈希負(fù)載均衡中使用權(quán)重。

健康檢測(cè)

Upstream 服務(wù)器節(jié)點(diǎn)的健康檢測(cè) 及 分發(fā)控制。

被動(dòng)能做到訪問(wèn)那一刻失敗的,可以重新分發(fā)到其他的節(jié)點(diǎn);主動(dòng)可以提前做好監(jiān)測(cè),避免錯(cuò)誤碰撞。

1. 被動(dòng)的健康檢測(cè)

通過(guò) nginx 自帶的 ngx_http_proxy_module 模塊 和 ngx_http_upstream_module模塊進(jìn)行檢測(cè),對(duì)具體的請(qǐng)求結(jié)果分析,判斷該服務(wù)器節(jié)點(diǎn)是否有問(wèn)題。

http {
    upstream myapp1 {
        // ngx_http_upstream_module。失敗1次后,即停止向該服務(wù)器分發(fā),直到 10秒后重新分發(fā)
        server srv1.example.com weight=1 max_fails=1 fail_timeout=10;
        server srv2.example.com weight=1 max_fails=1 fail_timeout=10;
        server srv3.example.com weight=1 max_fails=1 fail_timeout=10;
    }
    
    server {
        listen 80;
        
        // ngx_http_proxy_module
        proxy_send_timeout=60;
        proxy_connect_timeout=60;
        proxy_read_timeout=60;
        proxy_next_upstream=error timeout; // 默認(rèn)
    
        location / {
            proxy_pass http://myapp1;
        }
    }
}
  • fail_timeout — 該參數(shù)表示停止分發(fā)請(qǐng)求至該應(yīng)用服務(wù)器的時(shí)間
  • max_fails — 設(shè)置訪問(wèn)失敗的最大次數(shù)
  • proxy_connect_timeout - 設(shè)置與后端服務(wù)器建立連接的超時(shí)時(shí)間
  • proxy_read_timeout - 定義從后端服務(wù)器讀取響應(yīng)的超時(shí)。此超時(shí)是指相鄰兩次讀操作之間的最長(zhǎng)時(shí)間間隔,而不是整個(gè)響應(yīng)傳輸完成的最長(zhǎng)時(shí)間。如果后端服務(wù)器在超時(shí)時(shí)間段內(nèi)沒(méi)有傳輸任何數(shù)據(jù),連接將被關(guān)閉
  • proxy_next_upstream - 指定在何種情況下一個(gè)失敗的請(qǐng)求應(yīng)該被發(fā)送到下一臺(tái)后端服務(wù)器
error      # 和后端服務(wù)器建立連接時(shí),或者向后端服務(wù)器發(fā)送請(qǐng)求時(shí),或者從后端服務(wù)器接收響應(yīng)頭時(shí),出現(xiàn)錯(cuò)誤
timeout    # 和后端服務(wù)器建立連接時(shí),或者向后端服務(wù)器發(fā)送請(qǐng)求時(shí),或者從后端服務(wù)器接收響應(yīng)頭時(shí),出現(xiàn)超時(shí)
invalid_header  # 后端服務(wù)器返回空響應(yīng)或者非法響應(yīng)頭
http_500   # 后端服務(wù)器返回的響應(yīng)狀態(tài)碼為500
http_502   # 后端服務(wù)器返回的響應(yīng)狀態(tài)碼為502
http_503   # 后端服務(wù)器返回的響應(yīng)狀態(tài)碼為503
http_504   # 后端服務(wù)器返回的響應(yīng)狀態(tài)碼為504
http_404   # 后端服務(wù)器返回的響應(yīng)狀態(tài)碼為404
off        # 停止將請(qǐng)求發(fā)送給下一臺(tái)后端服務(wù)器

出現(xiàn) error 的場(chǎng)景,常見(jiàn)的是上游服務(wù)器的服務(wù)重啟、停止,或者異常崩潰導(dǎo)致的無(wú)法提供正常服務(wù)。而 timeout 的情況,就是代理請(qǐng)求過(guò)程中達(dá)到對(duì)應(yīng)的超時(shí)配置,主要包括了:

proxy_connect_timeout,建立三次握手的時(shí)間
proxy_read_timeout,建立連接后,等待上游服務(wù)器響應(yīng)以及處理請(qǐng)求的時(shí)間
proxy_send_timeout,數(shù)據(jù)回傳的間隔時(shí)間(注意不是數(shù)據(jù)發(fā)送耗時(shí))

2. 主動(dòng)的健康檢測(cè)

主動(dòng)定時(shí)向每臺(tái)服務(wù)器發(fā)送指令,來(lái)監(jiān)測(cè)是否正常。主要以下兩種:

  • nginx_upstream_check_module模塊
  • ngx_http_healthcheck_module模塊

2.1 nginx_upstream_check_module模塊

除了自帶的上述模塊,還有一個(gè)更專(zhuān)業(yè)的模塊,來(lái)專(zhuān)門(mén)提供負(fù)載均衡器內(nèi)節(jié)點(diǎn)的健康檢查的。這個(gè)就是淘寶技術(shù)團(tuán)隊(duì)開(kāi)發(fā)的 nginx 模塊。

在淘寶自己的 tengine 上是自帶了該模塊的,大家可以訪問(wèn)淘寶tengine的官網(wǎng)來(lái)獲取該版本的nginx,官方地址:http://tengine.taobao.org/ 。

upstream name {
   server 192.168.0.21:80;
   server 192.168.0.22:80;
   
   // 對(duì)所有節(jié)點(diǎn),每個(gè)3秒檢測(cè)一次,請(qǐng)求2次正常則標(biāo)記 realserver狀態(tài)為up,如果檢測(cè) 5 次都失敗,則標(biāo)記 realserver的狀態(tài)為down,超時(shí)時(shí)間為1秒
   check interval=3000 rise=2 fall=5 timeout=1000 type=http;
   // check_http_send "HEAD /status HTTP/1.0\r\n\r\n";
   // check_http_expect_alive http_2xx http_3xx;
}

參數(shù)

  • interval:向后端發(fā)送的健康檢查包的間隔。
  • fall(fall_count): 如果連續(xù)失敗次數(shù)達(dá)到fall_count,服務(wù)器就被認(rèn)為是down。
  • rise(rise_count): 如果連續(xù)成功次數(shù)達(dá)到rise_count,服務(wù)器就被認(rèn)為是up。
  • timeout: 后端健康請(qǐng)求的超時(shí)時(shí)間。
  • default_down: 設(shè)定初始時(shí)服務(wù)器的狀態(tài),如果是true,就說(shuō)明默認(rèn)是down的,如果是false,就是up的。默認(rèn)值是true,也就是一開(kāi)始服務(wù)器認(rèn)為是不可用,要等健康檢查包達(dá)到一定成功次數(shù)以后才會(huì)被認(rèn)為是健康的。
  • type:健康檢查包的類(lèi)型,現(xiàn)在支持以下多種類(lèi)型
    • tcp:簡(jiǎn)單的tcp連接,如果連接成功,就說(shuō)明后端正常。
    • ssl_hello:發(fā)送一個(gè)初始的SSL hello包并接受服務(wù)器的SSL hello包。
    • http:發(fā)送HTTP請(qǐng)求,通過(guò)后端的回復(fù)包的狀態(tài)來(lái)判斷后端是否存活。
    • mysql: 向mysql服務(wù)器連接,通過(guò)接收服務(wù)器的greeting包來(lái)判斷后端是否存活。
    • ajp:向后端發(fā)送AJP協(xié)議的Cping包,通過(guò)接收Cpong包來(lái)判斷后端是否存活。
  • port: 指定后端服務(wù)器的檢查端口。你可以指定不同于真實(shí)服務(wù)的后端服務(wù)器的端口,比如后端提供的是443端口的應(yīng)用,你可以去檢查80端口的狀態(tài)來(lái)判斷后端健康狀況。默認(rèn)是0,表示跟后端server提供真實(shí)服務(wù)的端口一樣。該選項(xiàng)出現(xiàn)于Tengine-1.4.0

健康服務(wù)器查看頁(yè)面

在Tengine-1.4.0以后,你可以配置顯示頁(yè)面的格式。支持的格式有: html、csv、 json。默認(rèn)類(lèi)型是html。

你也可以通過(guò)請(qǐng)求的參數(shù)來(lái)指定格式,假設(shè)‘/status’是你狀態(tài)頁(yè)面的URL, format參數(shù)改變頁(yè)面的格式,比如:

/server_status?format=html
/server_status?format=csv
/server_status?format=json
同時(shí)你也可以通過(guò)status參數(shù)來(lái)獲取相同服務(wù)器狀態(tài)的列表,比如:

/server_status?format=html&status=down
/server_status?format=csv&status=up
下面是一個(gè)狀態(tài)也配置的范例:

http {
  server {
     // 定義服務(wù)器的查看地址(可以通過(guò)程序靈活控制當(dāng)前機(jī)器的工作狀態(tài))
     location /server_status {
       check_status;
       access_log off;
     }
  }
}

2.2 health_check

只有商業(yè)版的 nginx 可用,這里不作詳細(xì)介紹。主要是通過(guò) health_check + zone 指令

http {
  upstream onmpw {
      // zone指令定義了一塊兒內(nèi)存空間。這塊兒空間存儲(chǔ)在各個(gè)工作進(jìn)程中共享的運(yùn)行環(huán)境的狀態(tài)和應(yīng)用服務(wù)器組的配置信息
      zone onmpw 64k;
      server 192.168.144.128;
      server 192.168.144.132;
      server 192.168.144.131;
  }
  server {
      listen 80;
      location / {
          proxy_pass http://onmpw;
          // interval=10: 每隔10秒向服務(wù)器發(fā)送一個(gè) / http 請(qǐng)求,如果沒(méi)有返回 2xx 或者 3xx,都認(rèn)為失敗
          // fails=3: 如果請(qǐng)求失敗次數(shù)達(dá)到3次,則該應(yīng)用服務(wù)器被認(rèn)為不能訪問(wèn)
          // passes=2: 被認(rèn)定為不能訪問(wèn)的服務(wù)器需要再次進(jìn)行兩次health_check 以后才會(huì)再次被認(rèn)為是可以正常訪問(wèn)的
          // uri=/some/path: 指定 health check 的地址
          health_check interval=10 fails=3 passes=2;
      }
  }
}

Upstream 的動(dòng)態(tài)負(fù)載均衡

我們可以發(fā)現(xiàn),如果每次upstream列表有改動(dòng),都需要到服務(wù)器進(jìn)行修改。
更好的做法是實(shí)現(xiàn)upstream服務(wù)的自動(dòng)發(fā)現(xiàn)。

Consul是一款開(kāi)源的分布式服務(wù)注冊(cè)與發(fā)現(xiàn)系統(tǒng),通過(guò)HTTP API可以使得服務(wù)注冊(cè)、發(fā)現(xiàn)實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單,它支持如下特性。

  • 服務(wù)注冊(cè): 服務(wù)實(shí)現(xiàn)者可以通過(guò)HTTP API或DNS方式,將服務(wù)注冊(cè)到Consul。
  • 服務(wù)發(fā)現(xiàn): 服務(wù)消費(fèi)者可以通過(guò)HTTP API或DNS方式,從Consul獲取服務(wù)的IP 和PORT。
  • 故障檢測(cè): 支持如TCP、HTTP等方式的健康檢查機(jī)制,從而當(dāng)服務(wù)有故障時(shí)自動(dòng)摘除。
  • K/V存儲(chǔ): 使用K/V存儲(chǔ)實(shí)現(xiàn)動(dòng)態(tài)配置中心,其使用HTTP長(zhǎng)輪詢(xún)實(shí)現(xiàn)變更觸發(fā)和配置更改。
  • 多數(shù)據(jù)中心: 支持多數(shù)據(jù)中心,可以按照數(shù)據(jù)中心注冊(cè)和發(fā)現(xiàn)服務(wù),即支持只消費(fèi)本地機(jī)房服務(wù),使用多數(shù)據(jù)中心集群還可以避免單數(shù)據(jù)中心的單點(diǎn)故障。
  • Raft算法: Consul使用Raft算法實(shí)現(xiàn)集群數(shù)據(jù)一致性。

通過(guò)Consul可以管理服務(wù)注冊(cè)與發(fā)現(xiàn),接下來(lái)需要有一個(gè)與Nginx部署在同一臺(tái)機(jī)器的Agent來(lái)實(shí)現(xiàn)Nginx配置更改和Nginx重啟功能。

有Confd或者Consul-template兩個(gè)選擇,而Consul-template是Consul官方提供的。其使用HTTP長(zhǎng)輪詢(xún)實(shí)現(xiàn)變更觸發(fā)和配置更改(使用Consul的watch命令實(shí)現(xiàn))。也就是說(shuō),我們使用Consul-template實(shí)現(xiàn)配置模板,然后拉取Consul配置渲染模板來(lái)生成Nginx實(shí)際配置。

參考

Using nginx as HTTP load balancer》官網(wǎng)

使用nginx實(shí)現(xiàn)HTTP負(fù)載均衡》 翻譯官網(wǎng)

億級(jí)流量網(wǎng)站架構(gòu)核心技術(shù)(負(fù)載均衡與反向代理)

Nginx負(fù)載均衡(七層)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容