WebSocket を使用した永続的な接続の作成

リージョン ID

REGION_ID は、アプリの作成時に選択したリージョンに基づいて Google が割り当てる省略形のコードです。一部のリージョン ID は、一般的に使用されている国や州のコードと類似しているように見える場合がありますが、このコードは国または州に対応するものではありません。2020 年 2 月以降に作成されたアプリの場合、REGION_ID.r が App Engine の URL に含まれています。この日付より前に作成されたアプリの場合、URL のリージョン ID は省略可能です。

詳しくは、リージョン ID をご覧ください。

WebSocket を使用して、クライアント(モバイル デバイスやパソコンなど)から App Engine インスタンスへの永続的な接続を作成できます。接続されたままになっていると、クライアントとサーバー間でいつでも双方向のデータ交換ができるため、レイテンシが短くなり、リソースの使用効率が向上します。

WebSocket

WebSocket プロトコルは RFC 6455 で定義され、クライアントとサーバー間で全二重の通信チャネルを提供します。このチャネルは「upgrade」ヘッダーを含む HTTP(S) リクエストから開始します。

WebSocket の一般的なユースケースを次に示します。

  • ソーシャル メディア フィード、スポーツのスコア、ニュース、株価などのリアルタイム イベントの更新
  • ソフトウェアやコンテンツの更新などのユーザー通知
  • チャット アプリケーション
  • 共同編集ツール
  • マルチプレーヤー型ゲーム

WebSocket は、追加の設定をしなくても、常にアプリケーションで利用できます。WebSocket 接続は、確立後 1 時間でタイムアウトします。

WebSocket を使用したサンプル アプリケーションの実行

最初に、App Engine の Java 用「Hello, World!」の説明に沿って環境とプロジェクトを設定し、App Engine の Java アプリの構造について理解します。

サンプル アプリケーションのクローンの作成

サンプルアプリをローカルマシンにコピーし、websockets ディレクトリに移動します。

git clone https://github.com/GoogleCloudPlatform/java-docs-samples
cd java-docs-samples/flexible/websocket-jetty/

サンプルをローカルで実行する

ローカルのパソコンでサンプル アプリケーションを実行するには:

  1. Jetty Maven プラグインを使用してローカルの Eclipse Jetty ウェブサーバーを起動します。

    mvn jetty:run-exploded
    
  2. ウェブブラウザに次のアドレスを入力します。

    http://localhost:8080
    

サンプルを App Engine にデプロイして実行する

アプリケーションを App Engine フレキシブル環境にデプロイするには、websocket-jetty ディレクトリから次のコマンドを実行します。

mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

PROJECT_ID は実際の Cloud プロジェクトの ID に置き換えます。pom.xml ファイルですでにプロジェクト ID を指定している場合は、実行するコマンドに -Dapp.deploy.projectId プロパティを含める必要はありません。

サンプル アプリケーションは jar としてパッケージされており、Servlet 3.1 を含む Java 8 / Jetty 9 ランタイムを使用して自動的に実行されます。

これでブラウザから https://PROJECT_ID.REGION_ID.r.appspot.com にアクセスできます。

JavaScript クライアントをテストするには、https://PROJECT_ID.REGION_ID.r.appspot.com/js_client.jsp にアクセスします。

セッション アフィニティ

すべてのクライアントが WebSocket をサポートしているわけではありません。そのため、多くのアプリケーションは、WebSocket をサポートしていないクライアントに対しては最終的に http のロング ポーリングを使用する socket.io などのライブラリを使用します。

通常、App Engine では使用可能なインスタンス間でリクエストが均等に分散されます。ただし、http のロング ポーリングを使用する場合は、特定のユーザーからの複数の連続したリクエストを同じインスタンスに到達させる必要があります。

App Engine が同じユーザーからのリクエストを同じインスタンスに送信できるようにするには、セッション アフィニティを有効にします。有効にすると、App Engine は Cookie を調べて同じユーザーから送信されたリクエストを特定し、これらのリクエストを同じインスタンスにルーティングします。

App Engine のセッション アフィニティは、ベスト エフォート方式で実装されています。アプリを開発するときは、常にセッション アフィニティが保証されているとは限らないと想定する必要があります。以下の場合、クライアントはターゲット インスタンスとのアフィニティを失う可能性があります。

  • App Engine オートスケーラーが、アプリケーションを処理するインスタンスを追加または削除することがあります。アプリケーションが負荷を再度割り当てるので、ターゲット インスタンスが移動することもあります。このリスクを最小限に抑えるため、インスタンスの最小数は、予想される負荷を処理できる程度に設定してください。
  • ターゲット インスタンスでヘルスチェックに失敗した場合、App Engine はセッションを正常なインスタンスに移動します。ヘルスチェックとそのカスタマイズ オプションの詳細については、スプリット ヘルスチェックをご覧ください。
  • インスタンスがメンテナンスまたはソフトウェア アップデートのために再起動されると、セッション アフィニティは失われます。App Engine フレキシブル環境の VM インスタンスは毎週再起動されます。

セッション アフィニティは保証されていないため、接続が切断されときに socket.io などのライブラリの機能を利用して HTTP のロング ポーリングを行う場合にのみ使用してください。セッション アフィニティを使用してステートフル アプリケーションを作成しないでください。

セッション アフィニティの有効化と無効化

デフォルトでは、セッション アフィニティはすべての App Engine アプリケーションで無効になっています。セッション アフィニティはアプリケーションのバージョン レベルで設定され、デプロイするときに有効または無効にできます。

App Engine のバージョンのセッション アフィニティを有効にするには、次のエントリを app.yaml ファイルに追加します。

network:
  session_affinity: true

更新された app.yaml を使用してバージョンがデプロイされると、そのインスタンスが利用可能である限り、新しいリクエストは同じインスタンスから処理を開始します。

セッション アフィニティを無効にするには、app.yaml ファイルからエントリを削除するか、値を false に設定します。

network:
  session_affinity: false