【Linux 性能优化系列】Linux 性能优化 -- 网络性能篇(四) 网络延迟优化
【1】网络延迟优化
网络时延的测试方法
hping3 命令
安装
sudo apt-get install hping3
hping3 命令,测试与百度的延迟
# -c表示发送3次请求,-S表示设置TCP SYN,-p表示端口号为80
$ hping3 -c 3 -S -p 80 baidu.com
traceroute 命令
安装
sudo apt-get install traceroute
traceroute 命令,测试与百度的延迟
# --tcp表示使用TCP协议,-p表示端口号,-n表示不对结果中的IP地址执行反向域名解析
$ traceroute --tcp -p 80 -n baidu.com
traceroute 会在路由的每一跳发送三个包,并在收到响应后,输出往返延时;如果无响应或者响应超时(默认 5s),就会输出一个星号;
【2】网络丢包优化
丢包指在网络数据的收发过程中,数据包还没传输到应用程序中,就被丢弃的现象;被丢弃包的数量,除以总的传输包数,即丢包率,丢包率是网络性能中最核心的指标之一;
丢包通常会带来严重的性能下降,对于 TCP 丢包通常意味着网络拥塞和重传,进而还会导致网络延迟增大、吞吐降低;
丢包在网络传输中出现的位置
- 在两台计算机连接之间,可能会发生传输失败的错误,比如网络拥塞、线路错误等;
- 在网卡收包后,环形缓冲区可能会因为溢出而丢包;
- 在链路层,可能会因为网络帧校验失败、QoS 等而丢包;
- 在 IP 层,可能会因为路由失败、组包大小超过 MTU 等而丢包;
- 在传输层,可能会因为端口未监听、资源占用超过内核限制等而丢包;
- 在套接字层,可能会因为套接字缓冲区溢出而丢包;
- 在应用层,可能会因为应用程序异常而丢包;
- 若配置了 iptables 规则,网络包可能因为 iptables 过滤规则而丢包;
【2.1】链路层丢包排查
netstat 命令 -- 检查网卡丢包
命令
netstat -i
- RX-OK、RX-ERR、RX-DRP、RX-OVR,分别表示接收时的总包数、总错误数、进入 Ring Buffer 后因其他原因导致的丢包数、Ring Buffer 溢出导致的丢包数;
- TX-OK、TX-ERR、TX-DRP、TX-OVR,分别表示发送时的总包数、总错误数、进入 Ring Buffer 后因其他原因导致的丢包数、Ring Buffer 溢出导致的丢包数;
- Flg 标志
- B 已经设置了一个广播地址
- L 该接口是一个回送设备
- M 接收所有的数据包(混乱模式)
- N 避免跟踪
- O 在该接口上,禁用ARP
- P 这是一个点到点连接
- R 接口正在运行
- U 接口处于"活动"状态
tc 命令 -- 检查网卡是否配置 tc 规则
命令
tc -s qdisc show dev eno1
结果
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
说明
eno1 上面配置了一个网络模拟排队规则 (qdisc netem),并且配置了丢包率为 30% (loss 30%)
解决
删除 netem 模块
tc qdisc del dev eth0 root netem loss 30%
【2.2】网络层和传输层丢包排查
netstat 命令 -- 协议收发汇总
命令
netstat -s
Ip:
Forwarding: 1
214542146 total packets received
18 with invalid addresses
48 forwarded
0 incoming packets discarded
212587679 incoming packets delivered
36781261 requests sent out
2 outgoing packets dropped
1225 fragments dropped after timeout
1998956 reassemblies required
47570 packets reassembled ok
1711123 packet reassemblies failed
Icmp:
2514 ICMP messages received
37 input ICMP message failed
InCsumErrors: 10
ICMP input histogram:
destination unreachable: 2450
timeout in transit: 21
echo requests: 2
echo replies: 31
5708 ICMP messages sent
0 ICMP messages failed
ICMP output histogram:
destination unreachable: 5661
time exceeded: 14
echo requests: 31
echo replies: 2
IcmpMsg:
InType0: 31
InType3: 2450
InType8: 2
InType11: 21
OutType0: 2
OutType3: 5661
OutType8: 31
OutType11: 14
Tcp:
31920 active connection openings
429 passive connection openings
523 failed connection attempts
1142 connection resets received
12 connections established
39259016 segments received
37353339 segments sent out
58952 segments retransmitted
1219 bad segments received
4328 resets sent
Udp:
173996859 packets received
3395 packets to unknown port received
331 packet receive errors
3861501 packets sent
331 receive buffer errors
0 send buffer errors
IgnoredMulti: 330293
UdpLite:
TcpExt:
6 resets received for embryonic SYN_RECV sockets
2 packets pruned from receive queue because of socket buffer overrun
12 ICMP packets dropped because they were out-of-window
1513 TCP sockets finished time wait in fast timer
18192 delayed acks sent
37 delayed acks further delayed because of locked socket
Quick ack mode was activated 8112 times
15792151 packet headers predicted
371218 acknowledgments not containing data payload received
10607302 predicted acknowledgments
TCPSackRecovery: 698
Detected reordering 63 times using SACK
4 congestion windows fully recovered without slow start
TCPDSACKUndo: 13
1 congestion windows recovered without slow start after partial ack
TCPLostRetransmit: 41764
TCPSackFailures: 1
1034 fast retransmits
TCPTimeouts: 55061
TCPLossProbes: 3347
TCPLossProbeRecovery: 1104
TCPBacklogCoalesce: 26750
TCPDSACKOldSent: 8113
TCPDSACKRecv: 168
361 connections reset due to unexpected data
1017 connections reset due to early user close
448 connections aborted due to timeout
TCPDSACKIgnoredOld: 11
TCPDSACKIgnoredNoUndo: 73
TCPSackShifted: 43
TCPSackMerged: 23
TCPSackShiftFallback: 789
IPReversePathFilter: 14
TCPRcvCoalesce: 8922712
TCPOFOQueue: 18762
TCPChallengeACK: 1222
TCPSYNChallenge: 1222
TCPSpuriousRtxHostQueues: 5
TCPAutoCorking: 151958
TCPFromZeroWindowAdv: 109
TCPToZeroWindowAdv: 109
TCPWantZeroWindowAdv: 276
TCPSynRetrans: 51463
TCPOrigDataSent: 20657582
TCPHystartTrainDetect: 11
TCPHystartTrainCwnd: 234
TCPACKSkippedSeq: 7
TCPKeepAlive: 5876
TCPDelivered: 20677380
TCPAckCompressed: 2975
IpExt:
InMcastPkts: 230863
OutMcastPkts: 20820
InBcastPkts: 515761
OutBcastPkts: 8857
InOctets: 275473275063
OutOctets: 13751580722
InMcastOctets: 53599231
OutMcastOctets: 3798519
InBcastOctets: 139501761
OutBcastOctets: 1488411
InNoECTPkts: 287914633
iptables
连接跟踪数查询
# 主机终端中查询内核配置
$ sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 262144
$ sysctl net.netfilter.nf_conntrack_count
net.netfilter.nf_conntrack_count = 41
查看 iptable 的过滤规则
命令
sudo iptables -t filter -nvL
结果
Chain INPUT (policy ACCEPT 213M packets, 274G bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:67
0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:67
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
48 3972 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
48 3972 DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
24 2460 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
24 1512 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- * virbr0 0.0.0.0/0 192.168.122.0/24 ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- virbr0 * 192.168.122.0/24 0.0.0.0/0
0 0 ACCEPT all -- virbr0 virbr0 0.0.0.0/0 0.0.0.0/0
0 0 REJECT all -- * virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- virbr0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT 37M packets, 14G bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT udp -- * virbr0 0.0.0.0/0 0.0.0.0/0 udp dpt:68
Chain DOCKER (1 references)
pkts bytes target prot opt in out source destination
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
pkts bytes target prot opt in out source destination
24 1512 DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
48 3972 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0
24 1512 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
48 3972 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
解决方案
删除 iptables 的 DROP 规则
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
附录
【1】iptables 知识点补充
【1.1】iptables 概念简介
netfilter/iptables 为 Linux 平台下的包过滤防火墙,可以完成封包过滤、封包重定向、网络地址转换 (NAT) 等功能;
iptables 和 netfilter 的关系
- iptables 是 Linux 防火墙的管理工具,位于 /sbin/iptables;
- netfilter 是 Linux 内核中实现包过滤的内部结构;
iptables 传输数据包的过程
iptables 的规则表和链
- 表 (tables) 提供特定的功能,iptables 内置了 4 个表,即 filter 表、nat 表、mangle 表和 raw 表,分别用于实现包过滤、网络地址转换、包重构 (修改) 和数据跟踪处理;
- 链 (chains) 是数据包传播的路径,每一条链是众多规则中的一个检查清单,每一条链中可以有一 条或数条规则;当一个数据包到达一个链时,iptables 就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件;如果满足,系统就会根据 该条规则所定义的方法处理该数据包;否则 iptables 将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables 就会根据该链预先定义的默认策略来处理数据包;
- 规则表
- 1. filter 表 —— 三个链,INPUT、FORWARD、OUTPUT
- 作用 : 过滤数据包
- 内核模块 : iptables_filter
- 2. Nat 表 —— 三个链,PREROUTING、POSTROUTING、OUTPUT
- 作用 : 用于网络地址转换 (IP、端口)
- 内核模块 : iptable_nat
- 3. Mangle 表 —— 五个链,PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
- 作用 : 修改数据包的服务类型、TTL、并且可以配置路由实现 QoS
- 内核模块 : iptable_mangle
- 4. Raw 表 —— 两个链,OUTPUT、PREROUTING
- 作用 : 决定数据包是否被状态跟踪机制处理
- 内核模块 : iptable_raw
- 规则表之间的优先顺序 : Raw —— mangle —— nat —— filter
- 1. filter 表 —— 三个链,INPUT、FORWARD、OUTPUT
- 规则链
- 1. INPUT —— 进来的数据包应用此规则链中的策略
- 2. OUTPUT —— 外出的数据包应用此规则链中的策略
- 3. FORWARD —— 转发数据包时应用此规则链中的策略
- 4. PREROUTING —— 对数据包作路由选择前应用此链中的规则
- 5. POSTROUTING —— 对数据包作路由选择后应用此链中的规则
- 规则表
【1.2】iptables 命令
命令格式
iptables [-t 表名] 命令选项[链名][条件匹配][-j 目标动作或跳转]
命令选项
- -A 在指定链的末尾添加 (append) 一条新的规则
- -D 删除 (delete) 指定链中的某一条规则,可以按规则序号和内容删除
- -I 在指定链中插入 (insert) 一条新的规则,默认在第一行添加
- -R 修改、替换 (replace) 指定链中的某一条规则,可以按规则序号和内容替换
- -L 列出 (list) 指定链中所有的规则进行查看
- -E 重命名用户定义的链,不改变链本身
- -F 清空 (flush)
- -N 新建 (new-chain) 一条用户自己定义的规则链
- -X 删除指定表中用户自定义的规则链 (delete-chain)
- -P 设置指定链的默认策略 (policy)
- -Z 将所有表的所有链的字节和数据包计数器清零
- -n 使用数字形式 (numeric) 显示输出结果
- -v 查看规则表详细信息 (verbose) 的信息
- -V 查看版本 (version)
- -h 获取帮助 (help)
参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。
【1】极客时间 -- Linux 性能优化实战