[Windows Azure] ロード バランサーのアイドルタイムアウトについて

ロードバランサーの制限について

Windows Azure Platform では、VM へのアクセス時に、ロード バランサーによる負荷分散が行われます。このロード バランサーでは、接続のアイドルタイムアウト設定があり、1 分と設定されています。

このため、Windows Azure Platform でホストされているアプリケーションの処理が 1 分を超える長い処理になるような場合には、ロード バランサーによって接続が切断され、クライアント アプリケーション側で例外が発生する場合があります。

残念ながら、このロード バランサーのアイドルタイムアウト設定は固定で 1 分となっており、変更することはできません。

WCF クライアントでの例外発生例

System.ServiceModel.CommunicationException: An error occurred while receiving the HTTP response to xxxxxxxxxxxxxxxxxxxxxxxx.cloudapp.net/Service1.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) --- End of inner exception stack trace --- at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead) --- End of inner exception stack trace --- at System.Net.HttpWebRequest.GetResponse() at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

 

対応策について

1 分を超える処理が想定される場合の対策の 1 つとして、クライアント アプリケーション側による定期的なポーリングの実施が考えられます。例えば、要求を発行したセッションと同一のセッションによって定期的にサーバーにダミーの要求を発行することで、接続が 1 分を超えてアイドル状態になることを抑制し、接続を維持できることが期待できます。

この機構の実現方法としては、例えばサーバーアプリケーションが WCF サービス、クライアントが WCF クライアントであれば、ReliableSession を使ってポーリング機構を実現する方法があります。また、クライアントが Silverlight クライアントの場合には、PollingDuplexHttpBinding を使ってポーリング機構を実現することが可能です。

しかしながら、サーバー アプリケーションが負荷分散されている場合、つまり Windows Azure のロール インスタンスが複数の場合には、これらの方法では同一サービスへのポーリングを行うことができなくなるため、利用することができません。これは、Windows Azure Platform のロード バランサーで、セッション アフィニティがサポートされないことに因ります。実際のところ、一般的には複数のロールインスタンスによって運用することが多いはずですので、つまり容易にこの方法での接続維持を実現することは困難ということになります。

以上のように、サーバー アプリケーションで長い処理が行われる可能性がある場合、ロードバランサーのアイドル タイムアウトを回避する方法として、接続を維持する方向の対策は、比較的実現が困難な方法となります。システム要件に応じて、例えば Worker Role と Windows Azure キュー ストレージを利用した非同期処理の実装等をご検討いただければと思います。

追記: 2012 年初頭にロードバランサーをハードウェアベースから、ソフトウェアベースに更新が行われ、1 分の制限が 4分に緩和されています。

--
デベロッパー サポート
板垣