TLDR#
- 問題:將 Nginx 配置從測試環境遷移到正式環境後,無法接收 SSE
- 原因:Nginx 1.22.0 預設使用了 HTTP/1.0 而不是 HTTP/1.1
- 調查方法:啟用調試日誌並分析
- 解決方案:在 Nginx 全局設置中指定 HTTP 版本為 1.1
使用一樣的 Config,從測試環境搬移到正式環境後,一般請求皆正常,但 SSE 無回應(Timeout)。
經過人工、工具比對,以及 ChatGPT 分析,都沒有發現設定上的問題。
唯一差異在於測試環境是 1.22.1,而正式環境的 Nginx 版本是 1.22.0。
調查過程#
啟用調試日誌#
首先在 /etc/nginx/nginx.conf
中啟用調試日誌,印出詳細的錯誤:
1
| error_log /var/log/nginx/error.log debug;
|
檢查配置並重新加載 Nginx:
1
2
| nginx -t
nginx -s reload
|
分析日誌#
我們可以在 /var/log/nginx/error.log
找到錯誤資訊。
若是緊急線上修復,且很多使用者在線,可能導致 log 過多難以查找,這時候可以用以下方法:
1
| tail -f -n 1 /var/log/nginx/error.log | grep -i "sse" # sse可替換為你想要查找的關鍵字
|
這行指令會持續追蹤 error.log
的最新一行,並且過濾出含有 “sse” 的 log。
接著去操作出問題的 API,得到以下資訊:
1
2
3
4
5
6
| # 已替換敏感資訊並省略字數
[notice] XXXX#XXXX: _XXXX "^/app/(._)$" matches "/app/api/sse", client: X.X.X.X, server: example.com, request: "GET /app/api/sse HTTP/1.1", host: "example.com", referrer: "https://example.com/app/Game"
[notice] XXXX#XXXX: *XXXX "^/app/(.*)$" matches "/app/api/sse", client: X.X.X.X, server: example.com, request: "GET /app/api/sse HTTP/1.1", host: "example.com", referrer: "https://example.com/app/Game"
[notice] XXXX#XXXX: *XXXX rewritten data: "/root/api/sse", args: "", client: X.X.X.X, server: example.com, request: "GET /app/api/sse HTTP/1.1", host: "example.com", referrer: "https://example.com/app/Game"
[error] XXXX#XXXX: *XXXX upstream timed out (110: Connection timed out) while reading upstream, client: X.X.X.X, server: example.com, request: "GET /app/api/sse HTTP/1.1", upstream: "http://127.0.0.1:80/root/api/sse", host: "example.com", referrer: "https://example.com/app/Game"
[info] XXXX#XXXX: \*XXXX epoll_wait() reported that client prematurely closed connection, so upstream connection is closed too while reading upstream, client: 127.0.0.1, server: example.com, request: "GET /root/api/sse HTTP/1.0", upstream: "http://X.X.X.X:8888/sse", host: "127.0.0.1", referrer: "https://example.com/app/Game"
|
發現問題#
仔細看可以發現在最後一行,Nginx 沒有正確吃到 HTTP/1.1 的設定並錯誤的使用了 HTTP/1.0,才導致 SSE 傳送失敗。
即使在 Config 中所有地方都設定 proxy_http_version 1.1;
,也無法順利解決。
推測因不明原因(可能是版本差異),Nginx 忽略設定檔,使用預設的 HTTP/1.0 來呼叫 SSE。
解決方案#
直接在 http 區塊中,將全域 proxy_http_version 預設改為 1.1。
強制 Nginx 在所有連接中使用 HTTP/1.1,包括與 upstream 的連接等。
1
2
3
4
| # 不同專案可能會有不同設定
http {
proxy_http_version 1.1;
}
|
- 版本差異可能導致意想不到的問題,即使配置文件相同。
- 啟用詳細日誌對於診斷問題非常有幫助。
- 有時全局設置可以解決特定問題,特別是當單個指令似乎不起作用時。
- 在進行環境遷移時,務必仔細檢查所有相關軟件的版本。