🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付
  • 我目前負責 AWS 上的 WEB 系統基礎設施維護管理。
  • 系統的超時設計雖然是一個不起眼的領域,但如果設計不當,將會直接導致系統故障,因此我認為這是非常重要的要點之一。
  • 同時,透過近期的工作,我深刻體悟到這個領域對於非專業人士來說理解上有難度,但讓應用程序負責人能夠掌握其內容是必不可少的。因此,我決定藉此機會整理自己的見解,將其總結在本篇文章中。

相關條件(主要是希望確認本投稿的人)

  • 尚未有超時設計經驗,想確認設計要點的人。

  • 雖然了解超時設計要點,但想確認為什麼需要這樣設定的人。

  • 本文省略了基於 TCP/IP 的 OSI 參考模型的基本概念及 TCP/IP 的通訊處理流程等基礎網絡知識的說明。

導入・前提知識整理

1. 超時設置的目的

「客戶端」和「伺服器端」雙方主要基於以下目的進行設置。此外,雙方適當設定超時可以防止一方的故障或延遲波及對方,避免對整個系統產生不良影響。

項目 設置目的 形象範例
客戶端 避免對伺服器的無謂連接嘗試與等待 ・在網絡故障或伺服器宕機的情況下防止永久等待
伺服器 保護伺服器資源,維持對客戶端的服務 ・限制在伺服器端執行處理的最大允許時間,以免影響其他請求處理/切斷不使用的客戶端連接
  • 根據 TCP/IP 的規範,連接的建立必須由客戶端發起,但連接的結束(解除)則可以由客戶端或伺服器端任意一方進行。
  • 因此,可以說客戶端基於超時切斷連接的行為是符合規範的合理表現。

2. 「連接」「事務」「會話」的區別

以下表格總結了它們各自的區別。

項目 概要
連接 在應用程序間進行通訊所需的傳輸路徑
事務 在連接建立的前提下進行的一系列操作,例如在線上檢索或更新處理
會話 在連接確立後,直至切斷之前所進行的多個事務的集合

3. 「TCP Keep-Alive」和「HTTP Keep-Alive」的區別

「TCP Keep-Alive」和「HTTP Keep-Alive」的運行層級和目的不同。以下總結了它們的區別。

項目 TCP Keep-Alive HTTP Keep-Alive
層級 傳輸層(L4) 應用層(L7)
目的 確認 TCP 連接是否存活(心跳監視) 重複使用 HTTP 連接<br>提升性能
動作時機 在無通訊的固定時間內自動發送探測包 在 HTTP 請求/響應完成後維持連接
設定位置 OS・內核層級 應用程序・Web 伺服器層級
發送數據 空的 ACK 封包(不包含數據) HTTP 標頭(Connection: keep-alive)
主要用途 ・防止防火牆等的超時<br>・快速檢測斷線<br>・消除僵屍連接 ・在多個 HTTP 請求中重複使用連接<br>・省略 3-way 握手<br>・降低延遲
HTTP 標頭 Connection: keep-alive<br>Keep-Alive: timeout=5, max=100
斷線契機 如果未收到應答 超時、達到最大請求、<br>收到 Connection: close
開銷 極小(定期的空封包) 小(減少連接的建立效果)
無效化影響 斷線檢測會延遲 每個請求都需要建立連接

各處理的差異形象如下:

  • TCP Keep-Alive 處理形象
    image.png
    image.png

  • HTTP Keep-Alive 處理形象
    image.png
    image.png

具體的封包及處理形象可參考以下網站
https://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/keepalive-tcp-http/

【補充】
如上述所述,「TCP Keep-Alive」與「HTTP Keep-Alive」運行的層級不同。
因此,即使在「HTTP Keep-Alive」的有效期間內,伺服器端收到「TCP Keep-Alive」的探測封包,則「HTTP Keep-Alive」的計時器不會重置。
這是因為探測封包不包含應用層(HTTP)的數據。

4. 超時設定位置

超時值在前述的「連接」「事務」「會話」各層級中均存在設置。以下將各項目的設定位置範例整理如下。

項目 特徵 目標項目例子 說明
連接超時 對於連接或通訊的等待時間 Connection Timeout 從發送連接請求到接收到連接完成的應答的等待時間。如連接失敗,則可立即使用此計時器報錯,以避免浪費等待時間
IdleTimeout 連接建立後,維持無請求狀態的最大時間。超過此時間,中間網絡設備(負載均衡器/防火牆等)將強制斷開連接
HTTP Keep-AliveTimeout 在發送 HTTP 請求時維持和重用已建立的 TCP 連接的時間。超過此時間,伺服器將斷開連接,並從下一請求重新連接
ReadTimeout/SocketTimeout 連接建立後,等待從連接返還數據的最大時間。超過此時間,客戶端將報錯,而不等待伺服器的處理完成
事務超時 對業務處理・數據庫處理等「各処理」的時間限制 Statement Timeout SQL 查詢的最大允許時間。超過此時間,將強制終止 SQL 執行
Transaction Timeout 包含數據庫操作的整體業務處理完成的最大允許時間。超過此時間,伺服器將中斷處理,執行數據庫的回滾並釋放資源
會話超時 保持登錄狀態的時間限制 SessionTimeout 用戶與系統連接的狀態(狀態)的最大保持時間。超過此時間,伺服器將丟棄該會話信息(客戶端將再次要求進行認證)

在進行整個系統的超時設計時,正確把握各組件可設置的超時值「是針對哪個層級的,哪種控制進行設置」是非常重要的。

超時設計的理論

1. TCP(L4層)

在 TCP 連接建立後,原則上除非有以下情況,應設計為維持連接(不包括因中間網絡設備如防火牆或負載均衡器斷開的情況)。

→以之前的電話通話為例,使用「智能手機的電話應用程序(應用層 L7)」時,如果在通話中按下「結束通話」按鈕之前,「通訊運營商(TCP:L4層)」無故切斷通話,那麼大家會感到困惑。這是一個相關的意象。

  • ① 上位層(應用程序)發出連接切斷指示(L7層控制)
  • ② 無效連接的檢測・刪除(L4 層控制)

本項中,我將整理上面提到的項目中,L4 層的角色「② 無效連接的檢測・刪除(TCP Keep-Alive)」和中間網絡設備中設置的「TCP Idle Timeout」。

(1)TCP IdleTimeout設計

防火牆和負載均衡器等中間網絡設備將在內部管理會話信息,並在監控通訊的同時運行。但從資源管理的觀點設置了「TCP Idle Timeout」計時器,持續無通訊狀態的連接將被判斷為不需要,並自管理表中刪除以及強制斷開連接。

因此,這些設備中設置的「TCP Idle Timeout」的設置值需要根據後述的應用層側的連接和事務計時器的設計政策進行考量。

(2)TCP Keep-Alive設計

TCP Keep-Alive 的運作概要如前述的 3. 「TCP Keep-Alive」與「HTTP Keep-Alive」的區別 中所述,這個處理在「TCP Idle Timeout設計」中提到的計時器重置時也扮演著重要角色。

具體而言,TCP Keep-Alive 的探測包將設計為以比防火牆和負載均衡器的「TCP Idle Timeout」更短的間隔發送。這樣可以防止意外地切斷 TCP 連接(無效化)。

Linux 發行版的默認值通常設為「7200 秒(2 小時)」,但從現代公共雲的使用觀點出發,為了有效利用此功能,建議調整為更短的設置值(大約幾分鐘)。然而,具體的設置值需要充分考慮應用層和中間網絡設備的設置才能決定。

2. 應用程序(L7層)

(1)連接/事務計時器設計

應用程序層的計時器設計基本理念是「從前端逐步減小超時值」。為何必須這樣設計,以下將其原因列出。

下圖示,若在發送目的地(應用伺服器/數據庫伺服器)處理完成之前,就在 WEB 伺服器側檢測到超時,則客戶端將無法獲得預期的結果。
(不良示例:WEB 伺服器的計時器值為最小值的情況)
image.png

因此,我們需要防止在發送目的地的處理完成之前發送源方超時。具體而言,正如之前所述,將計時器值設計為類漏斗(即後續處理的超時值較小,縮小後續處理的範圍)是必要的設計。
(以下是漏斗型設計中檢測到超時時的處理示例)
image.png

不過,「HTTP Keep-Alive」 的基本理念在任意 TCP 連接中是「發送方的 HTTP Keep-Alive 計時器 < 接收方的 HTTP Keep-Alive 計時器」,具體而言,如下表・圖所述,考慮包括之前所述的「TCP IdleTimeout」的設置。
image.png

為何應進行如此設計,以下將其例子列出。

如圖所示,當發送源(負載均衡器)通過 HTTP Keep-Alive 判斷現有連接是有效並嘗試重複使用之時,發送目的地的 WEB 伺服器端可能因超時已經切斷該連接,導致通訊錯誤的發生(當伺服器端的連接關閉與 ALB 的 HTTP 請求同時進行時會發生)。
(不良示例:WEB 伺服器的 HTTP Keep-Alive 計時器值小於負載均衡器的情況)
image.png

因此,為了防止發送目的地的 HTTP Keep-Alive 超時,需按照之前所述,將「客戶端⇔負載均衡器」和「負載均衡器⇔伺服器」的連接界別中,計時器值設計成扇形(即越往前的值越大,範圍越廣)。
(以下是若在扇型設計中檢測到超時時的處理示例)
image.png

【補充】
以下整理了 ALB 可設定的 TCP 空閒超時/HTTP Keep-Alive 超時的可設定參數,注意後端的 HTTP Keep-Alive 超時值實際上會與「空閒超時」相同的觀點。

  • 根據 ALB 當前的規範,所設置的「空閒超時」設置值會強制應用於後端側。
  • 這樣一來,即使在後端也延長了 HTTP Keep-Alive 超時,其優先級為「空閒超時」,而在超時發生時會導致連接被切斷。
目標連接 設置目標參數 目標參數設定項目名 調整可否 說明
HTTP 客戶端 ⇔ ALB 之間(前端) TCP 空閒超時 空閒超時 L4 層(TCP IdleTimeout),預設 60 秒。範圍在 1~4000 秒之內設置。不過後端會以共通的設定值適用。
HTTP Keep-Alive 超時 HTTP 客戶端的 Keep-Alive 期間 可調整 預設 3600 秒,範圍在 60~604800 秒(7天)之內設置。
ALB ⇔ 後端目標之間(後端) TCP 空閒超時 空閒超時 前端會以共通的設定值適用。
HTTP Keep-Alive 超時 HTTP 客戶端的 Keep-Alive 期間 自動應用「空閒超時」的設置值。

(2)會話計時器設計

首先,當發生會話超時時,通常會出現何種行為(如何設計)如下整理。

  1. 伺服器端將該會話信息視為內部無效化(過期),※此時不會進行任何通訊
  2. 客戶端發送下一個 HTTP 請求。
    • →伺服器端在收到該請求後,會與會話管理信息進行對照,視為該請求的會話無效
  3. 不會將該請求視為「系統錯誤」,而是提示客戶端進行如下處理:
    • 例如返回 302 響應,並重定向至登錄畫面等。
    • 在該請求中進行的業務處理將根據處理狀況執行回滾,使業務上不會有問題的狀態。

【參考】
由於僅是會話信息的超時處理,因此即使在 HTTP Keep-Alive 有效期間內發生會話超時,仍會利用既有的 TCP 連接進行運作(不會發生連接錯誤等情況)。

以上整理可與之前提到的連接/事務超時值保持獨立,但若會話超時值設置過短,則必須頻繁進行認證處理,因此應根據實用性與業務特性設置(對於 WEB 在線系統而言,通常將設置為數十分鐘至 1 小時)。

總結

本文解釋了 Web 系統中超時設計的重要性及具體的設計理論。在設計時需要意識到的要點如下:

  • 區分 L4 和 L7 的角色:將 TCP Keep-Alive 設置為比中間設備的 IdleTimeout 短,以防止意外斷開。
  • 事務保持「漏斗型」:前段(客戶端)的等待時間應比後段更長,防止在處理完畢之前發生超時。
  • HTTP Keep-Alive 為「扇型」:後段(伺服器)的有效期限應比前段更長,以防止重用時發生通訊錯誤。
  • 會話依據業務特性進行判斷:考慮認證持續的便利性與安全性之間的平衡。

原文出處:https://qiita.com/k2-irie/items/131672361b68c831f00d


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝8   💬7   ❤️5
241
🥈
我愛JS
📝1   💬8   ❤️2
62
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付