關於 Nginx upstream keepalive 的說明

模塊是 HttpUpstreamModule,配置的一個例子:nginx

[shell]upstream http_backend {
    server 127.0.0.1:8080;shell

    keepalive 16;
}
server {
    …後端

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        …
    }
}[/shell]tomcat

 

有幾點要說明:服務器

1. 默認狀況下 Nginx 訪問後端都是用的短鏈接(HTTP1.0),一個請求來了,Nginx 新開一個端口和後端創建鏈接,請求結束鏈接回收。若是像上面的配置同樣設置了長鏈接,Nginx 會接受客戶端的請求,處理完成以後 Nginx 會「繼續保持和後端的長鏈接」,若是併發請求超過了 keepalive 指定的最大鏈接數,Nginx 會啓動新的鏈接 來轉發請求,新鏈接在請求完畢後關閉,並且新創建的鏈接是長鏈接,這可能會形成額外的問題,最後再說。併發

2. keepalive 指定的 數值 是 Nginx 每一個 worker  鏈接後端的最大長鏈接數,而不是整個 Nginx 的。 並且這裏的後端指的是「全部的後端」,而不是每個後端(已驗證)。負載均衡

3. 在官網上  能夠看到 還有一個 single 參數,說實話我沒懂什麼意思,可是它已經被廢棄了,看這裏tcp

4. HttpUpstreamModule 模塊裏面還有一共指令:least_conn,解釋以下:tornado

Specifies that a group should use a load balancing method where a request is passed to the server with the least number of active connections, taking into account weights of servers. If there are several such servers, they are tried in turn using a weighted round-robin balancing method.測試

翻譯:

指定服務器組的負載均衡方法,根據其權重值,將請求發送到「活躍鏈接數最少」的那臺服務器。 若是這樣的服務器有多臺,那就採起有權重的輪轉法進行嘗試。

使用這個指令的時候後端服務器的鏈接數好像會變的很是少,很奇怪,我還沒親自測過,待確認。

 

最後再說一下第 1 點,先說一個現象,我發現當 keepalive 設置小的時候,好比1,那麼併發請求上去以後 Nginx 會出現大量的 TIME_WAIT,而若是把 keepalive 關掉(proxy_http_version 1.1 和 proxy_set_header Connection 「」 指令也去掉),那麼 TIME_WAIT 就會出如今後端服務器了,後端用的是 tornado,相信 jetty 和 tomcat 也是同樣。

這個現象是怎麼產生的呢,作一個測試。

命令:ab -n 100 -c 5 http://pxe1.hy01/

pxe1.hy01 (Nginx,上面配置了長鏈接,ip: 10.0.31.84) ,它會轉到 pxe0.hy01 的 8888 端口(tornado,ip: 10.0.11.12)

測試的時候在 pxe1.hy01 執行抓包命令:

# tcpdump -i em2 -A host 10.0.11.12 -n

看到:

00:22:53.252039 IP 10.0.31.84.53915 > 10.0.11.12.ddi-tcp-1: Flags [P.], seq 81:161, ack 275, win 123, length 80
@.@.].
..T
…..」…p%8|..P..{>…GET / HTTP/1.1
Host: http_backend
User-Agent: ApacheBench/2.3
Accept: */*

可是若是把 pxe1.hy01 的長鏈接設置都去掉的話,抓包以下:

00:23:58.111974 IP 10.0.31.84.54051 > 10.0.11.12.ddi-tcp-1: Flags [P.], seq 1:100, ack 1, win 115, length 99
E…..@.@.Z=
..T
….#」…O…SUP..s>…GET / HTTP/1.0
Host: http_backend
Connection: close
User-Agent: ApacheBench/2.3
Accept: */*

那麼上面出現的現象就好解釋了,是這樣:

Nginx 和後端的長鏈接不夠用時 Nginx 會新建鏈接來處理新的請求,而咱們的配置已經配置死了 HTTP1.1,創建鏈接後,後端認爲是「長鏈接」而不會主動關閉鏈接(通常有個空閒超時),關閉鏈接由 Nginx 來作了,因此 Nginx 會出現大量的 TIME_WAIT。

而默認狀況下,Nginx 用 HTTP1.0 請求後端,後端處理完成後就主動關閉鏈接,因此 TIME_WAIT 在後端。

那麼如今有新的問題了,若是開啓了長鏈接,而長鏈接又大量不夠用,此時 Nginx 存在的 TIME_WAIT 可能會大量佔用端口,致使端口用盡,若是用盡,後果很嚴重。

因此,「慎用 Nginx 的 長鏈接」。

相關文章
相關標籤/搜索