Linux 性能分析总结之网络(六)
0x00 前言
在上篇学习笔记中我总结了 I/O 学习笔记,本篇会总结 Linux 网络的性能优化学习笔记。在上篇文章中我们提到了说磁盘 I/O 就是计算机的最终数据持久化的地方,如下图在冯诺依曼架构中也就是对应输入输出的设备,而存储器则就是内存。
在单台计算机的时候,可以说计算过程就是先从输入设备获取指令和数据,在经过运算器的处理后,最终将运算结果输出到输出设备上,而 I/O 的产生则是在和输入和输出设备打交道了。如果是多台计算机,计算机之间如何互相沟通呢?那么就需要通过网络来连接各个计算机了。
在计算机之间的沟通,无非也就是指令和数据就是这两种。比如我访问一个 Web 网站,本质上不就是从网站服务器上获取数据吗?又比如在分布式的计算集群中,master 节点向 slave 节点下发计算任务,这就输出指令呀。是不是感觉网络和磁盘 I/O 很相似?没错,他们在冯诺依曼结果中都是作为输入输出设备,所以他们有很多相似之处,比如在 Linux 系统中,网络 I/O 的操作和文件操作很相似,但网络的层次比文件系统 I/O 更多,所以会更加复杂,一篇文章无法概述,本笔记只是记录一些要点。
0x01 网络基础
0x0100 收发流程
网络和文件系统一样,为了解耦异构设备,都是分层的,分层在网络中主要分为 OSI 和 TCP/IP 模型。如下所示
而自然和磁盘一样,Linux 内核在处理网络包的时候对不同的层会进行不同的处理。
- 应用层: 内核态系统调用,通过 socket 来发包
- 传输层: 对应用层的包进行封装,是五元组的抽象
- IP层: IP 报文发送,路由
- 链路层: 封帧,mac 寻址
- 网卡驱动: 收发包,网卡驱动收发包会通过硬中断和内核交互
0x0101 收包
- 网卡 DMA(可以理解为直接读 I/O 到内存,减少 cpu 的介入) 把收到的网络帧放到收包队列(在内存中),硬中断通知中断程序处理
- 中断程序分配一个叫 sk_buff 的 socket buffer数据结构,拷贝网络帧到这个结构,然后软中断通知内核来处理网络帧了
- 内核获得网络帧后,就跟剥洋葱一样,一层层的剥开
- 数据链路层:检查报文,去掉帧头帧尾,看 ip 层是什么报文,如果是 6 就交给上层 ipv6 对应的协议处理,如果是 4 就交给 4
- IP层: 判断网络包走向,是转发还是交给上层处理。比如 iptable 中的 forward 链就是转发链,如果要交给上层则确定上层协议是 tcp/udp 等,并去掉头尾
- 传输层:根据 tcp/udp 头,根据四元组找到对应的 socket,然后把数据拷贝到 socket 里
- 应用层:操作 socket 读取数据
0x0102 发包
- 应用层:通过系统调用,把数据包写到 socket 里
- 传输层:增加 tcp 头
- ip 层:增加 ip 头,路由寻址,找到下一跳,根据 MTU 分片
- 数据链路层:根据 mac 地址寻址,找到下一跳的 mac,增加头尾,放到发包队列,软中断通知中断程序驱动
- 物理层:驱动程序 DMA 读取网络帧,通过物理网卡通过脉冲信号或光信号发包
0x0110 性能指标
- 带宽: 最大传输速率
- 吞吐量: 单位时间内传输数据量
- 延时: 发出请求到收到响应的时间
- PPS: Packet Per Second,每秒发包量
- 网络可用性
- 并发数
- 丢包率
- 重传率
0x02 网络 I/O 原理
I/O通知方式:
- 水平触发: 应用程序 可以随时读fd
- 边缘触发: 只能在 fd 发生变化是才可以读
I/O 多路复用:
- 非阻塞 I/O 水平触发:
- select: fd 数量有限制,轮询检查 fd。O(n)
- poll: 无 fd 限制,轮询检查fd。O(n)
- 非阻塞 I/O边缘触发:
- epoll: 内核红黑树管理 fd,事件驱动
- 异步 I/O:异步通知,通过信号或者回调
工作模型:
- 主进程 + 多个 workder 子进程:nginx
- 主 bind + listen 初始化 socket
- 子 accept + epoll_wait 都绑定这个 socket
- 有惊群问题,需要锁机制来确保只有一个 worker 节点唤醒
- 多进程监听同个端口,需要开启端口重用,等于是内核将该端口的请求分发到不同的 worker 进程上
高性能网络模型:
- DPDK:跳过内核网络协议栈,直接用户态轮询
- XDP:在内核网络协议栈前处理网络包
0x03 网络优化方式
网络也是分层的,不同的层有不同的优化手段
- 应用层:
- 优化 I/O 模型
- 长连接
- DNS 缓存
- socket: 调整内核参数
- 传输层: 优化传输层协议
- 网络层:路由等
- 链路层:收发包
基本上就是:
- 先查看一波网络性能指标: sar,ip,ss 等工具
- tcpdump,wireshark抓包,分析异常网络流量情况
- 调整对应内核参数,基本上可以解决 80% 的问题
0x04 总结
虽然我是计算机网络专业毕业,但是想一篇文章写完所有的优化点还是太难了,毕竟计算机网络是一门单独的学科,只能把简单地把网络原理和优化思路记录下,在实际使用的时候还是要根据具体的情况来排查问题,另外有很多细节我比较熟悉,觉得太简单了就不一一记录了。