Windows Azure Web サイトに WebSocket を導入する
このポストは、11 月 14 日に投稿された Introduction to WebSockets on Windows Azure Web Sites の翻訳です。
編集メモ: 今回は、Windows Azure Web サイト チームの主任プログラム マネージャー リードを務める Stefan Schackow の記事をご紹介します。
先日、Windows Azure Web サイトで WebSocket プロトコルがサポートされるようになりました。.NET 開発者や Node.js 開発者の皆様に、ご自身のアプリケーションで WebSocket を有効にし、利用していただけるようになったのです。
Windows Azure ポータルの [Configure] タブに、アプリケーションの WebSocket サポートを有効にするオプションが新しく追加されています。
Web サイトで WebSocket を有効にすると、ASP.NET (4.5 以降) と Node.js の開発者は、各自のフレームワークからライブラリと API を使用して WebSocket と連携させることができます。
ASP.NET SignalR のチャット アプリケーションのサンプル
SignalR はオープン ソースの .NET ライブラリで、HTTP 接続を保持したままでデータを転送するリアルタイム Web アプリケーションの構築を可能にします。こちらのサイト (英語) に SignalR ライブラリに関する入門記事や詳細が掲載されていますのでご覧ください。
SignalR は、プロトコルとして WebSocket をネイティブにサポートするので、接続された Web アプリケーションを Windows Azure Web サイトで実行する場合に最適です。その例として、今回は SignalR を使用したサンプル チャット アプリケーション (英語) を Windows Azure Web サイトで実行してみましょう。
SignalR のサンプル チャット アプリケーションの構造は、以下のスクリーンショットをご覧ください。
Windows Azure Web サイトで Web アプリケーションを作成して WebSocket を有効にした後、この SignalR サンプル チャット アプリケーションをアップロードすれば、独自のミニ チャット ルームを Windows Azure Web サイトで実行することができます。
Fiddler による未加工の HTTP トレース (下記参照) を見ると、WebSocket プロトコルへのアップグレード要求が SignalR のクライアントサイド部分から送信され、Web サーバーとの WebSocket 接続がネゴシエートされているのがわかります。
Request snippet:
GET https://sigr-chat-on-waws.xxxx.net/signalr/connect?transport=webSocketssnip HTTP/1.1
Origin: https://sigr-chat-on-waws.xxxx.net
Sec-WebSocket-Key: hv2icF/iR1gvF3h+WKBZIw==
Connection: Upgrade
Upgrade: Websocket
Sec-WebSocket-Version: 13
…
Response snippet:
HTTP/1.1 101 Switching Protocols
Upgrade: Websocket
Server: Microsoft-IIS/8.0
X-Content-Type-Options: nosniff
X-Powered-By: ASP.NET
Sec-WebSocket-Accept: Zb4I6w0esmTDHM2nSpndA+noIvc=
Connection: Upgrade
…
SignalR を使用したリアルタイム Web アプリケーションの構築の詳細については、SignalR の概要を紹介する Web サイトで幅広いチュートリアル (英語) が公開されているので、そちらを参照してください。
ASP.NET のエコー処理のサンプル
ASP.NET は、.NET Framework 4.5 から WebSocket をサポートしています。多くの場合、開発者は SignalR のような高レベルのライブラリを使用して、WebSocket 接続の管理にまつわる低レベルの詳細部分を排除したいと考えるでしょう。しかし、このセクションでは好奇心旺盛な開発者向けに、ASP.NET で低レベルの WebSocket サポートを使用する簡単な例を紹介します。
ASP.NET Echo サンプル プロジェクトは、サーバーサイドの WebSocket をリッスンし応答を返す .ashx ハンドラーと、WebSocket 接続を確立しテキストをサーバーに送信する簡単な HTML ページから構成されます。
.ashx ハンドラーでは、次のように WebSocket 接続要求をリッスンします。
WebSocket 接続が確立されると、このハンドラーでは次のようにブラウザーにテキストをエコー バックします。
対応する HTML ページでは、ページがロードされたときに WebSocket 接続を確立します。ブラウザーのユーザーが WebSocket 接続にテキストを送信するたびに、ASP.NET ではそれをエコー バックします。
以下のスクリーンショットには、テキストを含むブラウザー セッションがエコー バックされているところと、WebSocket 接続が閉じられているところが表示されています。
Node.js の基本的なチャット アプリケーションのサンプル
Node.js 開発者にとって、socket.io ライブラリを使用して、長時間維持される HTTP 接続を行う Web ページを作成する手法は馴染みのあるものです。socket.io は、ネットワーク プロトコルとして複数のオプションと共に WebSocket もサポートしており、WebSocket が利用可能な場合に、それを転送に使用するよう構成することができます。
Node.js アプリケーションでは、以下のように socket.io モジュールを追加し、コード内でソケットを構成します。
以下のコードでは、クライアントがニックネーム (ハンドル ネームなど) で接続するのをリッスンし、そのときに接続しているすべてのクライアントに、チャット メッセージを配信します。
WebSocket を使用する Node.js アプリケーションでは、次のように web.config 内のコードを少しだけ調整する必要があります。
IIS の WebSocket サポート モジュール (iiswsock.dll) は Node.js では不要なので、この web.config のエントリで無効にします。IIS 上の Node.js には、独自の WebSocket の低レベルの実装が組み込まれているため、サポート モジュールを明示的に無効にする必要があるのです。
ただし、Web サイト の WebSocket 機能自体は、前述のとおり、ポータルの [Configure] タブの UI を使用して有効にする必要があることを忘れないでください。
サンプルの Node.js アプリケーションを使用して 2 つのクライアントが接続しメッセージをやりとりした場合、HTML 出力は次のようになります。
Fiddler による未加工の HTTP トレース (下記参照) を見ると、WebSocket プロトコルへのアップグレード要求が socket.io のクライアントサイド部分から送信され、Web サーバーとの WebSocket 接続がネゴシエートされているのがわかります。
Request snippet:
GET
https://abc123.azurewebsites.net/socket.io/1/websocket/11757107011524818642 HTTP/1.1
Origin: https://abc123.azurewebsites.net
Sec-WebSocket-Key: rncnx5pFjLGDxytcDkRgZg==
Connection: Upgrade
Upgrade: Websocket
Sec-WebSocket-Version: 13
…
Response snippet:
HTTP/1.1 101 Switching Protocols
Upgrade: Websocket
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Sec-WebSocket-Accept: jIxAr5XJsk8rxjUZkadPWL9ztWE=
Connection: Upgrade
…
WebSocket 接続の制約
現在、Windows Azure Web サイトでは、実行中の Web サイト インスタンスごとにサポートされる WebSocket の同時接続数に制限を設けています。1 つの Web サイト インスタンスにつきサポートされる WebSocket 接続数は、各スケールに応じて次のようになっています。
- 無料: Web サイト インスタンスあたり 5 接続
- 共有: Web サイト インスタンスあたり 35 接続
- 標準: Web サイト インスタンスあたり 350 接続
アプリケーションがこの制限を超えて WebSocket 接続を試行すると、Windows Azure Web サイトから 503 の HTTP エラー ステータス コードが返されます。
メモ:「Web サイト インスタンス」は、Web サイトが 2 インスタンスで実行するようスケーリングされている場合、実行中の Web サイト インスタンスは「2」とカウントされます。
WebSocket に SSL の使用が必要となる場合も
WebSocket を使用する際、開発者には 1 つ留意すべき点があります。WebSocket プロトコルは使用頻度がさほど多くない HTTP ヘッダー (Upgrade ヘッダー) を使用するので、Web プロキシなどのネットワークの途中にあるデバイスが対応しておらず、これらのヘッダーが削除される場合があります。そうすると、開発者はほとんどの場合、自分の WebSocket アプリケーションがなぜ動作しないのか、またはなぜ WebSocket が選択されないのか戸惑い、不満に思った結果、効率の悪い他の方法に戻してしまいます。
この問題は、WebSocket 接続を SSL で確立することで回避できます。そのために、次の 2 つの手順を実行します。
- WebSocket エンドポイントに対応する "wss://" プロトコル識別子を使用します。たとえば、ws://mytestapp.azurewebsites.net (WebSocket over HTTP) の代わりに、wss:// mytestapp.azurewebsites.net (WebSocket over HTTPS) に接続します。
- (オプション) 該当のページを SSL で実行します。これは必須ではなく、クライアントサイドで使用しているフレームワークによっては不要となることがあります。WebSocket 接続の "SSL 状態" が、該当の HTML ページに適用されている SSL 設定を反映している場合があるためです。
Windows Azure Web サイトでは、*.azurewebsites.net の既定の SSL 証明書を使用することで、無料のサイトでも SSL がサポートされます。そのため、この回避策を行う際に、SSL 証明書を独自に設定する必要はありません。azurewebsites.net の WebSocket エンドポイントで SSL を使用するように切り替えるだけで、*.azurewebsites.net のワイルドカード SSL 証明書が自動的に使用されます。
また、Web サイトをカスタム ドメインで登録し、そのサイトに対して SNI または IP ベースの SSL 証明書を設定することも可能です。Windows Azure Web サイトのカスタム ドメイン名の構成と Windows Azure Web サイトでの SSL 証明書の構成 (英語) の詳細については、Windows Azure のドキュメント ページを参照してください。