数据如何从网卡到应用
1 | NIC Kernel Protocols To App |
- 数据进入 Ring Buffer
- NIC硬中断,停止正在运行的进程,上下文切换
- kernel 运行中断处理程序以关闭中断
- kernel 通过 SoftIRQ 来完成实际的接收工作
- SoftIRQ 线程获取数据,通过网卡提供的协议处理程序
- 数据放入到socket缓冲区
- SoftIRQ 线程继续轮询知道数据取完
网络性能瓶颈
频繁中断
以腾讯云的一个vm为例
网卡虚拟化技术,使用的virtio。所以,分析vm的性能,了解virtio的方案是必要的。
以下显示CPU0在处理网卡的中断数量。
多个CPU,中断是否均匀
1 | ubuntu@VM-0-5-ubuntu:~$ cat /proc/interrupts |
合适的eth0队列
每个队列,绑定到不同的cpu上。
1 | # ethtool -l eth0 |
查看eth0的队列
1 | ls /sys/class/net/eth0/queues/ |
设置Ring Buffer
1 | # ethtool --show-ring eth0 |
- data先放在NIC硬件中,kernel从中读取
- 最大值4096
offload 的介入
1 | $ ethtool --show-features eth0|grep offload |
默认网卡上启动了offload,它的作用如下:
如果app发送一个7,300 Bytes的数据,它不会被在TCP层分成5个segment。而是作为一个整体,送到网卡上。
网卡将7,300 Bytes分成5个segment。
检查在队列中的数据
1 | $ cat /proc/net/softnet_stat |
第一列-表示该cpu收到的包个数;
第二列-表示因softnet_data的输入队列满而丢弃的数据包个数(input_pkt_queue,队列长度最大值可通过/proc/sys/net/core/netdev_max_backlog调整);
第三列-表示软中断一次取走netdev_budget个数据包,或取数据包时间超过2ms的次数;
修改netdev_max_backlog方式:
sysctl -a|grep netdev_max_backlog
net.core.netdev_max_backlog = 1000
TCP层控制
1 | #netstat -s|egrep 'pruned|collapsed' |
pruned: 由于套接字缓冲区溢出而从接收队列中删除的数据包
collapsed: Socket buffer满导致包无法放入
调整socket tcp 缓冲区
三列分别是:min default max1
2
3/etc/sysctl.conf
net.ipv4.tcp_rmem = 4096 262144 16777216
net.ipv4.tcp_wmem = 4096 262144 16777216调整socket 非TCP 缓冲区
tcp的缓冲区值,受限于这里的max1
2
3
4net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144讨论是否打开TCP Timestamps
默认打开:
1 | cat /proc/sys/net/ipv4/tcp_timestamps |
如果是NAT的场景,不要使用这个值。原因是:
clientA和clientB都通过lvs访问server1;
time-a: clientA已经访问到server1;
time-b: clientB也是通过lvs服务器访问到server1
lvs的配置:tcp_tw_recycle=1&tcp_timestamps=1
server1: 如果遇到 “源ip:源port” 一样并请求第二次,第二次的时间戳晚,抛弃第二次连接
tcp_tw_recycle 在kernel 4.x版本后已经废弃;
tcp_tw_recycle 表明尽快的回收处于 time_wait 状态的连接,不用等两个 MSL 就关闭连接。
缺点是:会拒绝所有比这个客户端时间戳更靠前的网络包。在开启
- SACK
SACK是接收方用来向发送方通知已经接收到哪些序列号段的一种机制,这样发送方在重传时就只需要重传接收方真正未收到的部分即可。
1 | root@VM-0-5-ubuntu:/proc# sysctl -a|grep tcp_sack |
应用层控制
现象:
1 | [root@VM_0_15_centos ~]# netstat -s | grep -i listen |
可调的位置:
针对accept queue,调整
修改全连接
/proc/sys/net/core/somaxconn
默认128
或者,调整应用层的backlog,比如:
listen 443 ssl backlog=20480;
全连接和半连接的关系: