TCP连接建立过程中的内核队列机制
服务器运维中,高并发场景下经常遇到连接超时、握手失败等问题,根因往往不在应用层,而在于Linux内核网络参数的默认值过低。Linux内核通过两个独立队列管理TCP连接建立过程:SYN队列(syncookies关联的半连接队列)和ACCEPT队列(全连接队列)。
客户端发起SYN包后,服务端内核将其放入SYN队列并回复SYN-ACK。当三次握手完成,连接从SYN队列移至ACCEPT队列,等待accept()系统调用取走。任一队列溢出都会导致连接异常:SYN队列溢出触发syncookie机制或直接丢弃SYN包;ACCEPT队列溢出时,内核根据tcp_abort_on_overflow决定是忽略ACK还是发送RST。
核心网络参数调优配置
以下参数需写入/etc/sysctl.conf或/etc/sysctl.d/目录下的配置文件,执行sysctl -p生效:
# /etc/sysctl.d/99-network-tuning.conf
# SYN队列长度,默认1024,高并发场景建议32768以上
net.ipv4.tcp_max_syn_backlog = 65536
# ACCEPT队列长度(全连接队列)
# 注意:此参数需配合somaxconn设置,取两者最小值
net.core.somaxconn = 65536
# SYN Cookies防护SYN Flood攻击
net.ipv4.tcp_syncookies = 1
# SYN+ACK重试次数,默认5次约180秒
# 降为2次约15秒,加速失败连接回收
net.ipv4.tcp_synack_retries = 2
# tcp_abort_on_overflow设为0(默认)
# 队列满时丢弃ACK而非发RST,避免客户端报错
net.ipv4.tcp_abort_on_overflow = 0
# 端口范围,默认32768-60999
net.ipv4.ip_local_port_range = 10240 65000
# FIN-WAIT-2状态超时时间(秒),默认60
net.ipv4.tcp_fin_timeout = 15
# TIME_WAIT状态相关
# 开启TIME_WAIT端口复用
net.ipv4.tcp_tw_reuse = 1
# TIME_WAIT状态下Socket的最大数量
net.ipv4.tcp_max_tw_buckets = 32768
# keepalive探测配置
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
# 读写缓冲区大小(字节)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# 网卡接收/发送队列长度
net.core.netdev_max_backlog = 65536
# 连接跟踪表大小(使用nf_conntrack时需要)
net.netfilter.nf_conntrack_max = 1048576
# 文件描述符限制
fs.file-max = 1048576
fs.nr_open = 1048576
文件描述符与进程级限制调整
内核参数fs.file-max设置系统全局文件描述符上限,但单个进程的打开文件数还受ulimit限制。即使内核允许百万级fd,进程默认的1024限制会导致Too many open files错误。
修改/etc/security/limits.conf添加:
# /etc/security/limits.conf
* soft nofile 655360
* hard nofile 655360
* soft nproc 655360
* hard nproc 655360
对于systemd管理的服务(如Nginx、Redis),limits.conf不生效,需要在service单元文件中配置:
# /etc/systemd/system/nginx.service
[Service]
LimitNOFILE=655360
LimitNPROC=655360
# 也可以通过systemctl edit nginx覆盖
# 修改后执行 systemctl daemon-reload && systemctl restart nginx
连接跟踪表与性能监控
当服务器作为NAT网关或运行iptables/nftables防火墙时,每个连接都会在conntrack表中占用一条记录。默认的nf_conntrack_max值通常为65536,在高并发场景下会导致conntrack table full, dropping packet错误。
# 查看当前conntrack使用情况
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
# 查看conntrack哈希表大小
cat /proc/sys/net/netfilter/nf_conntrack_buckets
# 调优建议:max值设为buckets的4倍
# buckets在内核模块加载时确定,通常为max/4
# 如需修改buckets,需在modprobe配置中设置
echo "options nf_conntrack hashsize=262144" > /etc/modprobe.d/nf_conntrack.conf
# conntrack条目超时时间
net.netfilter.nf_conntrack_tcp_timeout_established = 7200
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 30
验证调优效果
使用ss命令查看Socket队列状态,判断调优是否生效:
# 查看监听Socket的SYN和ACCEPT队列使用情况
ss -lnt | head -5
# 输出示例:
# State Recv-Q Send-Q Local Address:Port
# LISTEN 0 65536 0.0.0.0:80
# LISTEN 0 65536 0.0.0.0:443
# Recv-Q为当前ACCEPT队列中的连接数
# Send-Q为ACCEPT队列最大长度(即somaxconn)
# 统计各状态TCP连接数
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
# 使用nstat查看TCP层丢包计数
nstat -az | grep -E "TcpExtListenOverflows|TcpExtListenDrops|TcpExtTCPReqQFullDoCookies"
TcpExtListenOverflows计数持续增长说明ACCEPT队列溢出,需增大somaxconn和应用的backlog参数。TcpExtListenDrops增长则可能是SYN队列溢出或内存不足。通过监控这些计数器指标,可以精确定位网络层面的性能瓶颈,配合系统资源监控完成服务器安全加固和连接数提升的闭环调优。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/linux-nei-he-wang-luo-can-shu-diao-you-yu-tcp-bing-fa-lian/