服务端
1 .GO实现超时的网络原语:Deadline,Deadline是一个绝对时间值,当达到这个时间段时,所有io操作都会失败,返回超时错误
2 .Deadline不是超时机制,仅仅时一个绝对时间值,不会自动重置,需要每次手动设置
3 .ReadTimeout,WriteTimeout,可以在这两个地方设置超时方法
srv := &http.Server{
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
4 .ReadTimeout
1 .从接受Accept到request Body完全被读取,如果不读取body,那么时间截止到读到header为止.内部实现就是在Accept立即调用SetReadDeadline方法
2 .
5 .WriteTimeOut
1 .从request header的读取结束开始,到response write结束位置
2 .实现基础就是在readRequest 方法结束的时候调用SetWriteDeadline实现
3 .当连接是HTTPS的时候,SetWriteDeadline会在Accept之后立即调用,所以这个计算也包括TLS握手时的时间
4 .此时writeTimeOut设置的时间也包括读取Header到读取body第一个字节这段时间
6 .这个主要的场景就是上传大文件的时候就出现超时设置
流过程中的超时
1 .https://colobu.com/2016/07/01/the-complete-guide-to-golang-net-http-timeouts/
2 .hijack获取net.Conn,然后调用他的SetWriteDeadline
客户端
1 .最简单的就是http.Client的Timeout字段,计算时间就是从连接到读完response body
c := &http.Client{
Timeout: 15 * time.Second,
}
resp, err := c.Get("https://blog.filippo.io/")
2 .更细粒度的超时
1 .net.Dialer.Timout:限制建立TCP连接的时间
2 .http.Transport.TLSHandshakeTimeout 限制TLS握手的时间
3 .http.Transport.ResponseHeaderTimeout 限制读取response header的时间
4 .http.TrabsportExpectContinueTimeout 限制client在发送包含Expect:100-continue的header到收到继续发送body的response之间的时间等待
5 .http.Transport.IdleConnTimeout 控制连接池中一个连接可以idle多长时间
c := &http.Client{
Transport: &Transport{
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
ResponseHeaderTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
}
6 .没有限制发送request的时间
3 .取消client请求的方式
1 .Request.Cancel
2 .Context
ctx, cancel := context.WithCancel(context.TODO())
timer := time.AfterFunc(5*time.Second, func() {
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)
3 .Context好处还在于如果parent context被取消的时候(在context.WithCancel调用的时候传递进来的),子context也会取消, 命令会进行传递。
有疑问加站长微信联系(非本文作者)