すべてのプロダクト
Search
ドキュメントセンター

Server Load Balancer:接続ドレインの設定

最終更新日:Oct 22, 2026

バックエンドサーバーを削除したり、ヘルスチェックに失敗したりした場合でも、確立済みの接続はすぐには終了しません。これらの接続を突然切断すると、処理中のリクエストが中断され、サービスのグレースフルシャットダウンが妨げられる可能性があります。この問題を回避するために、Application Load Balancer (ALB) の接続ドレイン機能を使用できます。バックエンドサーバーが削除されたり、ヘルスチェックに失敗したりすると、接続ドレインは設定された期間、既存の接続をアクティブに保ちます。タイムアウト期間が経過すると、ALB は接続を閉じて、グレースフルシャットダウンを確実に行います。

利用シーン

接続ドレインは、以下の 2 つのシナリオに適用されます。

  • バックエンドサーバーの削除:バックエンドサーバーを削除する前に、接続ドレインのタイムアウトを長めに設定して、処理中のリクエストが完了できるようにします。

  • ヘルスチェックの失敗:ヘルスチェックに失敗したバックエンドサーバーについては、タイムアウトを短めに設定して、障害のある接続を迅速に終了させ、クライアントが接続エラーを受け取らないようにします。

両方のシナリオで同じ接続ドレイン設定が共有されるため、ビジネス要件に適したタイムアウトを設定する必要があります。

バックエンドサーバーの削除

次の図は一例です。バックエンドサーバー ECS01 を削除すると、ALB は新しいリクエストの送信を停止します。ECS01 は処理中のリクエストのみを処理し、新しいリクエストは受け入れません。

  • 接続ドレインが無効の場合、ECS01 はすべての処理中のリクエストが処理された後にのみセッションを閉じます。

  • 接続ドレインが有効で、タイムアウトが設定されている場合:

    • 削除されたバックエンドサーバー ECS01 に処理中のリクエストがある場合、ALB は接続ドレインのタイムアウトが経過した後に ECS01 上の既存のセッションを閉じます。

    • 削除されたバックエンドサーバー ECS01 に処理中のリクエストやアクティブな接続がない場合、ALB は接続ドレインのタイムアウトを待たずに、すぐに削除プロセスを完了します。

    • 削除プロセスが終了した時点で、削除されたバックエンドサーバー ECS01 がリクエストを処理中の場合、接続は終了し、クライアントは 500 エラー応答を受け取ります。たとえば、接続ドレインのタイムアウトが 15 秒に設定されているが、ECS01 でのリクエスト処理時間が 30 秒の場合、ECS01 が応答を送信する前に接続が終了します。この場合、クライアントは 500 エラー応答を受け取ります。

    説明

    ECS01 をサーバーグループに再追加しても、すでにドレイン中のセッションには影響しません。ECS01 は、既存のセッションが閉じられるまでドレイン状態のままであり、処理中のリクエストのみを処理します。ALB は、接続ドレインのタイムアウトが経過すると、これらのセッションを閉じます。

次の図は、接続ドレインが有効なサーバーグループから ECS01 が削除された後の状態遷移を示しています。

ヘルスチェックの失敗

バックエンドサーバー ECS01 がヘルスチェックに失敗すると、ALB は新しいリクエストの送信を停止します。ECS01 は処理中のリクエストのみを処理し、新しいリクエストは受け入れません。

  • 接続ドレインが無効の場合、ECS01 はヘルスチェックに合格するまでこの状態を維持します。合格後、新しいリクエストの受け入れを開始します。

  • 接続ドレインが有効で、タイムアウトが設定されている場合:

    • ALB は、接続ドレインのタイムアウトが経過した後に ECS01 上の既存のセッションを閉じます。

    • サーバーグループを更新した場合 (たとえば、ECS01 の構成を変更した場合)、その接続状態は変わりません。処理中のリクエストのみを処理し続けます。更新後に ECS01 がヘルスチェックに合格したとしても、ALB は接続ドレインのタイムアウトが経過すると既存のセッションを閉じます。

    説明
    • 接続ドレインのタイムアウトが経過し、ALB がセッションを閉じた後、ECS01 が新しいリクエストを受け入れることができるのは、ヘルスチェックに合格した場合のみです。失敗し続ける場合、新しいリクエストは受け入れません。

    • 接続ドレインは、バックエンドサービスの課題によって引き起こされるヘルスチェックの失敗によってのみトリガーされ、構成の更新に起因する失敗ではトリガーされません。

    次の図は、ECS01 がヘルスチェックに失敗した後の状態遷移を示しています。

ビジネスシナリオに基づいて接続ドレインを設定できます。このトピックでは、シナリオ 1:バックエンドサーバーの削除を例に、WebSocket と HTTP セッションの終了を設定する方法を説明します。

注意事項

  • 接続ドレインをサポートするのは、標準および WAF 有効の ALB インスタンスのみで、ベーシック ALB インスタンスはサポートしていません。

  • Function Compute サーバーグループは接続ドレインをサポートしていません。

  • 接続ドレインは WebSocket と HTTP の両方のセッションに有効です。HTTP セッションの場合、リクエストが予期せず閉じられるのを防ぐため、接続ドレインのタイムアウトを ALB の接続リクエストタイムアウトより大きい値に設定することを推奨します。デフォルトのタイムアウト値は、すでにこの推奨に従っています。接続リクエストタイムアウトの設定方法については、「HTTP リスナーの追加」をご参照ください。

前提条件

  • 標準または WAF 有効の ALB インスタンスが作成され、その ALB インスタンス用にサーバータイプのサーバーグループが作成されていること。このトピックでは、標準 ALB インスタンスを例として使用します。詳細については、「ALB インスタンスの作成」および「サーバーグループの作成と管理」をご参照ください。

  • ALB インスタンスのポート 80 に HTTP リスナーを設定し、それをサーバーグループに関連付けていること。詳細については、「HTTP リスナーの追加」をご参照ください。

  • 2 つのバックエンドサーバー ECS01 と ECS02 を作成していること。詳細については、「ウィザードを使用したインスタンスの作成」をご参照ください。

  • ECS02 をサーバーグループに追加し、クライアントからアクセス可能であること。詳細については、「ALB を使用した IPv4 サービスの負荷分散の実現」および「ALB を使用した IPv6 サービスの負荷分散の実現」をご参照ください。

    説明
    • このトピックでは、クライアントとして Alibaba Cloud Linux 3.2104 64 ビットオペレーティングシステムを使用します。クライアントとバックエンドサーバー ECS01 の両方に Python がインストールされていることを確認してください。Python がインストールされていない場合は、Python 公式ウェブサイトの手順をご参照ください。このトピックでは、Python 3.x を例として使用します。

    • このトピックでは、ECS02 は本番トラフィックを処理するバックエンドサーバーです。すでにそのようなバックエンドサーバーがある場合は、作成する必要はありません。

操作手順

接続ドレインを有効にし、タイムアウト期間を設定した後、このトピックでは、ALB がさまざまな接続ドレイン状態で WebSocket および HTTP セッションのリクエストをどのように処理するかを説明します。

WebSocket セッション

ステップ 1:接続ドレインの有効化

前提条件としてサーバーグループが作成されています。このステップでは、既存のサーバーグループで接続ドレインを有効にする方法を示します。この機能は、サーバーグループを作成する際にも有効にできます。

  1. ALB コンソールにログインします。

  2. 上部のナビゲーションバーで、サーバーグループがデプロイされているリージョンを選択します。

  3. 左側のナビゲーションウィンドウで、ALB > サーバーグループ を選択します。

  4. サーバーグループ ページで、目的のサーバーグループを見つけ、その ID をクリックします。

  5. 詳細 タブの 基本情報 セクションで、サーバーグループの編集 をクリックします。

  6. サーバーグループの編集 ダイアログボックスで、詳細設定 をクリックし、接続ドレイン を有効にします。

  7. グレースフル・シャットダウンのタイムアウト を 300 秒に設定し、保存 をクリックします。

ステップ 2:結果の検証

サーバーの設定

  1. ECS01 インスタンスにログインします。詳細については、「接続方法」をご参照ください。

  2. 次のコマンドを実行して、WebSocket ディレクトリを作成し、そのディレクトリに移動します。

    mkdir WebSocket
    cd WebSocket
  3. 次のコマンドを実行して、依存関係をインストールします。

    pip install tornado
    pip install websocket-client
  4. 次のコマンドを実行して、server.py 設定ファイルを編集します。

    vim server.py
    1. i キーを押して編集モードに入り、次の設定を追加して WebSocket サービスを開始します。

      #!/usr/bin/env python3
      # encoding=utf-8
      
      import tornado.websocket
      import tornado.ioloop
      import tornado.web
      from datetime import datetime
      
      
      # WebSocket handler
      class WebSocketHandler(tornado.websocket.WebSocketHandler):
          def open(self):
              current_time = datetime.now()
              formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
              print("Time:", formatted_time, "WebSocket connection opened")
      
          def on_message(self, message):
              current_time = datetime.now()
              formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
              print("Time:", formatted_time, "Received message:", message)
              self.write_message("Server received your message: " + message)
      
          def on_close(self):
              current_time = datetime.now()
              formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
              print("Time:", formatted_time, "WebSocket connection closed")
      
      # Routing
      application = tornado.web.Application([
          (r"/websocket", WebSocketHandler),
      ])
      
      if __name__ == "__main__":
          print("WebSocket Server Start on 8080 ...")
          application.listen(8080)
          tornado.ioloop.IOLoop.current().start()
      
    2. 設定ファイルを変更した後、Esc キーを押し、:wq と入力してから Enter キーを押してファイルを保存し、閉じます。

  5. server.py が保存されているディレクトリに移動し、次のコマンドを実行して WebSocket サービスを開始します。

    python3 server.py

    次の応答は、WebSocket バックエンドサービスが開始されたことを示します。

    Websocket Server Start on 8080 ...

ECS01 をサーバーグループに追加

  1. ALB コンソールにログインします。

  2. 上部のナビゲーションバーで、サーバーグループがデプロイされているリージョンを選択します。

  3. 左側のナビゲーションウィンドウで、ALB > サーバーグループ を選択します。

  4. サーバーグループ ページで、対象のサーバーグループを見つけ、操作 列の バックエンドサーバーの変更 をクリックします。

  5. バックエンドサーバー タブで、バックエンドサーバーの追加 をクリックします。バックエンドサーバーの追加 パネルで、ECS01 を選択し、次のステップ をクリックします。

  6. ポート/重み ステップで、ECS01 インスタンスを選択し、ポートを 8080 に設定し、次に OK をクリックします。

クライアントの設定

  1. クライアントにログインし、コマンドラインインターフェイス (CLI) を開きます。次のコマンドを実行して、WebSocket ディレクトリを作成し、そのディレクトリに移動します。

    mkdir WebSocket
    cd WebSocket
  2. 次のコマンドを実行して、依存関係をインストールします。

    pip install websocket-client
  3. 次のコマンドを実行して、client.py ファイルを編集します。

    vim client.py
    1. i キーを押して編集モードに入り、次の設定を追加して WebSocket クライアントを起動し、サービスにアクセスします。

      #!/usr/bin/env python3
      # encoding=utf-8
      
      import websocket
      import time
      from datetime import datetime
      
      def on_message(ws, message):
          print("Received message from server:", message)
      
      if __name__ == "__main__":
          ws = websocket.WebSocket()
          ws.connect("ws://<domain_name>:80/websocket") # <domain_name> を実際のドメイン名に置き換えてください。
          print("WebSocket connection opened")
          try:
              while True:
                  current_time = datetime.now()
                  formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
                  print("Sending time:", formatted_time)
                  ws.send("Hello, Server!")
                  result = ws.recv()
                  on_message(ws, result)
                  time.sleep(1)
          except Exception:
              print("WebSocket connection closed")
      
    2. 設定ファイルを変更した後、Esc キーを押し、:wq と入力してから Enter キーを押してファイルを保存し、閉じます。

  4. client.py が保存されているディレクトリに移動し、次のコマンドを実行して ECS01 バックエンドサーバーにアクセスします。

    python3 client.py

    次の応答は、アクセスが成功したことを示します。

    WebSocket connection opened
    Sending time: 2024-04-28 17:00:53
    Received message from server: Server received your message: Hello, Server!
    Sending time: 2024-04-28 17:00:54
    Received message from server: Server received your message: Hello, Server!

    ECS01 バックエンドサーバーは次の応答を返します。

    WebSocket Server Start on 8080 ...
    Time: 2024-04-28 17:00:53 WebSocket connection opened
    Time: 2024-04-28 17:00:53 Received message: Hello, Server!
    Time: 2024-04-28 17:00:54 Received message: Hello, Server!

バックエンドサーバーの削除

重要

バックエンドサーバーを削除する前に、接続ドレインのタイムアウトを設定してください。

  1. ALB コンソールにログインします。

  2. 上部のナビゲーションバーで、サーバーグループがデプロイされているリージョンを選択します。

  3. 左側のナビゲーションウィンドウで、ALB > サーバーグループ を選択します。

  4. 対象のサーバーグループを見つけ、その ID をクリックします。

  5. バックエンドサーバー タブをクリックして、目的のバックエンドサーバー ECS01 を探し、削除 を 操作 列でクリックします。

  6. 削除 ダイアログボックスで、OK をクリックします。

接続ドレインの待機

タイムアウト期間は 300 秒に設定されています。テスト結果は、ECS01 が削除されてから約 300 秒後に ALB がセッションを終了することを示しています。

説明

テスト結果では、ECS01 サーバー上の WebSocket 接続が開かれてから閉じられるまでの時間差は 330 秒です。バックエンドサーバー ECS01 が削除されてから WebSocket 接続が閉じられるまでの接続ドレインのタイムアウト期間は、約 300 秒です。

  • クライアントは次の応答を返します。

    Sending time: 2024-04-28 17:06:23
    Received message from server: Server received your message: Hello, Server!
    Sending time: 2024-04-28 17:06:24
    WebSocket connection closed
  • ECS01 サーバーインスタンスは次の応答を返します。

    Time: 2024-04-28 17:06:22 Received message: Hello, Server!
    Time: 2024-04-28 17:06:23 Received message: Hello, Server!
    Time: 2024-04-28 17:06:23 WebSocket connection closed

HTTP セッション

HTTP シナリオでは、クライアントが受け取る応答は、接続ドレインのタイムアウト、接続リクエストタイムアウト、およびバックエンドサーバーの処理時間の設定によって異なります。

  • 接続ドレインのタイムアウトがバックエンドサーバーの処理時間より短い場合、ECS01 が応答を送信する前に接続が中断されます。この場合、クライアントは 500 エラー応答を受け取ります。

  • バックエンドサーバーの処理時間が接続リクエストタイムアウトより長い場合、ECS01 へのリクエストはタイムアウトします。この場合、クライアントは 504 エラー応答を受け取ります。

このトピックでは、接続ドレインのタイムアウトが 15 秒、バックエンドサーバーの処理時間が 30 秒の例を使用します。このシナリオでは、ECS01 が応答を送信し終える前に接続が中断され、クライアントは 500 エラー応答を受け取ります。

説明
  • 接続リクエストタイムアウト (60 秒、ステップ 2 で設定) がバックエンドサーバーの処理時間 (30 秒) よりも長いため、504 エラーは返されません。代わりに、接続ドレインのタイムアウト (15 秒) がサーバーの処理時間よりも短いため、500 エラーが発生します。

  • このトピックでは、Python コードの time.sleep 関数を使用して、バックエンドサーバーの処理時間をシミュレートします。

ステップ 1:接続ドレインの有効化

前提条件としてサーバーグループが作成されています。このステップでは、既存のサーバーグループで接続ドレインを有効にする方法を示します。この機能は、サーバーグループを作成する際にも有効にできます。

  1. ALB コンソールにログインします。

  2. 上部のナビゲーションバーで、サーバーグループがデプロイされているリージョンを選択します。

  3. 左側のナビゲーションウィンドウで、ALB > サーバーグループ を選択します。

  4. サーバーグループ ページで、対象のサーバーグループを探し、その ID をクリックします。

  5. 詳細 タブの 基本情報 セクションで、サーバーグループの編集 をクリックします。

  6. サーバーグループの編集 ダイアログボックスで、詳細設定 をクリックし、接続ドレイン を有効にします。

  7. グレースフル・シャットダウンのタイムアウト を 15 秒に設定し、保存 をクリックします。

ステップ 2:ALB リクエストタイムアウトの設定

  1. ALB コンソールにログインします。

  2. 上部のナビゲーションバーで、ALB インスタンスがデプロイされているリージョンを選択します。

  3. インスタンス ページで、対象の ALB インスタンスを見つけ、その ID をクリックします。

  4. リスナー タブをクリックし、目的の HTTP リスナーを探し、その ID をクリックします。

  5. 基本情報 エリアで、リスナーの変更 をクリックします。

  6. リスナーの変更 ダイアログボックスで、詳細設定 の横にある 変更 をクリックします。

  7. 接続リクエストタイムアウト を 60 秒(デフォルト値)に設定し、保存 をクリックします。

ステップ 3:DNS 設定の構成

本番環境では、CNAME レコードを作成して、カスタムドメイン名を ALB インスタンスのドメイン名にマッピングすることを推奨します。

  1. 左側のナビゲーションウィンドウで、ALB > インスタンスを選択します。

  2. インスタンス ページで、作成した ALB インスタンスの DNS 名をコピーします。

  3. 以下の手順に従って CNAME レコードを追加します。

    説明

    ドメイン名が Alibaba Cloud 以外のプロバイダーによって登録されている場合は、DNS 設定を構成する前に、ドメイン名を Alibaba Cloud DNS コンソールに追加する必要があります。詳細については、「ドメイン名の管理」をご参照ください。ドメイン名が Alibaba Cloud に登録されている場合は、次の手順に進んでください。

    1. Alibaba Cloud DNS コンソールにログインします。

    2. インターネットの権威ある DNS 解決 ページで、目的のドメイン名を見つけ、操作 列の 解決設定 をクリックします。

    3. 解決設定 ページで、Add Record をクリックします。

    4. Add Record パネルで、次のパラメーターを設定して CNAME レコードを構成し、OK をクリックします。

      パラメーター

      説明

      レコードタイプ

      ドロップダウンリストから CNAME を選択します。

      ホストレコード

      ドメイン名のプレフィックス。このチュートリアルでは @ を使用します。

      説明

      ルートドメインを使用するには、ホスト名を @ に設定します。

      Query Source

      デフォルトを選択します。

      レコード値

      コピーした ALB インスタンスの DNS 名を入力します。

      TTL

      Time to Live (TTL) は、DNS レコードが DNS サーバーにキャッシュされる期間です。デフォルト値を使用します。

ステップ 4:結果の検証

サーバーの設定

  1. ECS01 インスタンスにログインします。詳細については、「接続方法」をご参照ください。

  2. 次のコマンドを実行して、http ディレクトリを作成し、そのディレクトリに移動します。

    mkdir http
    cd http
  3. 次のコマンドを実行して、http_server.py 設定ファイルを編集します。

    vim http_server.py
    1. i キーを押して編集モードに入り、次の設定を追加して HTTP サーバーサービスを開始します。

      #!/usr/bin/env python3
      # encoding=utf-8
      
      from http.server import SimpleHTTPRequestHandler, HTTPServer
      from datetime import datetime
      import time
      
      class DelayedHTTPRequestHandler(SimpleHTTPRequestHandler):
          def do_GET(self):
              current_time = datetime.now()
              formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
              print("Time:", formatted_time, "GET request received. Responding after a 30-second delay....")
              time.sleep(30) # time.sleep 関数を使用して、バックエンドサーバーの処理時間をシミュレートします。
              SimpleHTTPRequestHandler.do_GET(self)
      
      PORT = 8080
      server = HTTPServer(("", PORT), DelayedHTTPRequestHandler)
      print(f"Serving HTTP on 0.0.0.0 port {PORT} (http://0.0.0.0:{PORT}/) ...")
      server.serve_forever()
      
    2. 設定ファイルを変更した後、Esc キーを押し、:wq と入力してから Enter キーを押してファイルを保存し、閉じます。

  4. http_server.py が保存されているディレクトリに移動し、次のコマンドを実行して HTTP サーバーサービスを開始します。

    python3 http_server.py

    次の応答は、HTTP サーバーのバックエンドサービスが開始されたことを示します。

    Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...

ECS01 をサーバーグループに追加

  1. ALB コンソールにログインします。

  2. 上部のナビゲーションバーで、サーバーグループがデプロイされているリージョンを選択します。

  3. サーバーグループ ページで、目的のサーバーグループを見つけ、操作 列の バックエンドサーバーの変更 をクリックします。

  4. バックエンドサーバー タブで、バックエンドサーバーの追加 をクリックします。バックエンドサーバーの追加 パネルで、ECS01 を選択し、次のステップ をクリックします。

  5. ポート/重み ステップで、ECS01 インスタンスを選択し、ポートを 8080 に設定し、次に OK をクリックします。

クライアントの設定

  1. クライアントにログインし、CLI を開きます。次のコマンドを実行して、バックエンドサーバー ECS01 にアクセスします。

    curl http://<domain_name>:80/ -v

    次の応答は、ALB がバックエンドサービスにアクセスできることを示します。

    * About to connect() to www.example.com port 80 (#0)
    *   Trying 10.X.X.225...
    * Connected to www.example.com (10.X.X.225) port 80 (#0)
    > GET / HTTP/1.1
    > User-Agent: curl/7.29.0
    > Host: www.example.com
    > Accept: */*

    サーバーは次の応答を返します。

    Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
    Time: 2024-02-07 13:57:33 Received a GET request. Responding after a 30-second delay....

バックエンドサーバーの削除

重要

バックエンドサーバーを削除する前に、接続ドレインのタイムアウトを設定してください。

  1. ALB コンソールにログインします。

  2. 上部のナビゲーションバーで、サーバーグループがデプロイされているリージョンを選択します。

  3. 左側のナビゲーションウィンドウで、ALB > サーバーグループ を選択します。

  4. 対象のサーバーグループを見つけ、その ID をクリックします。

  5. バックエンドサーバー タブをクリックし、対象のバックエンドサーバー ECS01 を探し、操作 列の 削除 をクリックします。

  6. 削除 ダイアログボックスで、OK をクリックします。

接続ドレインの待機

テスト結果は、ALB に設定された接続ドレインのタイムアウトがバックエンドサーバーの処理時間よりも短い場合、クライアントが 500 エラー応答を受け取ることを示しています。

* About to connect() to www.example.com port 80 (#0)
*   Trying 10.X.X.224...
* Connected to www.example.com (10.XX.XX.224) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.example.com
> Accept: */*
> 
< HTTP/1.1 500 Internal Server Error
< Date: Wed, 07 Feb 2024 06:02:24 GMT
< Content-Type: text/html
< Content-Length: 186
< Connection: close
< Via: HTTP/1.1 SLB.87
< 
<html>
<head><title>500 Internal Server Error</title></head>
<body bgcolor="white">
<center><h1>500 Internal Server Error</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Closing connection 0

関連ドキュメント