写golang服务的时候,http网关参数设置出了一点小问题。
先是后台反馈告知: keep alive 时长是不是太短了,经常断开。
我当前的配置是这样的:这里的时间设置的都是3秒钟。
1 2 3 4 5 6 7 |
// http服务 s := &http.Server{ Addr: listenAddr, Handler: app.HandlerFunc(), ReadTimeout: time.Duration(app.Conf.GetConfig().Http.ReadTimeOut) * time.Millisecond, WriteTimeout: time.Duration(app.Conf.GetConfig().Http.WriteTimeout) * time.Millisecond, } |
如果你能看出问题,就不需要继续往下读了。
第一次排查问题: keep alive 是默认打开的,且没有任何参数。 故暂放了一段时间。
近期再次排查问题: 挨个阅读http.Server结构体内参数:
Addr:
Addr optionally specifies the TCP address for the server to listen on, in the form “host:port”. If empty, “:http” (port 80) is used. The service names are defined in RFC 6335 and assigned by IANA. See net.Dial for details of the address format.
Addr翻译:
Addr参数可以指定要监听的服务器TCP地址,其形式为: “host:port”.
如果为空,则使用 “:http”,默认端口是 80
服务名称由 IANA 在 RFC6335协议定义。
更详细的地址格式可以查看net.Dial.
Handler:
handler to invoke, http.DefaultServeMux if nil
Handler翻译:
要调用的处理器,如果为nil则调用默认处理器 http.DefaultServeMux
TLSConfig:
这个不关心,与https相关的.
ReadTimeout:
ReadTimeout is the maximum duration for reading the entire request, including the body.
Because ReadTimeout does not let Handlers make per-request decisions on each request body’s acceptable deadline or upload rate, most users will prefer to use ReadHeaderTimeout. It is valid to use them both.
ReadTimeout翻译:
ReadTimeout是读取整个请求(包括请求体)的最大持续时间。
因为ReadTimeout不允许处理程序对每个请求主体的可接受的截止日期或上传速率做出每个请求的决定,大多数用户更喜欢使用ReadHeaderTimeout。两者都可以使用。
注意这里,之前读的时候并没有理解这里的<每个请求>的意义以及对ReadHeaderTimeOut的理解。 继续往下阅读。
ReadHeaderTimeout:
ReadHeaderTimeout is the amount of time allowed to read request headers. The connection’s read deadline is reset after reading the headers and the Handler can decide what is considered too slow for the body. If ReadHeaderTimeout is zero, the value of ReadTimeout is used. If both are zero, there is no timeout.
ReadHeaderTimeout翻译:
ReadHeaderTimeout是允许读取请求头的时间。连接的读取截止日期在读取请求头后被重置,处理程序可以决定什么对主体来说太慢。
如果ReadHeaderTimeout为0,则使用ReadTimeout的值。如果两者都为零,则不存在超时。
这里就很精髓了,连接的读取截止日期再读取请求头后被重置。意思就是每次请求都重置截止时间。那反过来看就是 ReadTimeout就可能是导致keep alive 断开的罪魁祸首。
WriteTimeout:
WriteTimeout is the maximum duration before timing out writes of the response. It is reset whenever a new request’s header is read. Like ReadTimeout, it does not let Handlers make decisions on a per-request basis.
WriteTimeout翻译:
WriteTimeout是响应写入超时之前的最大持续时间。
每当读取一个新的请求头时,它都会被重置。
与ReadTimeout一样,它不允许处理程序根据每个请求做出决定。
每次读取一个新的请求头都会被重置,那么连接就不会因此断开。
假设设置为3秒钟,那么意思是读取完请求头之后有3秒的时间可以处理,3秒内必须返回。
IdleTimeout:
IdleTimeout is the maximum amount of time to wait for the next request when keep-alives are enabled. If IdleTimeout is zero, the value of ReadTimeout is used. If both are zero, there is no timeout.
IdleTimeout翻译:
IdleTimeout是启用keep-alive时等待下一个请求的最大时间。
如果IdleTimeout为0,则使用ReadTimeout的值。如果两者都为零,则不存在超时。
很明确了,就是因为我们设置了ReadTimeout的值,导致IdleTimeout为0时使用了ReadTimeout的值,3秒…
MaxHeaderBytes:
MaxHeaderBytes controls the maximum number of bytes the server will read parsing the request header’s keys and values, including the request line. It does not limit the size of the request body. If zero, DefaultMaxHeaderBytes is used.
MaxHeaderBytes翻译:
MaxHeaderBytes控制服务器解析请求头的键和值(包括请求行)时将读取的最大字节数。它不限制请求体的大小。
如果为0,则使用DefaultMaxHeaderBytes。
解决方案:
ReadTimeout 和 WriteTimeout 设置为30秒即可
- 请求发起,读取请求Header,读取请求Body,处理请求,Write Response,Idle。
- 那么 读取请求Header,读取Body,写返回值,Idle。这四步的等待时间都可能导致连接断开。
- 所以读取Header,Body,Witre 和 Idle 的时长都需要增加到30秒。
- 那么总结起来就是 ReadTimeout 和 WriteTimeout。
完毕…