最近针对公司的 goscon 网关发了一个 PR,新增了握手阶段的超时判定。现在回顾一下 Nginx 的所有超时判定,看看目前还缺少哪些判定

**client_header_timeout (默认 60 秒)**

**client_body_timeout  (默认 60 秒)**

**keepalive_timeout   (默认 75 秒)**

**lingering_timeout   (默认 5 秒)**

**<strong>resolver_timeout    (默认 30 秒)**</strong>

**send_timeout      (默认 60 秒)**

上述参数对应的行为如下:

  1. **client_header_timeout** 对应的是客户端发送 http 请求头的行为
  2. **client_body_timeout** 对应的是客户端发送 http 消息体的行为
  3. **keepalive_timeout** 对应的是 http 1.1 协议里的保活时长
  4. **lingering_timeout** 是配合 **lingering_close** 使用的,就是说关闭 socket 前,客户端还有数据发给服务器的话,**lingering_close** 用于设定要不要等客户端继续发,<code>**lingering_timeout** 决定等多久。这里是一个等待 - 读取 - 抛弃数据的循环,有可能重复多次,但是每次等待都不会超过 **lingering_timeout** 设定的时长</code>
  5. **<strong>resolver_timeout**</strong>对应的是域名解析的时长
  6. **send_timeout** 对应的是发送 http 响应给客户端时的超时。这里对应的是两次写操作之间的时长,经过了 **send_timeout** 的时间后,还不能写的话,就关闭连接。

对应到 goscon,目前的超时参数,是 reuseTimeout 和 uploadMaxDelay。reuseTimeout 会在 read/write 操作异常的时候生效,度过 reuseTimeout 时间后,goscon 保持的连接对就会被释放,里面的缓存数据都会丢掉。从行为上看,有点类似 Nginx 的 keepalive_timeout。

uploadMaxDelay 是用在给 socket 设置读超时上的,只要设置了这个参数(和 optUploadMinPacket),每次从 socket 里读数据都会设置一个 deadline。超过 deadline 后,会返回错误。这里漏了一个写的超时,留了个 SetWriteDeadline 的接口,但是没有调用。每次写操作也应该有类似的流程,超过 delay 后 write 就返回 error,Timeout()==True。这个参数类似于 Nginx 的 send_timeout,针对的是两次成功写操作的间隔。缺陷是对方依然可以每次读 1 个字节,然后等满一次 timeout 来占用资源。

这次 goscon 新增的握手阶段的超时(handshakeTimeout),类似于 client_header_timeout+client_body_timeout+send_timeout,包含了服务器对客户端的一次读,对客户端的一次写。之前只要连上 tcp,不进行握手操作,不会有任何超时机制,目前新增的超时可以针对这种情况做处理。