適合讀者
- 想理解 AWS ALB/Nginx 的 Connection 管理
- 使用 Nginx 作為 AWS ALB Backend 的開發者
前言
AWS ELB 提供 ALB(L7) 以及 NLB (L4) 的 Load Balancer, 然而 L4/L7 Balancer 的 Keep-Alive 的實作機制是完全不一樣的, 這邊針對 AWS ALB (L7) 的 Keep-Alive Connection 管理進行詳細的說明。
HTTP Keep-Alive
當 Client 發起請求時, AWS ALB 會維護 Frond-end Connection & Back-end Connection:
[client] -> [frond-end conn| alb | back-end conn ] -> [target]
其中 Back-end Connection 會使用 使用 HTTP/1.1 Keep-Alive 發起請求到 Target, 所以 Target 必須啟用 Keep-Alive。
Back-end Connection 建立後, 因為會被 AWS ALB 重複使用, 所以不會被斷開, 然而當 Back-end Connection 進入 Idle 狀態的時候, 回收機制由兩個因素主導:
- AWS ALB Idle Connection Timeout
- Target Keep-Alive Timeout
- 如果是由 AWS ALB 檢查到 Back-end Connection Idle 的時間太長, AWS ALB 會主動向 Client & Target 發送 TCP FIN, 斷開 Frond-end Connection & Back-end Connection。
- 如果是由 Target 檢查到 Back-end Connection Idle 的時間太長, Target 會主動向 AWS ALB 發送 TCP FIN, 斷開與 AWS ALB 的 Back-end Connection。
我們必須確保 Target Keep-Alive Timeout 大於 AWS ALB Idle Connection Timeout, 將 Back-end Connection 的生死大權交由 AWS ALB 管理, 才不會發生 Upstream Prematurely Closed Connection 。
這邊針對幾種 Scenarios 來去做討論:
Scenario 1
[client] -> [alb] -> [node.js]
- 確保 Node.JS 的 Keep-Alive Timeout 大於 AWS ALB Connection Idle Timeout
const server = require("http").createServer();server.keepAliveTimeout = 70000;
Scenario 2
[client] -> [alb] -> [nginx] -> [node.js]
- 確保 Nginx Keep-Alive Timeout 大於 AWS ALB Idle Connection Timeout
- 確保 Node.JS Keep-Alive Timeout 大於 Nginx Upstream Keep-Alive Timeout
Ingress-Nginx ConfigMap
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
data:
keep-alive: "75"
upstream-keepalive-timeout: "60"
Node.JS
const server = require("http").createServer();server.keepAliveTimeout = 75000;
Summary
使用 HTTP Keep-Alive, 必須保證 Upstream Keep-Alive Timeout 大於 Downstream Idle Connection Timeout, 讓斷開 Connection 的主導權回歸 Downstream。