Original source of English: The Complete Guide to go net/http timeouts, author: Filippo Valsorda
When using go to write HTTP servers and clients, timeouts are always one of the most error-prone and tricky places. Errors can come from many places, and an error can wait for a long time without results until a network failure or process hangs.
HTTP is a complex, multi-stage (multi-stage) protocol, so there is no universal timeout solution, such as a streaming service, a JSON API, and a comet service that require different timeouts, and often default values that are not what you want.
In this article, I'll disassemble each stage of the timeout setting to see what different ways to handle it, including the server side and the client. Setdeadline
First, you need to know the network primitives for Go Implementation timeout (primitive): Deadline (deadline).
Net. Conn provides a number of methods for deadline set[read| Write]deadline (time. Time). Deadline is an absolute time value, and when this time is reached, all I/O operations will fail, returning a timeout (timeout) error.
Deadline is not a timeout (timeout). Once they are set to take effect permanently (or until the next call to Setdeadline), regardless of whether the connection is used and how it is used at this time. So if you want to use Setdeadline to establish a time-out mechanism, you have to call it every time before the read/write operation.
You may not want to call setdeadline yourself, but instead let net/http call you, so you can invoke a more advanced timeout method. Remember, however, that all of the timeout implementations are based on deadline, so they will not receive or send reset this value each time (so they does not reset every when is sent or received).
A correction to the rain in Jiangnan:
Should be because "deadline is an absolute time value", is not a real timeout mechanism, so the author specifically reminded that this value will not automatically reset, need to manually set each time. server-side timeout settings
For servers exposed to the Web, setting timeouts for client connections is critical, otherwise a slow or compromised client may cause the file handle to be unable to be freed, resulting in the following error from the server:
Http:accept error:accept TCP [::]:80:accept4:too many open files; Retrying in 5ms
http. Server has two methods for setting timeouts: ReadTimeout and Andwritetimeout '. You can set them up by showing them:
1 2 3 4 5 |
SRV: = &http. server{Readtimeout:5 * time. Second, Writetimeout:10 * time. Second,} log. Println (SRV. Listenandserve ()) |
ReadTimeout time calculation is received from the connection (accept) to the request body is completely read (if you do not read the body, then the time until the header is read). Its internal implementation is to call the Setreaddeadline method immediately (line of code) in accept.
1 2 3 4 5 6 7 8 |
... if d: = C.server.readtimeout; D!= 0 {c.rwc.setreaddeadline (time). Now (). ADD (d))} if D: = C.server.writetimeout; D!= 0 {c.rwc.setwritedeadline (time). Now (). ADD (d))} ... |
WriteTimeout is normally calculated from the end of the read from the request header to the end of response write (that is, the declaration cycle of the Servehttp method). It is implemented by calling Setwritedeadline (line of code) at the end of the Readrequest method.
1 2 3 4 5 6 7 8 9 |
func (c *conn) readrequest (CTX context. Context) (W *response, err Error) {if c.hijacked () {return nil, errhijacked} if D: = c.server.readtimeout; d!= 0 {C.R Wc. Setreaddeadline (time. Now (). ADD (d))} if D: = C.server.writetimeout; D!= 0 { |