概要
タイムアウトと一口に言ってもサーバ・クライアント、そして各フェーズによって細かく設定があります。
今回はGoのnet/httpのtimeoutについて1つ1つ説明していきます。
環境
- golang/go 1.13
Server
全体図
サーバ系timeoutと各フェーズは以下の関係になっています。
各項目
項目 | 役割 |
---|---|
http.Server.ReadHeaderTimeout | request headersを読む際のtimeout |
http.Server.ReadTimeout | request headersやrequest bodyを読む際のtimeout。SetReadDeadline() を呼び出してセットする。 |
http.Server.WriteTimeout | request bodyの読み込み〜responseの書き込みまで。SetWriteDeadline() を呼び出してセットする。 |
http.Server.IdleTimeout | keep-alivesが有効な場合に次のリクエストが来るまで待つIdle時間 |
http.Server.ReadTimeout
やhttp.Server.WriteTimeout
に点線があるのは、TLS接続の場合Accept直後にSetReadDeadline()
やSetWriteDeadline()
を呼ぶためです。
references
例
一通りセットすると以下のようになります。
srv := &http.Server{ ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 120 * time.Second, Handler: serveMux, } log.Println(srv.ListenAndServe())
Client
全体図
クライアント系timeoutと各フェーズは以下の関係になっています。
各項目
項目 | 役割 |
---|---|
http.Client.Timeout | http clientのtimeout。 http.DefaultClientは未設定のため無限。 |
net.Dialer.Timeout | TCPコネクションの確立時のtimeout |
http.Transport.TLSHandshakeTimeout | TLS handshakeにかかる時間を制限 |
http.Transport.ResponseHeaderTimeout | Response headersの読み込みtimeout |
http.Transport.IdleConnTimeout | コネクション閉じる前のIdle時間 |
例
一通りセットすると以下のようになります。
c := &http.Client{ Transport: &http.Transport{ DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).DialContext, TLSHandshakeTimeout: 10 * time.Second, ResponseHeaderTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, }, Timeout: 60 * time.Second, }
references
その他
requestにcontext.WithTimeout付けた場合は?
以下のようにcontextによるTimeoutを設定したケースはどうなるか、です。
ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() req, err := http.NewRequest("GET", "http://httpbin.org/range/2048?duration=8&chunk_size=256", nil) if err != nil { log.Fatal(err) } req = req.WithContext(ctx)
WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
ref: context package - context - pkg.go.dev
とあるようにその時点でDeadlineを設定します。
なのでWithTimeout()を呼んでからレスポンスが返ってくるまでの範囲になります。
ExpectContinueTimeoutは?
http.Transport.ExpectContinueTimeout
という項目があります。
これはExpect: 100-continue
ヘッダーを付けてpreflightリクエストを送った際にレスポンスが返ってくるまでのtimeoutです。
ref: Preflight (Mixin) - Level 3 REST
ゼロ値の場合はタイムアウトがないことを意味し、サーバーの承認を待たずにすぐにbodyが送信されます。
Expect: 100-continue
ヘッダーを付けている- ExpectContinueTimeoutを設定している
の2つの条件を場合に有効になります。