在linux上做网络应用的性能优化时,一般都会对TCP相关的内核参数进行调节,特别是和缓冲、队列有关的参数 。很多文章会告诉你需要修改哪些参数,但我们经常是知其然而不知其所以然,每次照抄过来后,可能很快就忘记或混淆了它们的含义 。
下面我以server端为视角,从 连接建立、 数据包接收 和 数据包发送 这3条路径对参数进行归类梳理 。
一、连接建立
![Linux TCP队列相关参数的总结](http://img.jiangsulong.com/220427/05301K2D-0.jpg)
文章插图
简单看下连接的建立过程,客户端向server发送SYN包,server回复SYN+ACK,同时将这个处于SYN_RECV状态的连接保存到半连接队列 。客户端返回ACK包完成三次握手,server将ESTABLISHED状态的连接移入accept队列,等待应用调用accept() 。可以看到建立连接涉及两个队列:
- 半连接队列,保存SYN_RECV状态的连接 。队列长度由net.ipv4.tcp_max_syn_backlog设置
- accept队列,保存ESTABLISHED状态的连接 。队列长度为min(net.core.somaxconn,backlog) 。其中backlog是我们创建ServerSocket(intport,int backlog)时指定的参数,最终会传递给listen方法: #include int listen(int sockfd, int backlog); 如果我们设置的backlog大于net.core.somaxconn,accept队列的长度将被设置为net.core.somaxconn
二、数据包的接收先看看接收数据包经过的路径:
![Linux TCP队列相关参数的总结](http://img.jiangsulong.com/220427/05301L603-1.jpg)
文章插图
数据包的接收,从下往上经过了三层:网卡驱动、系统内核空间,最后到用户态空间的应用 。Linux内核使用sk_buff(socketkernel buffers)数据结构描述一个数据包 。当一个新的数据包到达,NIC(networkinterface controller)调用DMAengine,通过RingBuffer将数据包放置到内核内存区 。RingBuffer的大小固定,它不包含实际的数据包,而是包含了指向sk_buff的描述符 。当RingBuffer满的时候,新来的数据包将给丢弃 。一旦数据包被成功接收,NIC发起中断,由内核的中断处理程序将数据包传递给IP层 。经过IP层的处理,数据包被放入队列等待TCP层处理 。每个数据包经过TCP层一系列复杂的步骤,更新TCP状态机,最终到达recvBuffer,等待被应用接收处理 。有一点需要注意,数据包到达recvBuffer,TCP就会回ACK确认,既TCP的ACK表示数据包已经被操作系统内核收到,但并不确保应用层一定收到数据(例如这个时候系统crash),因此一般建议应用协议层也要设计自己的确认机制 。
【文章福利】需要C/C++ Linux服务器架构师学习资料加群812855908(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)
![Linux TCP队列相关参数的总结](http://img.jiangsulong.com/220427/05301LO8-2.jpg)
文章插图
上面就是一个相当简化的数据包接收流程,让我们逐层看看队列缓冲有关的参数 。
1、网卡Bonding模式 当主机有1个以上的网卡时,Linux会将多个网卡绑定为一个虚拟的bonded网络接口,对TCP/IP而言只存在一个bonded网卡 。多网卡绑定一方面能够提高网络吞吐量,另一方面也可以增强网络高可用 。Linux支持7种Bonding模式:
详细的说明参考内核文档LinuxEthernet Bonding Driver HOWTO 。我们可以通过
cat/proc/net/bonding/bond0查看本机的Bonding模式:
![Linux TCP队列相关参数的总结](http://img.jiangsulong.com/220427/05301L447-3.jpg)
文章插图
一般很少需要开发去设置网卡Bonding模式,自己实验的话可以参考这篇文档 。
- Mode 0(balance-rr) Round-robin策略,这个模式具备负载均衡和容错能力
- Mode 1(active-backup) 主备策略,在绑定中只有一个网卡被激活,其他处于备份状态
- Mode 2(balance-xor) XOR策略,通过源mac地址与目的MAC地址做异或操作选择slave网卡
- Mode 3 (broadcast) 广播,在所有的网卡上传送所有的报文
- Linux 环境下 DNS 域名解析服务
- Linux的系统启动卡制作及系统固化
- 通过十个问题助你彻底理解linux epoll工作原理
- 动图图解!既然IP层会分片,为什么TCP层也还要分段?
- linux内核协议栈 UDP之数据报接收过程
- Linux系统目录结构介绍
- Linux的sz和rz命令
- linux系统上查看载体为实体机还是虚拟机
- Linux上,最常用的十条命令
- Linux内核快速处理路径尽量多用kmem_cache而慎用kmalloc