Go 中 http 超时问题的排查( 四 )


简化来说:

  1. 调用方和服务方使用 http1.1 升级到 http2 的模式进行通讯
  2. 服务方 http2Serve r限制单连接并发数是 250
  3. 当并发超过 250 , 比如 1000 时 , 调用方就会并发创建 750 个连接 。这些连接的tls握手时间会越来越长 。而调用超时只有1s , 所以导致大量超时 。
  4. 这些连接有些没到服务方就超时 , 有些到了但服务方还没来得及处理 , 调用方就取消连接了 , 也是超时 。
并发量高的情况下 , 如果有网络断开 , 也会导致这种情况发送 。
 
重试
A服务使用的轻量级 http-sdk 有一个重试机制 , 当检测到是一个临时错误时 , 会重试 2 次 。
Temporary() bool // Is the error temporary?而这个超时错误 , 就属于临时错误 , 从而放大了这种情况发生 。
解决办法
不是升级模式的 http2 即可 。
httpClient.Transport = &http2.Transport{ TLSClientConfig: tlsConfig,}为什么 http2 不会大量创建连接呢?
这是因为 http2 创建新连接时会加锁 , 后面的请求解锁后 , 发现有连接没超过并发数时 , 直接复用连接即可 。所以没有这种情况 , 这个锁在 clientConnPool.getStartDialLocked 源码中 。
 
问题1
问题1:A服务使用 http1.1 发送请求到 B 服务超时 。
问题1 和问题 2 的原因一样 , 就是高并发来的情况下 , 会创建大量连接 , 连接的创建会越来越慢 , 从而超时 。这种情况没有很好的办法解决 , 推荐使用 http2 。如果不能使用 http2 , 调大 MaxIdleConnsPerHost 参数 , 可以缓解这种情况 。默认 http1.1 给每个 host 只保留 2 个空闲连接 , 来个1000 并发 , 就要创建 998 新连接 。该调整多少 , 可以视系统情况调整 , 比如 50 , 100 。

【Go 中 http 超时问题的排查】


推荐阅读