ALBのHTTPキープアライブ最適化による画面フリーズ問題の解決実践例

富士通株式会社 ジャパン・グローバルゲートウェイ Public & Social ITS Division　小沼 真実

# はじめに
AWS環境にスケーラブルで可用性の高いWebシステムを構築する際、負荷分散装置（ロードバランサー）として欠かせないのが、Application Load Balancer（以降、ALB）やNetwork Load Balancer（以降、NLB）など、Elastic Load Balancing （以降、ELB）になります。
ALBやNLBなどは、AWSマネージメントコンソールから比較的簡単に作成できますが、その中にはいくつか設定項目を持っているため、構築するWebシステムの特性に合わせて変更していく必要があります。
そのALBの設定値である「HTTPクライアントのキープアライブ期間」をデフォルトから変更しなかったため、あるWebシステムで画面フリーズ事象が発生することになりました。本記事では、その問題を解決した時の状況を実践例として紹介しますので、適切に設定するための参考になれば幸いです。

# 目次
　１．[ELBの種類](https://qiita.com/Masami_Konuma/items/89cfe7024fafa5e38c26#%EF%BC%91elb%E3%81%AE%E7%A8%AE%E9%A1%9E)
　２．[ALBとは？](https://qiita.com/Masami_Konuma/items/89cfe7024fafa5e38c26#%EF%BC%92alb%E3%81%A8%E3%81%AF)
　３．[ALBの設定](https://qiita.com/Masami_Konuma/items/89cfe7024fafa5e38c26#%EF%BC%93alb%E3%81%AE%E8%A8%AD%E5%AE%9A)
　４．[TCPキープアライブとHTTPキープアライブの違い](https://qiita.com/Masami_Konuma/items/89cfe7024fafa5e38c26#%EF%BC%94tcp%E3%82%AD%E3%83%BC%E3%83%97%E3%82%A2%E3%83%A9%E3%82%A4%E3%83%96%E3%81%A8http%E3%82%AD%E3%83%BC%E3%83%97%E3%82%A2%E3%83%A9%E3%82%A4%E3%83%96%E3%81%AE%E9%81%95%E3%81%84)
　５．[HTTPキープアライブの設定](https://qiita.com/Masami_Konuma/items/89cfe7024fafa5e38c26#%EF%BC%95http%E3%82%AD%E3%83%BC%E3%83%97%E3%82%A2%E3%83%A9%E3%82%A4%E3%83%96%E3%81%AE%E8%A8%AD%E5%AE%9A)
　６．[HTTPキープアライブ最適化による問題解決](https://qiita.com/Masami_Konuma/items/89cfe7024fafa5e38c26#%EF%BC%96http%E3%82%AD%E3%83%BC%E3%83%97%E3%82%A2%E3%83%A9%E3%82%A4%E3%83%96%E6%9C%80%E9%81%A9%E5%8C%96%E3%81%AB%E3%82%88%E3%82%8B%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA)
　７．[まとめ](https://qiita.com/Masami_Konuma/items/89cfe7024fafa5e38c26#%EF%BC%97%E3%81%BE%E3%81%A8%E3%82%81)

# １．ELBの種類
ELBにカテゴライズされる各種ロードバランサーについて、以下の表に整理します。アプリケーションの形態に応じて、最適なロードバランサーを選択する必要があります。
オーソドックスなWebアプリケーションの場合は、ALBを使用します。非常に高度なパフォーマンスと静的 IP がアプリケーションで必要な場合は、NLBを使用します。サードパーティのセキュリティ製品などを利用する場合は、Gateway Load Barancer（以降、GWLB）を使用します。その他、EC2-Classic ネットワーク内で構築された既存のアプリケーションがある場合は、Classic Load Balancer（以降、CLB）を使用します。

|№|機能|ALB|NLB|GWLB|CLB|
|:---:|----|----|----|----|----|
|1|ロードバランサーの種類|レイヤー7|レイヤー4|レイヤー3 Gateway<br>＋レイヤー4 Load Balancing|レイヤー 4/7|
|2|ターゲットの種類|IP、インスタンス、Lambda|IP、インスタンス、ALB|IP、インスタンス|－|
|3|フロー／プロキシの動作を終了する|あり|あり|なし|あり|
|4|プロトコルリスナー|HTTP、HTTPS、gRPC|TCP、UDP、TLS|IP|TCP、SSL/TLS、HTTP、HTTPS|
|5|右記を経由して到達可能|VIP|VIP|ルートテーブルのエントリ|－|
|6|暖気運転<br>（急激なスパイクへの対応）|申請必要|申請不要<br>（AWS Hyperplaneという特殊な負荷分散技術を使用）|－|－|

# ２．ALBとは？
ALBはリクエストレベル（レイヤー7）で動作し、トラフィックをリクエストの内容に基づいて、ターゲット（EC2やコンテナ、IP アドレス、Lambdaなど）にルーティングします。HTTP及びHTTPS トラフィックの負荷分散に適したALBは、ターゲットグループに設定したマイクロサービスやコンテナベースのアプリケーションに対し、リクエストルーティングを実施します。
ALBでは、AWS Certificate Manager（以降、ACM）と連携してサーバ証明書を利用し、SSL/TLS 暗号化とプロトコルを常に使用することで、アプリケーションのセキュリティを向上することができます。

![ALB機能.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620338/b1b0c32d-f6c5-4e95-bf00-98a4d958ea0f.jpeg)

# ３．ALBの設定
ALBはリクエスト属性に基づいて、着信HTTP及びHTTPSトラフィックを複数のターゲット（EC2やコンテナ、IP アドレス、Lambdaなど）に分散します。
ロードバランサーは接続リクエストを受け取ると、優先度順にリスナールールールを評価して適用するルールを決定し、該当する場合は、ルールアクションのターゲットグループからターゲットを選択します。

|№|設定種別|設定内容|
|:---:|----|----|
|1|基本的な設定|・ロードバランサー名<br>・スキーム（インターネット向け／内部）<br>・ロードバランサーのIPアドレスタイプ（IPv4／デュアルスタック／パブリックIPv4のないデュアルスタック）|
|2|ネットワークマッピング|・VPC<br>・IPプール（パブリック IPv4 アドレスに IPAM プールを使用する）<br>・アベイラビリティーゾーン及びサブネット|
|3|セキュリティグループ|・セキュリティグループ|
|4|リスナーとルーティング|・プロトコル<br>・ポート<br>・デフォルトアクション<br>・リスナータグ|
|5|AWS Web Application Firewall (以降、WAF)|・アプリケーション層のセキュリティ保護 – ターゲットの前（定義済みのWAFを自動作成／既存のWAF設定を使用する）<br>・ルールアクション（ブロック／カウント）<br>・リソースネーム（自動生成／カスタム名）|
|6|AWS Global Accelerator|・複数のリージョンにグローバル負荷分散を適用<br>・アクセラレータ名|

# ４．TCPキープアライブとHTTPキープアライブの違い
「キープアライブ」と聞くと、一定時間の無応答状態が続いた時タイムアウトする際に利用される「TCP」のキープアライブを先に思い浮かべる方が多いと思います。それとは別に「HTTP」のキープアライブという機能が存在し、それぞれ目的と役割が異なるため、両者の違いをよく理解しておく必要があります。

**■TCPキープアライブとは**
TCP キープアライブ とは、TCP コネクションを確立したホスト間において、通信開始からしばらくして相手からの通信が途絶えた際に、相手が活きているかを確認する仕組みです。TCP キープアライブ のメリットは、ネットワーク機器が原因による通信障害を確認し、不要なコネクションを開放できることです。

**■HTTPキープアライブとは**
HTTP キープアライブは、1つの TCP コネクションの中に複数の HTTP リクエストを実行できる機能です。これにより、通信の効率化が図れるというメリットがあります。TCP キープアライブ には ACK（肯定応答／確認応答）によるレスポンスがありますが、HTTPキープアライブにはそれがないため、コネクションを閉じるのではなく維持する、という意味合いになります。

つまり、ALBの設定値にある「HTTP クライアントのキープアライブ期間」とは、ALBがクライアントへの HTTP 接続を維持できる最大時間です。設定した HTTP クライアントのキープアライブ期間が過ぎると、ALBはもう 1 つのリクエストを受け入れ、接続を正常に終了するレスポンスを返します。

なお、ロードバランサーが送信するレスポンスのタイプは、クライアント接続で使用される HTTP のバージョンにより異なります。HTTP 1.x を使用して接続されたクライアントの場合、ロードバランサーはフィールド Connection: close を含む HTTP ヘッダーを送信します。HTTP/2を使用して接続されたクライアントの場合、ロードバランサーはGOAWAYフレームを送信します。

![TCP キープアライブとHTTP キープアライブの仕組みと違い.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620338/422b5124-1fee-463e-9dc7-b3a03195eba3.jpeg)

# ５．HTTPキープアライブの設定
ALBのHTTPクライアントのキープアライブ期間は、デフォルトで 3,600 秒（1 時間）に設定されています。この期間は、最小60 秒（1分間）から最大604,800 秒（7 日間）まで変更することができます。ただし、HTTPキープアライブ自体を無効にすることはできません。

HTTP クライアントのキープアライブ期間は、クライアントへの HTTP 接続が最初に確立された時点から開始されます。この期間中は、トラフィックの有無にかかわらず継続し、新しい接続が確立されるまでリセットされません。

HTTPクライアントのキープアライブ期間は、通信の効率性を追求することのトレードオフとして、TCPコネクションを確立し続けることにより、サーバ側は負荷が掛かるというデメリットも存在します。この設定を変更する場合、以下の流れで実施します。
AWSサポートに問い合わせした結果、この設定は動的に変更することが可能であり、現在接続しているクライアントに対し、強制的にコネクションが切断されるなどの影響はないそうです。

|№|操作パターン|操作内容|
|:---:|----|----|
|1|AWSマネージメントコンソールから変更する場合|AWSマネージメントコンソールにログインして、EC2 コンソール (https://console.aws.amazon.com/ec2/) を表示します。|
|2||ナビゲーションペインで、[ロードバランサー] を選択します。|
|3||設定を変更したいALBを選択します。|
|4||[属性] タブをクリックし、[編集] を選択します。|
|5||[トラフィックの設定] に HTTP クライアントのキープアライブ期間の値を入力します。デフォルト3,600秒で、変更可能な範囲は 60～604,800 秒です。|
|6||[変更の保存] をクリックします。|
|7|AWS CLI を使用して変更する場合|AWS CLI を使用してclient_keep_alive.seconds 属性を指定し、 modify-load-balancer-attributes コマンドを使用します。|

![HTTPキープアライブの設定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620338/abd356c2-24f3-41eb-a833-419404882fd9.jpeg)

# ６．HTTPキープアライブ最適化による問題解決
HTTPクライアントのキープアライブ期間は、設定時間に到達するとGOAWAYフレームを発出し、新しいコネクションへ切り替わるという動作が、設定した時間単位で周期的に実行されます。新しいコネクションへ切り替わるごとに、接続していたクライアントからの通信は切断されます。

GETリクエストのタイミングで通信が切断された場合はリトライが行われるため、クライアント側で認識することはありませんが、POSTリクエストのタイミングで通信が切断された場合はリトライが行われません。

あるWebシステムにおいて、画面のボタンを押下した時のPOSTリクエストが、HTTPキープアライブによるコネクションの切り替えのタイミングと重なった場合に、クライアントで画面フリーズ事象が発生しました。

![画面フリーズの発生状況.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620338/b31ef3c6-672f-4430-9e72-d5fbcbc17eff.jpeg)

この場合、HTTPクライアントのキープアライブ期間を延長することにより、新しいコネクションへ切り替わる頻度を下げることが可能です。あるWebシステムではデフォルトの3,600秒（1時間）→57,600秒（16時間）と変更することにより、サービス提供時間中（8:00～23:59）は、画面フリーズ事象の発生をほぼ無くすことに成功しました。

「ほぼ」とした理由は、リクエスト数が最大10,000を超過すると強制的にコネクションが切り替わるため、そのタイミングでPOSTリクエストが重なった場合、非常に低確率ですが、画面フリーズ事象が発生する可能性はあるためです。

HTTP/2接続では、いずれかのヘッダーの圧縮された長さが8Kバイトを超える場合、または1つの接続を介して処理されるリクエスト数が10,000を超える場合、GOAWAYフレームを送信し、TCP FINを使用して接続を閉じる仕様になっています。

![画面フリーズの解消結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620338/1b3df678-4e83-460a-8717-c095696c78fc.jpeg)

# ７．まとめ
今回は、ALBの設定値である「HTTPクライアントのキープアライブの期間」に関して解説してきましたが、いかがでしょうか？
TCPキープアライブとHTTPキープアライブの違いに気付かず、ALBの設定値をデフォルトのまま稼動しているWebシステムにおいて、その特性に合わせて設定変更が必要な場合もあるため、注意してください。
最後までお読みいただき、ありがとうございました。

# 参考文献
* 1：[[AWS Black Belt Online Seminar] Elastic Load Balancing (ELB) 資料及び QA 公開](https://aws.amazon.com/jp/blogs/news/webinar-bb-elastic-load-balancing-2019/)
* 2：[TCP Keep-Alive/http Keep-Aliveの仕組みと違い ～Client/Serverの挙動とメリット,設定～](https://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/keepalive-tcp-http/)
* 3：[HTTP クライアントのキープアライブ期間](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/edit-load-balancer-attributes.html#http-client-keep-alive-duration)
* 4：[Application Load Balancer のトラブルシューティング](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html#http-502-issues)