Go net/http Timeout Guide "translated 100%"

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

When using go to develop an HTTP server or client, the time-out error is often simple and subtle: many factors can result in timeouts. An error can take a long time without results until the network fails and the process is suspended.

HTTP is a complex multilayer protocol, so there is no universal solution to the problem of timeouts. Think about it: Streaming media terminal, JSON API, comet terminal. In fact, the default value is often not what you want. (I don't understand what comet endpoint means.) The link in the original text is a comet of the astronomical significance of Wikipedia. Translator suspected to support BT protocol BitComet)

In this article, I will describe separately, at those stages, you may need to set a timeout. And on both the server and the client, a different way to handle timeouts is also taken. (Translator: This article is mainly based on the Go standard library to introduce.) The Go Standard library provides a high level of flexibility in time-out definitions. When the translator started using go development, it was a toss-up.


caotj72 translated 11 months ago 2 people top Top Well translated! Other translation versions (1) Loading ...

Set deadline (timeout)

First, you need to understand the initial level of network timeout implementations that go provides: deadlines (deadline).

Deadlines is implemented in the Go standard library net.conn, through set[read| Write]deadline (time. Time) method to set. Deadlines is an absolute time, and once that is done, all I/O operations are stopped and a time-out error is generated. "Time." The precision of Time is nanosecond)

the deadlines itself is not timed out . Once set, it will remain in effect (until once again setdeadline), and it does not care if the link exists during this period and how it is used. Therefore, you need to use Setdeadline to set a timeout length before each read/write operation.

In practice, you don't need to call setdeadline directly, but instead use a higher-level timeout setting in standard library net/http. However, it is important to note that all deadlines-based timeouts are executed, so there is no need to reset the timeout before each receive/send operation. (This is also true for TCP, UDP, Unix-socket, see Standard Library net).

Server timed out

Setting the client link timeout is critical for an HTTP server that is deployed on the Internet. Otherwise, an ultra-slow or disappearing client may leak the file descriptor and eventually cause an exception. As shown below:

Http:accept error:accept TCP [::]:80:accept4:too many open files; Retrying in 5ms
caotj72 translated 11 months ago 1 people top Top Well translated!

http. The server provides two timeouts to implement ReadTimeout and writetimeout. You can set them using an explicit definition:

SRV: = &http. server{Readtimeout:5 * time. Second, Writetimeout:10 * time. Second,}log. Println (SRV. Listenandserve ())

The time range covered by the readtimeout is: from the reception of a link request, to the end of reading a complete Request message (HTTP protocol request message, possibly only the message header, such as Get, so, can also be read request packet header). is set by calling Setreadline in the Net/http accept method.

The time range covered by the writetimeout is from the start of the read request packet to the end of the return response message (also known as the Servehttp life cycle). Set by Setwritedeadline before the Readrequest method is finished.

However, when using an HTTPS connection, WriteTimeout is set by calling Setwritedeadline in the Accept method. Because, it also needs to cover the time that is spent in the TLS handshake. This means that (in this case only), when using HTTPS, the WriteTimeout actually includes the fetch/wait time of the request message.

When you are dealing with untrusted clients and networks, both timeouts should be set. In order to avoid, a client, because of the ultra-slow read/write operation, long time to occupy a linked resource.

Finally, HTTP. Timeouthandler. It is not a server parameter, but a handler wrapper that uses it to limit the length of the servehttp call. When the timeout condition is reached, the response data is cached and a 504 Gateway timeout is sent. Note that there is a problem with version 1.6, which is fixed in 1.6.2.

caotj72 translated 11 months ago 1 people top Top Well translated! Other translation versions (1) Loading ...

http. Listenandserve's Problem

Unfortunately, HTTP. Listenandserve, http. Convenient functions such as LISTENANDSERVETLS and Http.serveare, which pass through http.server, are not suitable for external publishing network services.
Because these functions turn off the timeout setting by default , they cannot be set manually. With these functions, the connection is quickly leaked, and then the file descriptor is exhausted. I have made at least 6 such mistakes in this regard.
For this, you should use http.server! When creating an Http.server instance, call the appropriate method to specify ReadTimeout (read time-out time) and WriteTimeout (write time-out time), there are some cases below.

about Flow

The annoying thing is the inability to access objects under the Net.conn package from Serverhttp, so a server that wants to respond to a stream must de-writetimeout settings (that's why the default value is 0). Because access to net is not available. Conn package, you cannot call Setwritedeadline before each write operation to set a reasonable idle time-out.

Imqipan translated 11 months ago 0 People top Top Well translated!

Similarly, due to the inability to confirm that Responsewriter.close supports concurrent write operations, Responsewriter.write can cause blocking and cannot be canceled.

(Translator Note: in Go 1.6.2, the interface Responsewriter definition does not have a close method and needs to be implemented in the interface implementation itself.) Speculation is that the author has implemented this method in development)

Unfortunately, this means that the streaming media server will not be able to effectively guarantee its own efficiency and stability when faced with a low-speed client.

I have submitted some suggestions and look forward to some feedback.

Client Timeout

Client timeouts, depending on your decision, can be simple or complex. But it is also important to prevent resources from leaking and blocking.

The simplest way to use timeouts is HTTP. Client. It covers the entire interaction process, from initiating the connection to receiving the response message end.

c: = &http. client{timeout:15 * time. SECOND,}RESP, err: = C.get ("https://blog.filippo.io/")

Similar to the server-side scenario, use HTTP. Get package-level easy-to-use functions when creating clients, you cannot set timeouts. Application in an open network environment, there is a great risk.

caotj72 translated 11 months ago 0 People top Top Well translated!

There are other ways to get more granular time-out control:

    • Net. Dialer.timeout limit the time it takes to create a TCP connection (if a new link is required)

    • http. Transport.tlshandshaketimeout Limit the time the TLS handshake is used

    • http. Transport.responseheadertimeout limit the time it takes to read a response message header

    • http. Transport.expectcontinuetimeout restricts the time that the client waits to receive a go-ahead response message after sending an HTTP header containing: 100-continue. In 1.6, this setting is not valid for HTTP/2. (A specific package defaulttransport is provided in the 1.6.2)

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,    }} 

As far as I know, there is no mechanism to limit the time it takes to send requests. The current solution is to pass time after the client method returns. Timer to manually control when the request information is read (see "How to cancel a request" below).

Finally, in the new version 1.7, Http.Transport.IdleConnTimeout is provided. It is used to control the retention time of an idle connection in the connection pool, regardless of the stage at which a client request is blocked.

Note that the client will use the default redirection mechanism. Because of HTTP. Transport is an underlying system mechanism, without the redirection concept, so http. The client.timeout covers the time spent on redirection, and finer-timed timeouts can be tailored to different requests.

caotj72 translated 11 months ago 0 People top Top Well translated!

Cancel and Context

Net/http provides two methods for revoking client requests: Request.cancel and the context provided in the new version 1.7.

The Request.cancel is an optional channel. When the request.timeout is triggered, the request.cancel will be set and closed, causing the request to be interrupted (basically "undo" is the same mechanism, when writing this article, I found a 1.7 bug, all undo operation, will be as a timeout error returned).

We can use Request.cancel and time.timer to build a time-out more controllable client that can be used for streaming media. It can reset the deadline after successful response to some of the data in the genre (Body).

package mainimport  (       "io"      "Io/ioutil"      "Log"      "Net/http"      "Time") Func main ()  {      c := make (chan struct{})      Timer := time. Afterfunc (5*time. Second, func ()  {        close (c)     })         // serve 256 bytes every second.     req, err := http. Newrequest ("GET",  "http://httpbin.org/range/2048?duration=8&chunk_size=256",  nil)      if err != nil {        log. Fatal (Err)     }    req. Cancel = c    log. Println ("Sending request ...")     resp, err := http. Defaultclient.do (req)     if err != nil {         log. Fatal (Err)     }    defer resp. Body.close ()     log. Println ("Reading body ...")     for {         timer. Reset (2 * time. Second)                 //  try instead: timer. Reset (50 * time.millisecond)         _, err = io. Copyn (Ioutil. Discard, resp. body, 256)         if err == io. eof {            break         } else if err != nil { &Nbsp;          log. Fatal (Err)         }    }}

In the above example, we set a 5-second timeout in the request phase. But read the response message phase, we need to read 8 times, at least 8 seconds. For each read operation, set a timeout of 2 seconds. With this mechanism, we can gain unrestricted access to streaming media without worrying about the risk of blocking. If we do not read any data within 2 seconds, Io. Copyn will return an error message: Net/http:request canceled.

A new context package has been added to the 1.7 version of the standard library. About contexts, we have a lot of things to learn. Based on the gist of this article, the first thing you should know is that contexts will replace request.cancel and no longer suggest (oppose) using Request.cancel.

caotj72 translated 11 months ago 0 People top Top Well translated!

In order to use contexts to undo a request, we need to create a new context and its Context.withcancel-based cancel () function, as well as create a request.withcontext-based request. When we want to revoke a request, we actually revoke the corresponding context through the Cancel () function (replacing the original way of closing the Cancel channel):

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)

In context (which we provide to the context.) Withcancel) has been withdrawn, the contexts has a more advantageous position. We can send commands to the entire pipeline.

That's it. I hope you understand readdeadline more deeply than I do.

caotj72 translated 11 months ago 0 People top Top Well translated!
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.