正常的三次握手情况如下
问题
1、服务,CPU消耗从15%消耗突增到了80%,问题在哪?
问题背景:线上一直4核单需要支持2000QPS一直无异常,CPU利用率维持在15%左右。但是在某次上线后,每次请求增加一次redis访问,线上CPU利用率飙升至80%。
请看命令
问题出现在connect选择端口的过程中
由于底层是遍历查找
如果内核现在只剩下一个端口可用的情况下,每次的遍历查找消耗就会极大。同时内核为了防止多进程选择端口冲突,会进行加锁。这个两个原因造成性能问题。
2、偶发的线上访问耗时,该如何排查和处理?
详情参考队列溢出导致的超时问题
connect可能发生的问题
1、服务端,connect过程由于底层是遍历查找
如果内核现在只剩下一个端口可用的情况下,每次的遍历查找消耗就会极大。同时内核为了防止多进程选择端口冲突,会进行加锁。这两个原因可能造成性能上的突发问题。
队列溢出可能会导致超时问题
客户端connect包发出时会启动一个重传定时器,用做重试机制
现在我们将视角转换到服务端
如果服务端的连接队列已经满了,那么对于connect的请求就会丢弃,从而造成客户端进行重试,用户体验上就是页面的显示就给人一种网络不好,十分卡顿的现象。
客户端在1S以后进行了第一次握手重试,接下来又在3,7,15,31,63S等时间共重试6次(这个重试了多少次要看具体的tcp_syn_retries设置的值为多少)
所以加入服务器上出现了半/全连接队列溢出导致的丢包问题,那接口的响应至少时1S以上
三次握手相关的优化方法
➤ 如果请求频繁,请弃用短连接改用长连接
➤ 如果可能,尽量合并请求!
➤ 客户端注意 ip_local_port_range 要够用
➤ 客户端连接不同的服务端
➤ 打开 SYN cookie 避免半连接队列溢出
➤ 服务端通过 backlog 和 net.core.somaxconn 控制合适的连接队列长度
➤ 服务端应该尽快 accept 让应用取走连接