Client <--> ALB <--> proxy(nginx) <--> App の構成でkeepalive timeoutをどう設定するのか...
ALBで設定できる項目
idle_timeout.timeout_seconds
ターゲットとのkeepaliveのtimeout。デフォルトは60秒。
client_keep_alive.seconds
クライアントとのkeepaliveのtimeout。デフォルトは3600秒。
ALB、nginxの設定内容
以下が推奨設定
キープアライブ (Apache の KeepAlive、NGINX の keepalive_disable)
CPU 使用率を削減し、応答時間を改善するには、キープアライブをオンにします。キープアライブをオンにすると、ロードバランサーで、HTTP リクエストの度に新しい TCP 接続を確立する必要がありません
キープアライブタイムアウト (Apache の KeepAliveTimeout、NGINX の keepalive_timeout)
キープアライブオプションが有効になっている場合は、ロードバランサーのアイドルタイムアウトよりも長いキープアライブタイムアウトを選択します。
読み取りタイムアウト (Apache の RequestReadTimeout、NGINX の client_header_timeout と client_body_timeout)
アプリケーションの応答時間に合わせて読み取りタイムアウトを設定します。こうすることで、ロードバランサーがリクエストのヘッダーとボディの両方を受信するために、接続を十分な時間開いたままにしておくことができます。
とのこと。
nginxはkeepalive_timeoutを0に設定すると無効になる(リクエスト毎にTCPのコネクションをcloseする)。 何も設定していなければデフォルトの60秒になるため、keepaliveはもちろん有効である。
キープアライブオプションが有効になっている場合は、ロードバランサーのアイドルタイムアウトよりも長いキープアライブタイムアウトを選択します。
nginxのkeepalive_timeoutが60秒であれば、idle_timeout.timeout_secondsはそれより短い値が推奨値となる。
読み取りタイムアウト (Apache の RequestReadTimeout、NGINX の client_header_timeout と client_body_timeout)
client_header_timeoutとclient_body_timeoutはnginxのクライアント(ここではALB)からのリクエストに対する設定となる。
client_header_timeout
If a client does not transmit the entire header within this time, the request is terminated with the 408 (Request Time-out) error.
とのこと。ALB -> nginxのリクエストのヘッダにそんな大きなものはないので、デフォルトの60秒でよいだろう。
client_body_timeout
If a client does not transmit anything within this time, the request is terminated with the 408 (Request Time-out) error.
とのこと。ALB -> nginxでデフォルトの60秒以内になにも送らないということは現状発生していないので、デフォルトのままにしておく。
ALBのclient_keep_alive.secondsは、ロードバランサーがリクエストのヘッダーとボディの両方を受信するために、接続を十分な時間開いたままにしておくことができます。
とのことなので、デフォルトの3600秒は十分に長い。特に問題も起きていないのでこのままにしておく。
TCP keepaliveとHTTP keepalive
参考
TCP keepalive
TCP keepaliveは以下に定義してある
- コネクションがアイドル状態になってから一定時間が立つとkeepalive probe(ペイロードが空のACKのリクエスト)を送る
- keepalive probeを受け取ったらACKで応答する
- ペイロードに1オクテット(バイト)のデータを入れても良い(空だと送れないものもある)
- probeの応答がなくなったらRSTを送ってコネクションを切断する
HTTP keepalive
コネクションが確立している状態であれば、3-wayハンドシェイクなしでHTTPのリクエストをTCPセグメントで送るようにする機能。
その際に Connection: keep-alive
のヘッダが付与される。
この Connection: keep-alive
ヘッダがあれば、新しいコネクションではなく、すでに確立しているコネクションを使うようにサーバ側が対応する。
明示的にコネクションを切断する場合、Connection: close
ヘッダを付与してリクエストを出すとTCPのコネクションが切断するように処理される。
HTTP/2では1つのTCPのコネクション内で複数のリクエスト・レスポンスを送る(Multiplexing)ので、HTTP keepaliveというものは存在しない(デフォルトでコネクションを維持する設計になっている)。