TCP全链接队列

本文探讨了客户端调用RT较高及Connectionreset问题的原因,分析了由于服务端API处理缓慢导致的TCP全链接队列溢出现象。介绍了TCP三次握手过程中涉及的全链接队列与半链接队列的概念,并提供了如何通过ss命令查看队列状态的方法,以及如何调整系统参数避免队列溢出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

最近发现客户端调用RT比较高,并且偶尔Connection reset出现,而查看服务运行情况,资源占用cpu、memory和线程都正常。通过分析是服务的一个api接口处理过慢,慢接口导致tcp全链接队列溢出

全链接队列和半链接队列

  • tcp三次握手时,linux内核会维护两个队列:
    全链接队列,也称为syn队列
    半链接队列,也称为accept队列

三次握手过程

1、 客户端发送SYN包,并进入SYN_SENT状态
2、服务端接收到数据包将相关信息放入半连接队列(SYN 队列),并返回SYN+ACK包给客户端。
3、服务端接收客户端ACK数据包,这时如果全连接队列(accept 队列)没满,就会从半连接队列里面将数据取出来放入全连接队列,等待应用使用,当队列已满就会跟据tcp_abort_on_overflow配置执行策略。

查看全链接队列

执行命令:ss
ss 命令获取数据又分为LISTEN 状态,和非LISTEN 状态。

  • ss -tln
    其中l显示正在listener的socket n指不解析服务名称 t指tcp链接
    Recv-Q 完成三次握手并等待服务端 accept() 的 TCP 全连接总数,(全链接队列里的tcp连接个数)
    Send-Q 全连接队列大小

  • ss -tn
    Recv-Q 已收到但未被应用进程读取的字节数
    Send-Q 已发送但未收到确认的字节数

  • 查看全链接队列溢出次数,执行命令: netstat -s | egrep “listen|LISTEN”

解决办法
  • TCP三次握手的最后一步,当全连接队列已满就会根据tcp_abort_on_overflow策略进行处理。Linux 可通过 /proc/sys/net/ipv4/tcp_abort_on_overflow 进行配置。

  • 当tcp_abort_on_overflow=0,服务accept 队列满了,客户端发来ack,服务端直接丢弃该ACK,此时服务端处于【syn_rcvd】的状态,客户端处于【established】的状态。在该状态下会有一个定时器重传服务端 SYN/ACK 给客户端(不超过 /proc/sys/net/ipv4/tcp_synack_retries 指定的次数,Linux下默认5)。超过后,服务器不在重传,后续也不会有任何动作。如果此时客户端发送数据过来,服务端会返回RST。(这也就是我们的异常原因了)

  • 当tcp_abort_on_overflow=1,服务端accept队列满了,客户端发来ack,服务端直接返回RST通知client,表示废掉这个握手过程和这个连接,client会报connection reset by peer。

  • 全连接队列大小取决于backlog 和somaxconn 的最小值,也就是 min(backlog,somaxconn)

  • somaxconn 是Linux内核参数,默认128,可通过/proc/sys/net/core/somaxconn进行配置

  • backlog是 listen(int sockfd,int backlog)函数中的参数backlog,Tomcat 默认100,Nginx 默认511.

backlog配置
  • Nginx 配置 server{ listen 8080 default_server backlog=512}
  • Redis 配置redis.conf文件 tcp-backlog 511参数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值