目 录CONTENT

文章目录

【实践】网络与服务器请求故障排查实践

FatFish1
2024-12-23 / 0 评论 / 0 点赞 / 51 阅读 / 0 字 / 正在检测是否收录...

问题1 三次握手产生的连接池满

【现象】:QPS远低于预期值,压测机请求产生大量网络异常:Connection time out/Read time out,后端未观测到很多请求

【思路】:连接超时,看起来多半是网络问题,如果是后端主动拒绝连接(tomcat线程池满等),报错不应该是连接超时

【排查流程】:

  • 在节点上查看网络情况

netstat -nat | awk '/tcp/{print $6}' | sort | uniq -c

>>
700 SYN_RECV
200 ESTABLISHED
……
  • 看到有700的SYN_RECV半连接产生,即想到与三次握手相关的配置

# 半连接队列长度
$ sysctl net.ipv4.tcp_max_syn_backlog
>> 128

# 全连接队列长度
$ sysctl net.core.somaxconn
>> 1024

三次握手的流程中,客户端实际上向服务器发送了两个连接请求,一次请求syn,一次应答ack,这两个请求分别存放在半连接队列net.ipv4.tcp_max_syn_backlog中和全连接队列net.core.somaxconn

net.ipv4.tcp_max_syn_backlog设置过小,服务器就会丢弃过量的半连接,客户端长期无法建立连接,就会产生Connetion time out异常

net.core.somaxconn过小,服务器就会丢弃过量的全连接,客户端认为连接建立了,但是长期收不到服务器数据,就会产生Read time out异常

http://www.chymfatfish.cn/archives/net%26socket#tcp%E5%BB%BA%E7%AB%8B%E8%BF%9E%E6%8E%A5%E7%9A%84%E8%BF%87%E7%A8%8B---%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B

问题2 tcp重发导致的socket无法断连

为了节省tcp连接产生的开销,socket被设计成一个长连接,一旦连接建立,socket不会在发送一轮数据后就关闭

但是有些主备倒换场景下(比如redis、sftp),原本连接在主节点上的socket由于倒换变成了从节点,但是本质上addr还没有变,只是从节点不给访问了,这时候客户端不会立刻收到RST包,而是基于tcp重连机制进行重传,重传次数参考配置内核参数net.ipv4.tcp_retries2 ,默认值15次,重传时间从200ms递增,最大到120s,超过最大重传次数后客户端才会收到RST包,得知socket已断开

使用socket作为底层连接并且有池化逻辑的服务都可能存在此问题,例如:Jedis/Lettuce、Jsch

Jedis对此做了优化,见jedis部分

http://www.chymfatfish.cn/archives/jedis

lettuce没有优化,可以通过修改socket配置解决:

.tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT))

0

评论区