WebSocket は、単一の TCP 接続上で全二重の通信チャネルを提供するネットワークプロトコルです。クライアントとサーバーの間に永続的な接続を確立し、双方がいつでもデータを送受信できるようにします。これにより、新規接続を繰り返し確立する際のオーバーヘッドとレイテンシーを回避できるため、従来の HTTP リクエスト/レスポンスモデルより効率的です。WebSocket は主にリアルタイム通信を必要とするアプリケーションで使用されます。ALB はデフォルトで WebSocket プロトコルをサポートします。
WebSocket の概要
WebSocket を使用する理由
Web テクノロジーの進化に伴い、ライブチャットルームやリアルタイムコメントなどの機能では、サーバーがデータをリアルタイムにプッシュすることをアプリケーションに求めるケースが増えています。従来のポーリング方式では、クライアントのブラウザーが最新データを取得するために HTTP リクエストをサーバーへ繰り返し送信しますが、重大な欠点があります。大きな HTTP ヘッダーと小さなデータペイロードを伴うリクエストが頻発すると、サーバーの負荷が増大し、帯域幅を無駄に消費します。
これらの問題に対処するために、HTML5 ではクライアントとサーバー間の通信をより効率化するソリューションとして WebSocket プロトコルが導入されました。WebSocket は全二重通信をサポートしているため、サーバーとクライアントは同時にデータを送受信できます。これにより、サーバーはポーリングリクエストを待たずに、新しいデータをクライアントに能動的にプッシュできます。この双方向のリアルタイム通信メカニズムにより、データ転送の効率が向上し、不要なネットワークリクエストが減り、サーバーのリソースと帯域幅を節約でき、よりスムーズで応答性の高いユーザーエクスペリエンスを提供できます。
WebSocket の主な機能
通信は標準的な TCP 3 ウェイハンドシェイクで始まります。次に、クライアントはプロトコルアップグレードハンドシェイクと呼ばれる特別な HTTP リクエストを送信します。このハンドシェイクが成功すると、接続は HTTP から WebSocket に切り替わります。以降、クライアントとサーバー間のすべての通信では WebSocket プロトコルが使用され、同一の接続上で双方向のデータ交換が可能になります。
WebSocket 接続を確立すると、その接続はアクティブな状態のままになります。この永続的で低レイテンシーな接続により、継続的な双方向のデータ転送が可能になり、データ交換の効率が向上します。
WebSocket はデータフレームを使用して通信します。データフレームには簡潔なヘッダーを持つ独自のフレームプロトコル形式があります。データはテキストまたはバイナリとして送信できます。この方式により、永続的な接続におけるプロトコルオーバーヘッドが削減され、ネットワークのやり取りがより効率的になります。サーバーのリソースと帯域幅を節約しながら、よりスムーズなリアルタイムのインタラクティブエクスペリエンスを提供します。
WebSocket プロトコルの詳細については、公式ドキュメント「The WebSocket Protocol」をご参照ください。
WebSocket のユースケース
WebSocket は、AI アプリケーション、オンラインチャットルーム、リアルタイム通知システム、マルチプレイヤーオンラインゲーム、リアルタイムのマーケットデータフィードなど、高速でリアルタイムかつ双方向の通信を必要とするアプリケーションに最適です。
シナリオ例
ある企業が、Web ベースのオンラインチャットアプリケーションを Alibaba Cloud 上にデプロイしたいと考えています。ユーザーはドメイン名を通じてバックエンドサービスにアクセスし、リアルタイム通信を行います。インスタントメッセージングアプリケーションであるため、低レイテンシーかつ効率的なリアルタイムの双方向通信が必要です。
この企業の Web サイトサービスは、高い同時実行性と永続的な接続の管理という課題に直面しています。ユーザー数が増加するにつれて、従来の HTTP モデルでは、各インタラクションで新しい接続が必要になるため、リアルタイム通信で多数の同時接続ユーザーをサポートできません。これにより、サーバー負荷が急増し、パフォーマンスが低下します。
このシナリオでは、ALB を WebSocket プロトコルと組み合わせて使用することで、高い同時実行性のもとで永続的な接続を効果的に管理します。アプリケーションをサーバーグループにまたがってデプロイし、メッセージ同期に Redis を使用することで、高可用性を確保します。これにより、オンラインチャットルームアプリケーションに信頼性が高く効率的なリアルタイムメッセージングソリューションを提供します。
使用上の注意
ALB インスタンス上の HTTP リスナーは、デフォルトで WebSocket プロトコルをサポートします。 ALB はローリングアップデートをサポートしており、設定変更によって既存の永続的な接続が中断されることはありません。
次の点にご注意ください:
-
ALB インスタンスとバックエンドサーバー間の接続で HTTP/1.1 などの特定の HTTP バージョンを使用する場合、バックエンドサーバーもその HTTP バージョンをサポートすることを推奨します。
-
HTTP リスナーのデフォルトの接続リクエストタイムアウトは 60 秒です。 ALB とバックエンドサーバー間で 60 秒を超えてデータがやり取りされない場合、ALB は接続を閉じます。
-
デフォルトの 60 秒のタイムアウトでは不十分な場合、リスナーの 接続リクエストタイムアウト を変更できます。
-
接続を維持するには、少なくとも 60 秒に 1 回パケットを交換するキープアライブメカニズムを実装する必要があります。
-
前提条件
-
インターネット向けの ALB インスタンスが必要です。詳細については、「ALB インスタンスの作成と管理」をご参照ください。
-
3つの ECS インスタンス (ECS01、ECS02、ECS03) が必要です。
-
ECS01 と ECS02 は WebSocket アプリケーションのデプロイに、ECS03 は Redis のデプロイに使用します。
-
このチュートリアルでは、すべてのサーバーで CentOS 7.9 を実行します。
-
ECS01、ECS02、ECS03 を同じセキュリティグループに配置することを推奨します。異なるセキュリティグループに配置する場合は、サーバー間で必要な通信ポートのトラフィックを許可するルールを設定してください。
-
-
ICP 登録が完了した登録済みドメイン名が必要です。詳細については、「Alibaba Cloud ドメイン名の登録」および「ICP 登録」をご参照ください。
手順
手順1:サービスのデプロイ
ECS03 インスタンスに Redis を、ECS01 および ECS02 インスタンスに WebSocket アプリケーションをデプロイする必要があります。
このトピックでは、デモンストレーションとして、CentOS 7.9 上のシンプルな Python ベースのオンラインチャットルームを使用します。この例は参考用です。本番環境では、独自のアプリケーションを使用してください。
ECS03 への Redis のデプロイ
-
ECS03 インスタンスにログインします。
-
次のコマンドをコピーして実行し、Redis をインストールして設定します。
# EPEL (Extra Packages for Enterprise Linux) をインストール sudo yum install epel-release -y # Redis をインストール sudo yum install redis -y # Redis サービスを開始して有効化 sudo systemctl start redis sudo systemctl enable redis # リモート接続を許可するように Redis 設定ファイルを編集 sudo sed -i 's/^bind 127.0.0.1$/bind 0.0.0.0/' /etc/redis.conf sudo sed -i 's/^protected-mode yes/protected-mode no/' /etc/redis.conf # 変更を反映させるために Redis サービスを再起動 sudo systemctl restart redis # Redis のステータスを確認 sudo systemctl status redis -
コマンドがエラーなく実行され、出力に Redis サービスが アクティブ (実行中) 状態であると表示された場合、デプロイと設定は成功です。
● redis.service - Redis persistent key-value database Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled) Active: active (running) since ... Main PID: 12345 (redis-server) CGroup: /system.slice/redis.service └─12345 /usr/bin/redis-server 0.0.0.0:6379
ECS01 への WebSocket のデプロイ
-
ECS01 インスタンスにログインします。
-
sudo pip3 install flask flask-socketio flask-cors redisを実行して、依存関係をインストールします。 -
vi ECS01_ws.pyを実行し、iキーを押して編集モードに入ります。 -
次のコードをコピーして貼り付けます。
-
Escキーを押し、:wqと入力して変更を保存します。 -
sudo python3 ECS01_ws.pyコマンドでスクリプトを実行します。 -
次の出力が表示された場合、WebSocket アプリケーションはポート 5000 で起動しています。
Server initialized for threading. * Serving Flask app 'ECS01_ws' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on all addresses. WARNING: This is a development server. Do not use it in a production deployment. * Running on http://192.168.*.*:5000/ (Press CTRL+C to quit)アプリケーションの起動に失敗した場合は、ポートが既に使用されていないか、コマンドやコードのコピーが間違っていないかを確認してください。
● redis.service – Redis 永続化キー・バリュー・データベース
Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/redis.service.d
└─limit.conf
Active: active (running) since Thu 2xxx xxx xxx xxx CST; 6s ago
Process: 14715 ExecStop=/usr/libexec/redis-shutdown (code=exited, status=0/SUCCESS)
Main PID: 14730 (redis-server)
CGroup: /system.slice/redis.service
└─14730 /usr/bin/redis-server 0.0.0.0:6379
ECS02 への WebSocket のデプロイ
-
ECS02 インスタンスにログインします。
-
sudo pip3 install flask flask-socketio flask-cors redisを実行して、依存関係をインストールします。 -
vi ECS02_ws.pyを実行し、iキーを押して編集モードに入ります。 -
次のコードをコピーして貼り付けます。
-
Escキーを押し、:wqと入力して変更を保存します。 -
sudo python3 ECS02_ws.pyコマンドでスクリプトを実行します。 -
次の出力が表示された場合、WebSocket アプリケーションはポート 5000 で起動しています。
Server initialized for threading. * Serving Flask app 'ECS02_ws' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on all addresses. WARNING: This is a development server. Do not use it in a production deployment. * Running on http://192.168.*.*:5000/ (Press CTRL+C to quit)アプリケーションの起動に失敗した場合は、ポートが既に使用されていないか、コマンドやコードのコピーが間違っていないかを確認してください。
手順2:サーバーグループの設定
-
ALB コンソール にログインします。
-
上部メニューで、インスタンスがデプロイされているリージョンを選択します。
-
左側のナビゲーションペインで、サーバーグループ をクリックします。
-
サーバーグループの作成 をクリックします。サーバーグループの作成 ページで、次のパラメーターを設定し、他のパラメーターはデフォルト値のままにして、作成 をクリックします。
パラメーター
説明
サーバーグループタイプ
サーバー を選択します。
[VPC]
バックエンドサーバー ECS01 と ECS02 がある VPC を選択します。
バックエンドサーバーは、ALB インスタンスと同じ VPC にある必要があります。
-
サーバーグループが作成されました ダイアログボックスで、バックエンドサーバーの追加 をクリックします。
-
バックエンドサーバーの追加 ページで、ECS01 と ECS02 を選択してサーバーグループに追加します。ポートには、このチュートリアルで WebSocket アプリケーションが使用する 5000 を設定します。
手順3:HTTP リスナーの設定
-
ALB コンソール にログインします。
-
上部メニューで、インスタンスがデプロイされているリージョンを選択します。
-
左側のナビゲーションペインで、インスタンス を選択します。
-
インスタンス ページで対象のインスタンスを探し、操作 列の リスナーの作成 をクリックします。
-
リスナーの設定 ページで、次のパラメーターを設定し、他のパラメーターはデフォルト値のままにして、次へ をクリックします。
パラメーター
説明
リスナープロトコルの選択
[HTTP] を選択します。
リスニングポート
ポートを 5000 に設定します。
-
サーバーグループを選択 ページで、次のパラメーターを設定し、他のパラメーターはデフォルト値のままにして、次へ をクリックします。
パラメーター
説明
サーバーグループを選択
作成したサーバーグループを選択します。
-
確定 ページで、設定を確認し、送信 をクリックします。その後、リスナーが作成されるのを待ちます。
手順4:DNS 解決の設定
本番環境では、CNAME レコードを作成して、カスタムドメイン名を ALB インスタンスのドメイン名にマッピングすることを推奨します。
-
左側のナビゲーションペインで、を選択します。
-
インスタンス ページで、作成した ALB インスタンスの DNS 名をコピーします。
-
次の手順に従って、CNAME レコードを追加します。
説明ドメイン名が Alibaba Cloud 以外のプロバイダーによって登録されている場合は、DNS 名前解決を設定する前に、ドメイン名を Alibaba Cloud DNS コンソールに追加する必要があります。 詳細については、「ドメイン名の管理」をご参照ください。 ドメイン名が Alibaba Cloud に登録されている場合は、次の手順に進んでください。
-
Alibaba Cloud DNS コンソールにログインします。
-
権威 DNS 名前解決 ページで、対象のドメイン名を見つけ、操作 列の 解決設定 をクリックします。
-
解決設定 ページで、Add Record をクリックします。
-
Add Record パネルで、次のパラメーターを設定して CNAME レコードを構成し、OK をクリックします。
パラメーター
説明
[レコードタイプ]
ドロップダウンリストから [CNAME] を選択します。
[ホストレコード]
ドメイン名のプレフィックス。 このチュートリアルでは、@ を使用します。
説明ルートドメインを使用するには、ホスト名を
@に設定します。[Query Source]
デフォルトを選択します。
[レコード値]
コピーした ALB インスタンスの DNS 名を入力します。
TTL
Time to Live (TTL) は、DNS レコードが DNS サーバーにキャッシュされる期間です。 デフォルト値を使用してください。
-
手順5:結果の検証
2 台の別々のコンピューターでブラウザでアプリケーションを開き、メッセージを交換して、ALB が WebSocket を介してリアルタイムメッセージを配信することを確認します。
-
ブラウザで、
http://<your-domain-name>:5000にアクセスし、オンラインチャットルームアプリケーションを開きます。[オンラインチャットルーム] インターフェイスが読み込まれます。チャットメッセージエリアに "You have entered the chat room!" というメッセージが表示され、WebSocket 接続が確立されたことを示します。ページには、[ユーザー名の設定] ボタンのあるユーザー名設定エリアと、[送信] ボタンのあるメッセージ送信エリアがあります。
ブラウザの開発者ツールを開くと、[ネットワーク] タブにブラウザが WebSocket プロトコルを使用して通信していることが表示されます。
[ネットワーク] パネルで、フィルターを
websocketに設定します。ステータスコードが 101 の WebSocket リクエストは、プロトコルアップグレードが成功したことを示します。接続ステータスは保留中であり、永続的な WebSocket 接続が確立され、アクティブであることを意味します。 -
チャットのユーザー名を入力し、[ユーザー名の設定] をクリックします。
-
各コンピューターで、複数のチャットメッセージを入力し、[送信] をクリックしてアプリケーションをテストします。
両方のブラウザで、メッセージがリアルタイムに受信されます。
オンラインチャットルームアプリケーションは正常にデプロイされました。ページには、[ユーザー名] 入力ボックスと [ユーザー名の設定] ボタン、チャットメッセージ表示エリア、そして下部に [送信] ボタン付きのメッセージ入力ボックスがあります。User1 や User2 などの複数のユーザーが、チャットルームでリアルタイムで会話できます。
-
これにより、ALB が WebSocket を介してリアルタイムで高可用性のメッセージングを提供することを確認できます。
よくある質問
WebSocket Secure の使用方法
WebSocket Secure は、WebSocket プロトコルの暗号化されたバージョンです。
HTTPS リスナーは、デフォルトで WebSocket Secure をサポートしています。WebSocket Secure を使用するには、リスナーを設定する際に HTTPS を選択してください。
WebSocket の料金
WebSocket および WebSocket Secure の使用に追加料金は発生しません。
WebSocket のサポートリージョン
ALB がサポートされているすべてのリージョンで、WebSocket および WebSocket Secure もサポートされています。
関連ドキュメント
このチュートリアルでは、テスト目的で ECS インスタンスに Redis をデプロイします。ただし、Redis サーバーが 1 台のみの場合、単一障害点となる可能性があります。本番環境では、高可用性を確保するために Tair を使用することを推奨します。詳細については、「Tair のクイックスタート」をご参照ください。