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

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

最終更新日:May 23, 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 リスナーの追加」をご参照ください。

  • バックエンドサーバー ECS01 および ECS02 が作成済みである必要があります。詳細については、「ウィザードを使用したインスタンスの作成」をご参照ください。

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

    説明
    • 本トピックでは、クライアントとして Alibaba Cloud Linux 3.2104 64 ビットオペレーティングシステムを使用します。ご利用のクライアントおよびバックエンドサーバー ECS01 の両方に Python がインストールされていることを確認してください。Python がインストールされていない場合は、公式 Python Web サイトの手順に従ってインストールしてください。本トピックでは、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 ハンドラ
      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")
      
      # ルーティング
      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 エラー応答を受け取ります。

説明
  • 504 エラーは返されません。これは、接続リクエストタイムアウトステップ 2 で設定された 60 秒)が バックエンドサーバーの処理時間(30 秒)よりも長いためです。代わりに、接続ドレインタイムアウト(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 インスタンスの DNS 名を指すように設定します。

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

  2. インスタンス ページで、ご利用の ALB インスタンスの DNS 名をコピーします。

  3. CNAME レコードを追加して、ご自身のドメイン名を ALB インスタンスの DNS 名にマッピングします。

    説明

    ご自身のドメイン名が 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

      TTL(Time to Live)は、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

関連ドキュメント