-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ASPNETTimeoutValues
ASP.NET のタイムアウトについての考慮点を纏めました。
タイムアウトは「どちら側が」「どのレイヤで」設定されているかによって、
タイムアウト後にサーバ側の処理が続くかどうかが変わる。
ここが理解の要点である。
クライアント側のタイムアウトは、
リクエスト − レスポンス間のタイムアウトについて言及しているものが多いので、
タイムアウト後にサーバ側が
- 動作し続けるものと、
- 動作し続けないもの
があるので注意が必要。
- HTTP クライアント側(クライアント側)のタイムアウト値。
- こちらは、タイムアウト後にサーバー側が動作し続けるモノが多い。
- HTTP クライアントに依って異なるが、だいたい以下のものがある。
| 種類 | 内容 |
|---|---|
WebRequest のタイムアウト |
WebRequest.Timeout プロパティ |
| HttpClient のタイムアウト |
HttpClient.Timeout プロパティ |
| WCF クライアントのタイムアウト | WCFのタイムアウト(MS_WCFTimeout.md) |
補足(最新化):
WebRequest/HttpWebRequestは .NET Core 以降は非推奨(.NET 6 で[Obsolete])であり、HttpClientを使用する。
HttpClient.Timeoutは「リクエスト全体」に効くため、 大きなレスポンスのストリーミングでは扱いにくい。 細かく制御するなら、CancellationTokenSourceによるキャンセルやSocketsHttpHandler.ConnectTimeout/PooledConnectionLifetimeを併用する。
- データ プロバイダ側(クライアント側)のタイムアウト値。
- こちらは、タイムアウト後にサーバ側が停止(ロールバック)されるモノが多い。
- データ プロバイダに依って異なるが、だいたい以下のものがある。
| 種類 | 内容 | 既定値(SQL Server) |
|---|---|---|
| コネクション タイムアウト(接続のタイムアウト) | クエリの接続のタイムアウト(SqlConnection.ConnectionTimeout) |
15 秒 |
| コマンド タイムアウト(実行のタイムアウト) | クエリの実行のタイムアウト(SqlCommand.CommandTimeout) |
30 秒 |
補足: コマンド タイムアウトが発生すると、 クライアントは SQL Server に attention(キャンセル)要求を送るため、 実行中のバッチは中断される。 ただし、暗黙のトランザクションは自動でロールバックされないので、 アプリ側で確実に
Rollback/Disposeすること。
サーバ側のタイムアウトは、実行タイムアウト以外に様々なタイムアウトが存在する。
実行タイムアウトの場合、
タイムアウト後にサーバ側は動作を停止する(当然といえば当然)。
- こちらは、Keep-Alive 系のタイムアウトになる。
- TCP の RST パケットが送信されるもよう。
- IIS のサイト設定「接続の制限」 →「接続タイムアウト」(既定 120 秒)。
- 意外にも、上記以外のタイムアウト値を発見できず。
- 実行タイムアウト系は、AP サーバのタイムアウトだからか。
補足: IIS 側にも実際は
headerWaitTimeout(HTTP.sys がヘッダ到着を待つ時間、既定 2 分)やminBytesPerSecond(応答が遅すぎる接続の切断、既定 240 bytes/sec)があり、 低速クライアントや Slow HTTP 攻撃の切り分けで効いてくる。
一定時間リクエストが無いとワーカー プロセスが停止する(既定 20 分)。
これが初回リクエストが遅い原因になることがある。
Web.config(httpRuntime タグの executionTimeout 属性)に記述する(既定 110 秒)。
<httpRuntime executionTimeout="110" />補足:
executionTimeoutは<compilation debug="true" />のときは無視される。 「開発機ではタイムアウトしないのに本番で切れる」という典型的な罠である。また ASP.NET Core にはこの設定自体が存在しない (代わりにホスト側の
RequestTimeoutやRequestTimeoutsミドルウェアを使う)。
WS-* だけあって、色々あって難しい
(…のが普及しなかった理由でもありそう)。
WCFのタイムアウト(MS_WCFTimeout.md)
Web.config(sessionState タグの timeout 属性)に記述する(既定 20 分)。
- DB に依って異なるが、だいたい以下のものがある。
- 通常、DB の実行タイムアウト相当は、データ プロバイダ側にある。
ロックによるブロッキングのタイムアウト値。
SQL Server の既定は「無期限(SET LOCK_TIMEOUT -1)」である。
- SQL Server でのロック・タイムアウト(
MS_SQLServerLockTimeout.md) - DBMSのロック・分離戦略と同時実行制御(
MS_DBMSLockingAndConcurrency.md)
- トランザクション処理の実行のタイムアウト。
-
TransactionScopeに実装されていることから、
コマンド タイムアウト同様に、クライアント側の設定である。
補足:
TransactionScopeの既定は 1 分、machine.configのmaxTimeoutは既定 10 分で、 コードで 10 分超を指定してもmaxTimeoutに切り詰められる。
- クライアント側設定とサーバ側設定がある。
- コネクション レベルのタイムアウトなので、
どちら側の設定の場合も、タイムアウト時に、サーバは動作をしていないことになる。
| 側 | 設定 |
|---|---|
| クライアント側 | DB のクライアント側タイムアウト(SqlConnection.ConnectionTimeout) |
| サーバ側 | IIS のサーバ側タイムアウト(接続タイムアウト) |
| 側 | 設定 |
|---|---|
| クライアント側 | DB のコマンド タイムアウト、トランザクション タイムアウト |
| サーバ側 | ASP.NET の executionTimeout
|
- クライアント側タイムアウトでは、AP サーバの Thread は停止しないことがある。
- 停止しない場合、Transaction の結果は AP サーバの処理結果に依る。
- サーバ側タイムアウトでは、AP サーバの Thread が停止する。
- 停止する場合は、Transaction はロールバックされる。
- Connection や Transaction オブジェクトは、
Close されないで GC されると Transaction をロールバックする仕様であるため。 - 従って、Exception が上がっているのに
Transaction オブジェクトを Commit するようなコードを書いてはダメ。
- Connection や Transaction オブジェクトは、
補足: 「GC されるとロールバックされる」に依存するのは危険で、 GC のタイミングまでロックが保持され続けるため 後続の処理をブロックする。
usingで確実にDisposeするのが正しい。また、ASP.NET の
executionTimeoutはスレッドをThreadAbortExceptionで中断する仕組みだったが、 .NET Core / .NET 5 以降はThread.Abortが非サポートであり、CancellationTokenによる協調的キャンセルへ移行している。
Tags: あるある, .NET開発, ASP.NET, 障害対応, 性能
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。