Linux系统丢包相关 一、测试工具 Siege是linux下的一个web系统的压力测试工具,支持多链接,支持get和post请求,可以对web系统进行多并发下持续请求的压力测试。 -c 200 指定并发数200 -r 5 指定测试的次数5 -f urls.txt 制定url的文件 -i internet系统,随机发送url -b 请求无需等待 delay=0 -t 5 持续测试5分钟 比如:siege -c 200000 -r 100000 192.168.1.2 80 20万并发10万次
tcping ping这个小工具大家都非常熟悉,但是他不能ping端口,当我们需要知道目的地址的某端口是否开放时,这时需要用到这个tcping小工具了 比如:tcping -n 100 -d -g 1 192.168.1.2 443 -n 100次 -d 显示时间 -g 2秒内未回包 立即结束
二、排查丢包相关 1、连接跟踪表溢出 连接跟踪表溢出而开始丢包,首先需要查看具体连接判断是否正遭受DOS攻击,如果是正常的业务流量造成,可以考虑调整nf_conntrack的参数: cat /proc/sys/net/nf_conntrack_max 查看支持最大连接数(默认50万)具体看硬件性能 cat /proc/net/ip_conntrack|wc –l 查看当前跟踪数(不会超过50万) cat /proc/sys/net/netfilter/nf_conntrack_buckets 存储conntrack条目的哈希表大小,默认值是nf_conntrack_max的1/4 cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established 决定ESTABLISHED状态连接的超时时间,默认是432000秒,就是5天; cat /proc/net/nf_conntrack | cut -d ’ ’ -f 16 | cut -d ‘=’ -f 2| sort | uniq -c | sort -nr | head -n 16 查看最多连接IP cat /proc/net/nf_conntrack 连接跟踪(conntrack)记录
2、Ring Buffer溢出 排除防火墙的因素,从底向上看Linux接收数据包的处理,网卡驱动层; ethtool或/proc/net/dev可以查看因Ring Buffer满而丢弃的包统计,在统计项中以fifo标识: ethtool -S eno1 | grep rx_ | grep errors 通过ethtool可以查看网卡设备Ring Buffer最大值 查看网卡Ring Buffer最大值和当前设置 ethtool -g eth0 默认为256 修改网卡eth3接收与发送硬件缓存区大小 ethtool -G eth0 rx 4096 tx 4096
3、单队列网卡导致单线程CPU过高
当有大量数据包时、top或者htop会发现CPU 0 使用率百分之百 cat /proc/interrupts 查看大量包是否都在一行、后边123…CPU数据包特小 第一列为ID、最后一列为接口、选数据量大的 比如: echo 01 > /proc/irq/112/smp_affinity 0号网卡接口使用CPU-01 echo 02 > /proc/irq/124/smp_affinity 6号网卡接口使用CPU-02 这样可以减轻一半单线程CPU负载
有的设备不支持多队列网卡、架构问题、只能临时CPU绑定网卡接口
4、netdev_max_backlog溢出 netdev_max_backlog是内核从NIC收到包后,交由协议栈(如IP、TCP)处理之前的缓冲队列。每个CPU核都有一个backlog队列,与Ring Buffer同理,当接收包的速率大于内核协议栈处理的速率时,CPU的backlog队列不断增长,当达到设定的netdev_max_backlog值时,数据包将被丢弃 cat /proc/net/softnet_stat 00987be2 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000ca1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
每一行代表每个CPU核的状态统计,从CPU0依次往下; 每一列代表一个CPU核的各项统计:第一列代表中断处理程序收到的包总数;第二列即代表由于netdev_max_backlog队列溢出而被丢弃的包总数。 从上面的输出可以看出,这台服务器统计中,并没有因为netdev_max_backlog导致的丢包。
netdev_max_backlog的默认值是1000,在高速链路上,可能会出现上述第二列统计不为0的情况,可以通过修改内核参数net.core.netdev_max_backlog来解决: sysctl -w net.core.netdev_max_backlog=2000
5、 反向路由过滤 反向路由过滤机制是Linux通过反向路由查询,检查收到的数据包源IP是否可路由(Loose mode)、是否最佳路由(Strict mode),如果没有通过验证,则丢弃数据包,设计的目的是防范IP地址欺骗攻击。rp_filter提供了三种模式供配置: ? 0 - 不验证 ? 1 - RFC3704定义的严格模式:对每个收到的数据包,查询反向路由,如果数据包入口和反向路由出口不一致,则不通过 ? 2 - RFC3704定义的松散模式:对每个收到的数据包,查询反向路由,如果任何接口都不可达,则不通过 SUGAP# cat /proc/sys/net/ipv4/conf/eth3/rp_filter 0 根据实际网络环境将rp_filter设置为0或2: sysctl -w net.ipv4.conf.all.rp_filter=2 或 sysctl -w net.ipv4.conf.eth0.rp_filter=2
6、 半连接队列溢出 半连接队列指的是TCP传输中服务器收到SYN包但还未完成三次握手的连接队列,队列大小由内核参数tcp_max_syn_backlog定义。 当服务器保持的半连接数量达到tcp_max_syn_backlog后,内核将会丢弃新来的SYN包。 半连接队列的连接数量可以通过netstat统计SYN_RECV状态的连接得知 dmesg | grep “TCP: drop open request from” netstat -ant|grep SYN_RECV|wc –l 0 大多数情况下这个值应该是0或很小,因为半连接状态从第一次握手完成时进入,第三次握手完成后退出,正常的网络环境中这个过程发生很快,如果这个值较大,服务器极有可能受到了SYN Flood攻击。 tcp_max_syn_backlog的默认值是256,通常推荐内存大于128MB的服务器可以将该值调高至1024,内存小于32MB的服务器调低到128,同样,该参数通过sysctl修改 sysctl -w net.ipv4.tcp_max_syn_backlog=1024 受到内核参数tcp_syncookies的影响,若启用syncookie机制,当半连接队列溢出时,并不会直接丢弃SYN包,而是回复带有syncookie的SYC+ACK包,设计的目的是防范SYN Flood造成正常请求服务不可用。 sysctl -w net.ipv4.tcp_syncookies=1
7、 高带宽下,TCP序列号在一次会话中可能被重复使用而带来的问题。 PAWS全名Protect Againest Wrapped Sequence numbers,目的是解决在高带宽下,TCP序列号在一次会话中可能被重复使用而带来的问题。 依赖于timestamp机制,理论依据是:在一条正常的TCP流中,按序接收到的所有TCP数据包中的timestamp都应该是单调非递减的,这样就能判断那些timestamp小于当前TCP流已处理的最大timestamp值的报文是延迟到达的重复报文,可以予以丢弃。服务器已经处理数据包Z,而后到来的A1包的timestamp必然小于Z包的timestamp,因此服务端会丢弃迟到的A1包,等待正确的报文到来。 PAWS机制的实现关键是内核保存了Per-Connection的最近接收时间戳,如果加以改进,就可以用来优化服务器TIME_WAIT状态的快速回收。 TIME_WAIT状态是TCP四次挥手中主动关闭连接的一方需要进入的最后一个状态,并且通常需要在该状态保持2MSL(报文最大生存时间),它存在的意义有两个: 1.可靠地实现TCP全双工连接的关闭:关闭连接的四次挥手过程中,最终的ACK由主动关闭连接的一方(称为A)发出,如果这个ACK丢失,对端(称为B)将重发FIN,如果A不维持连接的TIME_WAIT状态,而是直接进入CLOSED,则无法重传ACK,B端的连接因此不能及时可靠释放。 2.等待“迷路”的重复数据包在网络中因生存时间到期消失:通信双方A与B,A的数据包因“迷路”没有及时到达B,A会重发数据包,当A与B完成传输并断开连接后,如果A不维持TIME_WAIT状态2MSL时间,便有可能与B再次建立相同源端口和目的端口的“新连接”,而前一次连接中“迷路”的报文有可能在这时到达,并被B接收处理,造成异常,维持2MSL的目的就是等待前一次连接的数据包在网络中消失。 TIME_WAIT状态的连接需要占用服务器内存资源维持,Linux内核提供了一个参数来控制TIME_WAIT状态的快速回收:tcp_tw_recycle,它的理论依据是: 在PAWS的理论基础上,如果内核保存Per-Host的最近接收时间戳,接收数据包时进行时间戳比对,就能避免TIME_WAIT意图解决的第二个问题:前一个连接的数据包在新连接中被当做有效数据包处理的情况。这样就没有必要维持TIME_WAIT状态2MSL的时间来等待数据包消失,仅需要等待足够的RTO(超时重传),解决ACK丢失需要重传的情况,来达到快速回收TIME_WAIT状态连接的目的。 但上述理论在多个客户端使用NAT访问服务器时会产生新的问题:同一个NAT背后的多个客户端时间戳是很难保持一致的(timestamp机制使用的是系统启动相对时间),对于服务器来说,两台客户端主机各自建立的TCP连接表现为同一个对端IP的两个连接,按照Per-Host记录的最近接收时间戳会更新为两台客户端主机中时间戳较大的那个,而时间戳相对较小的客户端发出的所有数据包对服务器来说都是这台主机已过期的重复数据,因此会直接丢弃。 netstat可以得到因PAWS机制timestamp验证被丢弃的数据包统计: netstat -s |grep -e “passive connections rejected because of time stamp” -e “packets rejects in established connections because of timestamp”
sysctl net.ipv4.tcp_tw_recycle net.ipv4.tcp_tw_recycle = 0 (默认0) SUGAP# SUGAP# sysctl net.ipv4.tcp_timestamps net.ipv4.tcp_timestamps = 1 (默认1) SUGAP# 同时开启了tcp_tw_recycle和timestamps,而客户端正是使用NAT来访问服务器,造成启动时间相对较短的客户端得不到服务器的正常响应。 如果服务器作为服务端提供服务,且明确客户端会通过NAT网络访问,或服务器之前有7层转发设备会替换客户端源IP时,是不应该开启tcp_tw_recycle的,而timestamps除了支持tcp_tw_recycle外还被其他机制依赖 #sysctl -w net.ipv4.tcp_tw_recycle=0 #sysctl -w net.ipv4.tcp_timestamps=1
8、丢数据、还有可能是开发问题 htop查看占用CPU最高的进程、你会发现CPU 0 爆、其他CPU不怎么动; 这时候可能他程序就有问题了、不能多个CPU负载;
最终你的CPU、内存、网卡、IO 使用率不超百分之80、9.9成啥故障没有;
|