Linux性能优化从入门到实战:20 综合篇:网络丢包

网络丢包问题的分析思路

ping 基于 ICMP 协议,hping3 可以基于 TCP 协议。

hping3 实际上只发送了 SYN 包;
curl 在发送 SYN 包后,还会发送 HTTP GET 请求。

# -c 表示发送 10 个请求,-S 表示使用 TCP SYN,-p 指定端口为 80
$ hping3 -c 10 -S -p 80 192.168.0.30
HPING 192.168.0.30 (eth0 192.168.0.30): S set, 40 headers + 0 data bytes
len=44 ip=192.168.0.30 ttl=63 DF id=0 sport=80 flags=SA seq=3 win=5120 rtt=7.5 ms
...
--- 192.168.0.30 hping statistic ---
10 packets transmitted, 5 packets received, 50% packet loss
round-trip min/avg/max = 3.0/609.7/3027.2 ms

$ curl --max-time 3 http://192.168.0.30

Linux性能优化从入门到实战:20 综合篇:网络丢包

(1)链路层

# 查看网卡的丢包记录
$ netstat -i
Kernel Interface table
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0       100       31      0      0 0             8      0      0      0 BMRU
lo       65536        0      0      0 0             0      0      0      0 LRU

#  tc 规则(用于QoS)导致的丢包(不包含在网卡的统计信息中)
$ tc -s qdisc show dev eth0
qdisc netem 800d: root refcnt 2 limit 1000 loss 30%
 Sent 432 bytes 8 pkt (dropped 4, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
# 解决方法:删掉 netem 模块
$ # tc qdisc del dev eth0 root netem loss 30%

(2)网络层和传输层

$ netstat -s
Ip:
    Forwarding: 1					// 开启转发
    31 total packets received		// 总收包数
    0 forwarded						// 转发包数
    0 incoming packets discarded	// 接收丢包数
    25 incoming packets delivered	// 接收的数据包数
    15 requests sent out			// 发出的数据包数
Icmp:
    0 ICMP messages received		// 收到的 ICMP 包数
    0 input ICMP message failed		// 收到 ICMP 失败数
    ICMP input histogram:
    0 ICMP messages sent			//ICMP 发送数
    0 ICMP messages failed			//ICMP 失败数
    ICMP output histogram:
Tcp:
    0 active connection openings	// 主动连接数
    0 passive connection openings	// 被动连接数
    11 failed connection attempts	// 失败连接尝试数
    0 connection resets received	// 接收的连接重置数
    0 connections established		// 建立连接数
    25 segments received			// 已接收报文数
    21 segments sent out			// 已发送报文数
    4 segments retransmitted		// 重传报文数
    0 bad segments received			// 错误报文数
    0 resets sent					// 发出的连接重置数
Udp:
    0 packets received
    ...
TcpExt:
    11 resets received for embryonic SYN_RECV sockets	// 半连接重置数
    0 packet headers predicted
    TCPTimeouts: 7		// 超时数
    TCPSynRetrans: 4	//SYN 重传数
	...

(3)iptables

# 查询 NAT 连接跟踪数
$ sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 262144
$ sysctl net.netfilter.nf_conntrack_count
net.netfilter.nf_conntrack_count = 182

$ iptables -t filter -nvL
Chain INPUT (policy ACCEPT 25 packets, 1000 bytes)
 pkts bytes target     prot opt in     out     source               destination
    6   240 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode random probability 0.29999999981

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 15 packets, 660 bytes)
 pkts bytes target     prot opt in     out     source               destination
    6   264 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            statistic mode random probability 0.29999999981
# 解决方法:两条 DROP 规则统计数值不为0,所以删除它们
$ iptables -t filter -D INPUT -m statistic --mode random --probability 0.30 -j DROP
$ iptables -t filter -D OUTPUT -m statistic --mode random --probability 0.30 -j DROP

# MTU 问题与解放方法:eth0 的 MTU 只有 100,而以太网的 MTU 默认值是 1500
$ ifconfig eth0 mtu 1500