-
Notifications
You must be signed in to change notification settings - Fork 0
MS_WCFTimeout
WCF のタイムアウトについてまとめてみた。
WCF では、Binding でタイムアウト設定が可能。
- SendTimeout
- OperationTimeout の初期化に使用。
- メッセージの送信プロセス全体を制御。
- 要求/応答サービス操作の応答メッセージの受信
- コールバック コントラクト メソッドから応答メッセージを送信
- ReceiveTimeout
使用されない。 - OpenTimeout
明示的なタイムアウト値が指定されていない場合、チャネルを開くときに使用。 - CloseTimeout
明示的なタイムアウト値が指定されていない場合、チャネルを閉じるときに使用。
補足(
SendTimeoutが「送信」だけではない点が要点): 名前から
「送信にかかる時間の上限」と読んでしまいがちだが、
本文が明記しているとおり
応答メッセージの受信までを含む。
すなわち、要求/応答型の呼び出しでは
**実質的にこれが「呼び出し全体のタイムアウト」**である。「サーバの処理が重いのでタイムアウトを延ばしたい」という場合に
変更すべきなのはSendTimeoutであり、
ReceiveTimeoutではない。
クライアント側のReceiveTimeoutは使われない(本文のとおり)ため、
ここを延ばしても何も変わらない、というのが典型的な躓きどころである。各既定値は次のとおり(いずれも
Bindingの既定)。
プロパティ 既定値 効く場面 OpenTimeout1 分 チャネルを開く(接続確立、セキュリティ ネゴシエーション) SendTimeout1 分 呼び出し全体(応答受信まで) ReceiveTimeout10 分 サーバ側でのアイドル セッションの維持時間 CloseTimeout1 分 チャネルを閉じる なお、
ReceiveTimeoutは「使われない」のではなく
サーバ側で意味を持つ(後述)。
- 検証した所、
executionTimeoutは効いてない模様。 - クライアント側のタイムアウト設定しかないが、
サーバ側プログラムから OperationTimeout に設定が可能。
(既定で、クライアント側の SendTimeout 設定をサーバ側の OperationTimeout 設定の初期値に設定している)
補足(
executionTimeoutが効かない理由):httpRuntimeの
executionTimeoutは ASP.NET のパイプラインが
要求の実行時間を制限する設定である。
これが WCF に効かないのは、次の 2 つの理由による。
executionTimeoutはdebug="true"のとき無効になる
(compilation debug="true"だと ASP.NET はタイムアウトを適用しない)。
検証環境で「効かない」と見えるのは、多くの場合これが原因である。- WCF を ASP.NET 互換モード(
aspNetCompatibilityEnabled="true")で
動かしていない場合、要求は ASP.NET のパイプラインではなく
WCF 自身のディスパッチャが処理するため、
httpRuntimeの設定が適用されない。したがって、本文の「効いてない模様」は
設定ミスではなく仕様どおりである。サーバ側で処理時間そのものを打ち切りたい場合は、
WCF のタイムアウト設定ではなく
業務処理側にキャンセル機構を実装する(CancellationToken等)か、
DB 側のタイムアウト
(SQL Server でのロック・タイムアウト)で
上限を設けることになる。
補足(サーバ側で意味を持つタイムアウト): サーバ側の
Bindingでは、
次の 2 つが実際に効く。
設定 サーバ側での意味 ReceiveTimeoutセッションのアイドル タイムアウト。この時間クライアントから何も来なければセッションを破棄する OpenTimeout/CloseTimeoutチャネルの開閉
ReceiveTimeoutの既定は 10 分と長めであるため、
セッション有りのバインディング(netTcpBinding、
wsHttpBindingの信頼できるセッション等)では、
切断されたクライアントのセッションが 10 分間残り続ける。
同時接続数の上限(ServiceThrottlingのMaxConcurrentSessions)と
併せて考慮しないと、
接続できなくなるという形で問題が表面化する。
補足(タイムアウトは「多層」であることを忘れない): WCF の呼び出しでは、
実際には複数のタイムアウトが重なっている。ブラウザ/呼び出し元 └ ASP.NET executionTimeout(呼び出し元が Web アプリの場合) └ WCF SendTimeout ← 呼び出し全体 └ HTTP/TCP の接続タイムアウト └ サーバ側の業務処理 └ SqlCommand.CommandTimeout(既定 30 秒) └ SQL Server のロック タイムアウト内側ほど短くなっていないと、
外側が先に諦めて内側の処理は動き続ける(孤児処理)ことになる。
DB の更新処理では、これが
ロックを掴んだまま放置される原因になり得る
(SQL Server でのデッドロック)。
設計時には各層の値を一覧にして、
内側 < 外側の関係を確認しておくこと。
- executionTimeout
- WCF service timeout
http://stackoverflow.com/questions/9567999/wcf-service-timeout
- WCF service timeout
- OperationTimeout
- WCF のタイムアウト問題。。 | 自宅プログラマーのメモ部屋 - 楽天ブログ
https://plaza.rakuten.co.jp/nutristudio/diary/201106250001/ - バインディングでのタイムアウト値の構成 | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/framework/wcf/feature-details/configuring-timeout-values-on-a-binding
- WCF のタイムアウト問題。。 | 自宅プログラマーのメモ部屋 - 楽天ブログ
- バインディングでのタイムアウト値の構成
設定・実装の例@Open棟梁
- https://github.com/OpenTouryoProject/OpenTouryo/blob/master/root/programs/CS/Frameworks/Infrastructure/Framework/Transmission/CallController.cs#L626
- https://github.com/OpenTouryoProject/OpenTouryo/issues/280
移行メモ(構成): 原典ではクライアント側の参考リンクが
「クライアント側」節の中にあったが、
サーバ側の参考節と並ぶ位置に整理した(内容は同一)。
補足(最新化:WCF の現在): WCF は .NET Framework 限定の技術であり、
.NET Core 以降にはサーバ側が移植されていない。
新規開発では次が後継となる。
用途 後継 HTTP ベースのサービス ASP.NET Core Web API(WebAPI) 高性能な RPC gRPC 既存 WCF の移植 CoreWCF(コミュニティ主導、Microsoft 支援) なお、クライアント側(
System.ServiceModel.*パッケージ)は
.NET Core / .NET 5 以降でも利用可能であり、
既存の WCF サービスを呼ぶことはできる。
その場合も本ページのタイムアウト設定はそのまま有効である。
Tags: 移行, .NET開発, 通信技術
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。