kubernetes ingress-nginx 啟用 upstream 長連接,需要注意,否則容易 502


  之前踩過這個坑,在《使用 nginx 作反向代理,啟用 keepalive 時,遇到 502 錯誤的調查過程》 中了記錄調查過程,當時多個案例同時查,記錄的比較亂,這里重新整理一下結論。

  ingress-nginx 到 upstream 的長連接通過configmap中的 upstream-keepalive-connections 等參數設置,注意與 keep-alive 區分(見文末)。另外 ingress-nginx 0.20 之前的版本有 bug,即使配置了也不生效:ingress-nginx upstream 的 keep-alive 不生效。

 

1.三個結論

  這里主要解釋結論 3,這里的結論不僅適用於 ingress-nginx,也適用於其它使用 nginx 的場景。

  結論1:nginx 的端口耗盡時,會返回 502 錯誤(和本文要討論的內容無關)。

  結論2:nginx 向已經被服務端主動斷開的連接發送請求,會收到 RST,然后返回 502。

  結論3:服務端先於 nginx 斷開連接的情況有兩種,

    1)服務端的連接超時時間小於 nginx 中的配置;

    2)服務端配置的單個連接的最大請求數小於 nginx 中配置。

 

2.為什么服務端有超時時間和最大請求數限制?

  服務端應用可能是通過本地的 tomcat 或者其它 web 框架對外暴露的,這種情況非常普遍。 這些 Web 服務或者框架通常都有默認的長連接設置。

  譬如 tomcat 的相關配置

  

  另外曾經遇到過的 Gunicorn 超時時間只有 2 秒:

 

3.nginx 的配置與后端服務的配置不一致時

  如果做反向代理的 nginx 中配置的連接斷開條件比后端服務設置的條件寬松,那么就容易出現后端服務先斷開連接的情況, 這時候 nginx 轉發請求到 upstream,upstream 會返回 RST,nginx 打印下面的錯誤日志,給客戶端返回 502:

2019/06/13 04:57:54 [error] 3429#3429: *21983075 upstream prematurely closed connection while reading 
response header from upstream, client: 10.19.167.120, server: XXXX.com, request: "POST XXXX HTTP/1.0",
upstream: "http://11.0.29.4:8080/XXXXXX", host: "XXXX.com"
 
2019/06/13 04:58:34 [error] 3063#3063: *21989359 recv() failed (104: Connection reset by peer) while 
reading response header from upstream, client: 10.19.138.139, server: XXXX.com, request: 
"POST /api/v1/XXXX HTTP/1.1", upstream: "http://11.0.145.9:8080/api/v1/XXXX", host: "XXXX.com"

 

4.建議設置

  可以調整 nginx 的 upstream 中 keepalive_timeout 和 keepalive_requests,確保 nginx 先於 upstream 斷開連接。只有 nginx 與 upstream 之間使用長連接的時候需要考慮這種情況,並進行類似的設置。

upstream record_upstream {
    server  127.0.0.1:9091;
    keepalive 16;
    keepalive_timeout  58s;    # 默認 60 s,根據實際情況調整,建議小於 60s
    keepalive_requests 98;     # 默認 100 個,根據實際情況調整,建議小於 100
}
 
server {
    ...
    location /http/ {
        proxy_pass http://record_upstream;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        ...
    }
}

  nginx 的 keepalive_timeout 和 keepalive_requests 參數各有兩個:一組屬於 ngx_http_core_module,在 http/server/location 中使用,限制的是 client 與 nginx 之間的連接;另一組是上面使用的,屬於 ngx_http_upstream_module,限制的是 nginx 與 upstream 之間的連接。

 

5.默認行為

  nginx 的 upstream 中沒有明確配置 keepalive,那么無論 client 和 nginx 之間是否長連接,nginx 和 upstream 都是短連接。

  用下面的配置觀察:

upstream record_upstream {
    server  127.0.0.1:9091;
 
    #keepalive 3;
    #keepalive_timeout  58s;
    #keepalive_requests 98;
}
 
server {
    listen       9000;
    listen       [::]:9000;
    server_name  echo.example;
    keepalive_requests  2000;
    keepalive_timeout 60s;
 
    location / {
        proxy_pass  http://record_upstream;
        #proxy_http_version 1.1;
        #proxy_set_header Connection "";
    }
}

  使用長連接訪問 nginx :

wrk -c 1 -t 1 -d 2s  http://127.0.0.1:9000

  http-record 收到的請求是 “Connection: close”:

/go/src/Server/echo.go:46: {
    "RemoteAddr": "172.17.0.1:34522",
    "Method": "GET",
    "Host": "record_upstream",
    "RequestURI": "/",
    "Header": {
        "Connection": [
            "close"
        ]
    },
    "Body": ""
}

 

6.參考

  https://www.lijiaocn.com/%E9%97%AE%E9%A2%98/2019/12/04/nginx-keep-alive-problem.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM