Linux性能优化实战笔记(网络篇)
关于 Linux 网络,你必须知道这些
网络模型(TCP/IP)
- 应用层,负责向用户提供一组应用程序,比如 HTTP、FTP、DNS 等
- 传输层,负责端到端的通信,比如 TCP、UDP 等
- 网络层,负责网络包的封装、寻址和路由,比如 IP、ICMP 等
- 网络接口层,负责网络包在物理网络中的传输,比如 MAC 寻址、错误侦测以及通过网卡传输网络帧等。
Linux网络栈
- 传输层在应用程序数据前面增加了 TCP 头
- 网络层在 TCP 数据包前增加了 IP 头
- 网络接口层,又在 IP 数据包前后分别增加了帧头和帧尾
- (网络接口层定义最大传输单元MTU,若网络层包大小超过该值,则网络层要先做分片后往下交付)
- 总体调用栈:应用程序->系统调用->套接字->TCP/UDP->IP->链路层->igb/bnx->网卡
Linux网络收发流程
- 参见下图
性能指标
- 带宽,表示链路的最大传输速率,单位通常为 b/s
- 吞吐量,表示单位时间内成功传输的数据量,单位通常为 b/s(比特 / 秒)或者 B/s(字节 / 秒)
- 延时,表示从网络请求发出后,一直到收到远端响应,所需要的时间延迟
- PPS,是 Packet Per Second(包 / 秒)的缩写,表示以网络包为单位的传输速率
- 其它包括:网络的可用性(网络能否正常通信)、并发连接数(TCP连接数量)、丢包率、重传率
网络配置
- 查看工具:ifconfig、ip
- 命令:ifconfig eth0、ip -s addr show dev eth0
指标介绍
- 网络接口的状态标志。ifconfig 输出中的 RUNNING ,或 ip 输出中的 LOWER_UP ,都表示物理网络是连通的
- MTU 的大小。MTU 默认大小是 1500
- 网络接口的 IP 地址、子网以及 MAC 地址
网络收发的字节数、包数、错误数以及丢包情况
- errors 表示发生错误的数据包数,比如校验错误、帧同步错误等
- dropped 表示丢弃的数据包数,即数据包已经收到了 Ring Buffer,但因为内存不足等原因丢包;
- overruns 表示超限数据包数,即网络 I/O 速度过快,导致 Ring Buffer 中的数据包来不及处理(队列满)而导致的丢包;
- carrier 表示发生 carrirer 错误的数据包数,比如双工模式不匹配、物理电缆出现问题等;
- collisions 表示碰撞数据包数。
套接字信息
- 查看工具:netstat、ss
- 命令:netstat -nlp、ss -ltnp
指标介绍
- 接收队列(Recv-Q)和发送队列(Send-Q),通常应该是 0。若不为0说明有网络包的堆积发生
- syn backlog 是 TCP 协议栈中的半连接队列长度;全连接队列(accept queue)
协议栈统计信息
- 命令:netstat -s、ss -s
网络吞吐&PPS
- 查看工具:sar
- 命令:sar -n DEV 2 10
指标介绍
- rxpck/s 和 txpck/s 分别是接收和发送的 PPS,单位为包 / 秒
- rxkB/s 和 txkB/s 分别是接收和发送的吞吐量,单位是 KB/ 秒
- rxcmp/s 和 txcmp/s 分别是接收和发送的压缩数据包数,单位是包 / 秒
连通性&延迟
- 查看工具:ping
C10K 和 C1000K 回顾
定义
- C表示Client的意思,C10K就是单机支持1w的请求;C1000K即单机支持100w请求。
I/O模型优化
I/O事件通知方式
- 水平触发:只要文件描述符可以非阻塞地执行 I/O ,就会触发通知。也就是说,应用程序可以随时检查文件描述符的状态,然后再根据状态,进行 I/O 操作
- 边缘触发:只有在文件描述符的状态发生改变(也就是 I/O 请求达到)时,才发送一次通知。这时候,应用程序需要尽可能多地执行 I/O,直到无法继续读写,才可以停止。
使用非阻塞 I/O 和水平触发通知(select和poll)
- 实现方式:每个线程同时监控一批套接字的文件描述符,轮询遍历出哪些可以执行I/O,再执行真正的网络读写
- 缺点:轮询耗时、select还有文件描述符数量限制、每次调用都涉及用户态和内核态的两次切换
使用非阻塞 I/O 和边缘触发通知,比如 epoll
实现方式
- epoll 使用红黑树,在内核中管理文件描述符的集合,这样就不需要应用程序在每次操作时都传入、传出这个集合
- epoll 使用事件驱动的机制,只关注有 I/O 事件发生的文件描述符,不需要轮询扫描整个集合
使用异步 I/O(Asynchronous I/O,简称为 AIO)
- 实现方式:异步 I/O 允许应用程序同时发起很多 I/O 操作,而不用等待这些操作完成。而在 I/O 完成后,系统会用事件通知(比如信号或者回调函数)的方式,告诉应用程序
工作模型优化
主进程 + 多个 worker 子进程
实现方式
- 主进程执行 bind() + listen() 后,创建多个子进程
- 在每个子进程中,都通过 accept() 或 epoll_wait() ,来处理相同的套接字
惊群问题
- 定义:当网络 I/O 事件发生时,多个进程被同时唤醒,但实际上只有一个进程来响应这个事件,其他被唤醒的进程都会重新休眠
- 解决方法:在每个 worker 进程中,都增加一个了全局锁(accept_mutex)。这些 worker 进程需要首先竞争到锁,只有竞争到锁的进程,才会加入到 epoll 中,这样就确保只有一个 worker 子进程被唤醒
监听到相同端口的多进程模型
实现方式
- 所有的进程都监听相同的接口,并且开启 SO_REUSEPORT 选项,由内核负责将请求负载均衡到这些监听进程中去
支撑C1000K的优化措施
实现方式
- 跳过内核协议栈的冗长路径,把网络包直接送到要处理的应用程序那里去(DPDK 和 XDP)
DPDK
- 定义:用户态网络的标准,它跳过内核协议栈,直接由用户态进程通过轮询的方式,来处理网络接收。
XDP
- 定义:Linux 内核提供的一种高性能网络数据路径。它允许网络包,在进入内核协议栈之前,就进行处理,也可以带来更高的性能
【案例】怎么评估系统的网络性能
- Linux网络基于TCP/IP协议栈,因此协议栈每层都可以评估分析其性能
各协议层性能测试
网络接口层&网络层(转发能力)
- 测试工具:pktgen、hping3
使用命令
- modprobe pktgen
- ps -ef | grep pktgen | grep -v grep
- ls /proc/net/pktgen/
TCP/UDP
- 测试工具:iperf3
使用方式
在服务端执行:iperf3 -s -i 1 -p 8888
- (-s表示启动服务端,-i表示汇报间隔,-p表示监听端口)
在客户端执行:iperf3 -c 192.168.0.30 -b 1G -t 15 -P 2 -p 10000
- (-c表示启动客户端,192.168.0.30为目标服务器的IP,-b表示目标带宽,-t表示测试时间,-P表示并发数,-p表示目标服务器监听端口)
结果指标
- SUM 行就是测试的汇总结果,包括测试时间、数据传输量以及带宽等
- 按照发送和接收,这一部分又分为了 sender 和 receiver 两行
HTTP
- 测试工具:ab
使用方式
- 安装命令:yum install -y httpd-tools
执行命令:ab -c 1000 -n 10000 http://192.168.0.30/
- (-c表示并发请求数为1000,-n表示总的请求数为10000)
结果指标
- 测试结果分为三个部分,分别是请求汇总、连接时间汇总还有请求延迟汇总
应用负载
- 测试工具:wrk
使用方式
安装命令
- git clone https://github.com/wg/wrk.git
- cd wrk
- apt-get install build-essential -y
- make
- sudo cp wrk /usr/local/bin/
执行命令:wrk -c 1000 -t 2 http://192.168.0.30/
- (-c表示并发连接数1000,-t表示线程数为2)
【案例】DNS 解析时快时慢,我该怎么办
域名与DNS解析
- 查看DNS服务器:cat /etc/resolv.conf
DNS记录类型
- A 记录,用来把域名转换成 IP 地址
- CNAME 记录,用来创建别名
- NS 记录,表示该域名对应的域名服务器地址
查询域名IP与使用的DNS服务器
- 使用工具:nslookup
- 执行命令:nslookup www.baidu.com
- 返回结果:使用的域名服务器及端口信息、域名的非权威查询结果
DNS查询链路
- 使用工具:dig
执行命令:dig +trace +nodnssec www.baidu.com
- (+trace表示开启跟踪查询,+nodnssec表示禁止DNS安全扩展)
- 返回结果:DNS解析过程中,各级DNS服务器的信息与查询耗时
- (上述两个工具的安装:yum install -y bind-utils)
本地DNS解析
- 执行命令:cat /etc/hosts
DNS解析失败案例分析
- 执行命令:nslookup www.baidu.com,返回connection timed out; no servers could be reached
- 但直接ping IP地址是通的,说明服务器本身没问题
- 再次执行命令:nslookup -debug www.baidu.com,开启debug模式,发现提示127.0.0.1#53(127.0.0.1)连接失败,说明是本地访问DNS服务器有问题
- 执行命令:cat /etc/resolv.conf,发现没有输出,说明是本地没有配置DNS服务器
DNS解析不稳定案例分析
- 执行命令:time nslookup www.baidu.com,发现耗时非常长,且有时候直接超时
怀疑可能的问题有
- DNS 服务器本身有问题,响应慢并且不稳定
- 客户端到 DNS 服务器的网络延迟比较大
- DNS 请求或者响应包,在某些情况下被链路中的网络设备弄丢了
- 直接ping DNS服务器,发现耗时确实比较长,且有丢包情况
- 更换DNS服务器后情况好转,或者可以开启DNS缓存:/etc/init.d/dnsmasq start
DNS优化方法
- 对 DNS 解析的结果进行缓存
- 对 DNS 解析的结果进行预取(这是浏览器等 Web 应用中最常用的方法,预取域名的DNS解析结果)
- 使用 HTTPDNS 取代常规的 DNS 解析
- 基于 DNS 的全局负载均衡(GSLB)
【案例】使用 tcpdump 和 Wireshark 分析网络流量
tcpdump
- 仅支持命令行格式使用,常用在服务器中抓取和分析网络包
使用范例:tcpdump -nn udp port 53 or host 35.190.27.188
- -nn ,表示不解析抓包中的域名(即不反向解析)、协议以及端口号
- udp port 53 ,表示只显示 UDP 协议的端口号(包括源端口和目的端口)为 53 的包
- host 35.190.27.188 ,表示只显示 IP 地址(包括源地址和目的地址)为 35.190.27.188 的包
- 这两个过滤条件中间的“ or ”,表示或的关系,也就是说,只要满足上面两个条件中的任一个,就可以展示出来
wireshark
- 除了可以抓包外,还提供了强大的图形界面和汇总分析工具,在分析复杂的网络情景时,尤为简单和实用
可以先使用tcpdump抓包并将结果输出,然后用wireshark分析
- 输出命令:tcpdump -nn udp port 53 or host 35.190.27.188 -w ping.pcap
【案例】怎么缓解 DDoS 攻击带来的性能下降问题
DDoS
- DDoS 的前身是 DoS(Denail of Service),即拒绝服务攻击,指利用大量的合理请求,来占用过多的目标资源,从而使目标服务无法响应正常请求。
- DDoS(Distributed Denial of Service) 则是在 DoS 的基础上,采用了分布式架构,利用多台主机同时攻击目标主机。
攻击类型
- 耗尽带宽
- 耗尽操作系统的资源
- 消耗应用程序的运行资源
排查经过
- 客户端curl页面发现响应非常慢
服务端通过sar命令,查看网络情况
- 执行命令:sar -n DEV 1
- 结果发现rxpck/s非常大,而txpck/s则相对较小。说明服务端收到大量的小包请求
通过tcpdump抓包排查是什么小包
- 执行命令:tcpdump -i eth0 -n tcp port 80
- 结果发现大量数据包是Flags [S],表示这是一个 SYN 包。大量的 SYN 包表明这是 SYN Flood 攻击
- SYN Flood的原理,是通过大量TCP的半开连接状态,从而无法建立新的 TCP 连接
查看服务端TCP半开连接
- 执行命令:netstat -n -p | grep SYN_REC
- 结果发现大量相同的IP占用TCP连接
防止SYN Flood攻击手段
禁止某个指定IP的连接
- 执行命令:iptables -I INPUT -s 192.168.0.2 -p tcp -j REJECT
限制syn并发数为每秒1次
- 执行命令:iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT
限制单个IP在60秒新建立的连接数为10
- 执行命令:iptables -I INPUT -p tcp --dport 80 --syn -m recent --name SYN_FLOOD --update --seconds 60 --hitcount 10 -j REJECT
增大半连接的最大数量
- 执行命令:sysctl -w net.ipv4.tcp_max_syn_backlog=1024
设置SYN_RECV失败时的重试次数
- 执行命令:sysctl -w net.ipv4.tcp_synack_retries=1
使用TCP SYN Cookies
- TCP SYN Cookies 也是一种专门防御 SYN Flood 攻击的方法。SYN Cookies 基于连接信息(包括源地址、源端口、目的地址、目的端口等)以及一个加密种子(如系统启动时间),计算出一个哈希值(SHA1),这个哈希值称为 cookie