一、上节回顾

上一节,我们了解了 NAT(网络地址转换)的原理,学会了如何排查 NAT 带来的性能问题,最后还总结了 NAT 性能优化的基本思路。我先带你简单回顾一下。

NAT 基于 Linux 内核的连接跟踪机制,实现了 IP 地址及端口号重写的功能,主要被用来解决公网 IP 地址短缺的问题。

在分析 NAT 性能问题时,可以先从内核连接跟踪模块 conntrack 角度来分析,比如用systemtap、perf、netstat 等工具,以及 proc 文件系统中的内核选项,来分析网络协议
栈的行为;然后,通过内核选项调优、切换到无状态 NAT、使用 DPDK 等方式,进行实际优化。

通过前面的学习,你应该已经体会到,网络问题比我们前面学过的 CPU、内存或磁盘 I/O都要复杂。无论是应用层的各种 I/O 模型,冗长的网络协议栈和众多的内核选项,抑或是
各种复杂的网络环境,都提高了网络的复杂性。

不过,也不要过分担心,只要你掌握了 Linux 网络的基本原理和常见网络协议的工作流程,再结合各个网络层的性能指标来分析,你会发现,定位网络瓶颈并不难。

找到网络性能瓶颈后,下一步要做的就是优化了,也就是如何降低网络延迟,并提高网络的吞吐量。学完相关原理和案例后,我就来讲讲,优化网络性能问题的思路和一些注意事项。

由于网络优化思路的内容比较多,我们分两节来学习,今天我们先来看上篇。

二、确定优化目标

跟 CPU 和 I/O 方面的性能优化一样,优化前,我会先问问自己,网络性能优化的目标是什么?换句话说,我们观察到的网络性能指标,要达到多少才合适呢?

实际上,虽然网络性能优化的整体目标,是降低网络延迟(如 RTT)和提高吞吐量(如BPS 和 PPS),但具体到不同应用中,每个指标的优化标准可能会不同,优先级顺序也大相径庭。

就拿上一节提到的 NAT 网关来说,由于其直接影响整个数据中心的网络出入性能,所以NAT 网关通常需要达到或接近线性转发,也就是说, PPS 是最主要的性能目标。

再如,对于数据库、缓存等系统,快速完成网络收发,即低延迟,是主要的性能目标。而对于我们经常访问的 Web 服务来说,则需要同时兼顾吞吐量和延迟。

所以,为了更客观合理地评估优化效果,我们首先应该明确优化的标准,即要对系统和应用程序进行基准测试,得到网络协议栈各层的基准性能。

在 怎么评估系统的网络性能 中,我已经介绍过,网络性能测试的方法。简单回顾一下,Linux 网络协议栈,是我们需要掌握的核心原理。它是基于 TCP/IP 协议族的分层结构,我
用一张图来表示这个结构。

明白了这一点,在进行基准测试时,我们就可以按照协议栈的每一层来测试。由于底层是其上方各层的基础,底层性能也就决定了高层性能。所以我们要清楚,底层性能指标,其
实就是对应高层的极限性能。我们从下到上来理解这一点。

首先是网络接口层和网络层,它们主要负责网络包的封装、寻址、路由,以及发送和接收。每秒可处理的网络包数 PPS,就是它们最重要的性能指标(特别是在小包的情况
下)。你可以用内核自带的发包工具 pktgen ,来测试 PPS 的性能

再向上到传输层的 TCP 和 UDP,它们主要负责网络传输。对它们而言,吞吐量(BPS)、连接数以及延迟,就是最重要的性能指标。你可以用 iperf 或 netperf ,来测试传输层的性能。

不过要注意,网络包的大小,会直接影响这些指标的值。所以,通常,你需要测试一系列不同大小网络包的性能。

最后,再往上到了应用层,最需要关注的是吞吐量(BPS)、每秒请求数以及延迟等指标。你可以用 wrk、ab 等工具,来测试应用程序的性能。

不过,这里要注意的是,测试场景要尽量模拟生产环境,这样的测试才更有价值。比如,你可以到生产环境中,录制实际的请求情况,再到测试中回放。

总之,根据这些基准指标,再结合已经观察到的性能瓶颈,我们就可以明确性能优化的目标。

三、网络性能工具

同前面学习一样,我建议从指标和工具两个不同维度出发,整理记忆网络相关的性能工具。

第一个维度,从网络性能指标出发,你更容易把性能工具同系统工作原理关联起来,对性能问题有宏观的认识和把握。这样,当你想查看某个性能指标时,就能清楚知道,可以用
哪些工具。

这里,我把提供网络性能指标的工具,做成了一个表格,方便你梳理关系和理解记忆。你可以把它保存并打印出来,随时查看。当然,你也可以把它当成一个“指标工具”指南来使用。

再来看第二个维度,从性能工具出发。这可以让你更快上手使用工具,迅速找出想要观察的性能指标。特别是在工具有限的情况下,我们更要充分利用好手头的每一个工具,用少
量工具也要尽力挖掘出大量信息。

同样的,我也将这些常用工具,汇总成了一个表格,方便你区分和理解。自然,你也可以当成一个“工具指标”指南使用,需要时查表即可。

四、网络性能优化

总的来说,先要获得网络基准测试报告,然后通过相关性能工具,定位出网络性能瓶颈。再接下来的优化工作,就是水到渠成的事情了。

当然,还是那句话,要优化网络性能,肯定离不开 Linux 系统的网络协议栈和网络收发流程的辅助。你可以结合下面这张图再回忆一下这部分的知识。

接下来,我们就可以从应用程序、套接字、传输层、网络层以及链路层等几个角度,分别来看网络性能优化的基本思路

五、应用程序

应用程序,通常通过套接字接口进行网络操作。由于网络收发通常比较耗时,所以应用程序的优化,主要就是对网络 I/O 和进程自身的工作模型的优化。

相关内容,其实我们在 C10K 和 C1000K 回顾 的文章中已经学过了。这里我们简单回顾一下。

1、从网络 I/O 的角度来说,主要有下面两种优化思路。

第一种是最常用的 I/O 多路复用技术 epoll,主要用来取代 select 和 poll。这其实是解决C10K 问题的关键,也是目前很多网络应用默认使用的机制。

第二种是使用异步 I/O(Asynchronous I/O,AIO)。AIO 允许应用程序同时发起很多I/O 操作,而不用等待这些操作完成。等到 I/O 完成后,系统会用事件通知的方式,告诉
应用程序结果。不过,AIO 的使用比较复杂,你需要小心处理很多边缘情况。

2、而从进程的工作模型来说,也有两种不同的模型用来优化。

第一种,主进程 + 多个 worker 子进程。其中,主进程负责管理网络连接,而子进程负责实际的业务处理。这也是最常用的一种模型。

第二种,监听到相同端口的多进程模型。在这种模型下,所有进程都会监听相同接口,并且开启 SO_REUSEPORT 选项,由内核负责,把请求负载均衡到这些监听进程中去。
除了网络 I/O 和进程的工作模型外,应用层的网络协议优化,也是至关重要的一点。我总结了常见的几种优化方法。

  1. 使用长连接取代短连接,可以显著降低 TCP 建立连接的成本。在每秒请求次数较多时,这样做的效果非常明显。
  2. 使用内存等方式,来缓存不常变化的数据,可以降低网络 I/O 次数,同时加快应用程序的响应速度。
  3. 使用 Protocol Buffer 等序列化的方式,压缩网络 I/O 的数据量,可以提高应用程序的吞吐。
  4. 使用 DNS 缓存、预取、HTTPDNS 等方式,减少 DNS 解析的延迟,也可以提升网络I/O 的整体速度。

六、套接字

套接字可以屏蔽掉 Linux 内核中不同协议的差异,为应用程序提供统一的访问接口。每个套接字,都有一个读写缓冲区。

  • 读缓冲区,缓存了远端发过来的数据。如果读缓冲区已满,就不能再接收新的数据。
  • 写缓冲区,缓存了要发出去的数据。如果写缓冲区已满,应用程序的写操作就会被阻塞。

所以,为了提高网络的吞吐量,你通常需要调整这些缓冲区的大小。比如:

增大每个套接字的缓冲区大小 net.core.optmem_max;
增大套接字接收缓冲区大小 net.core.rmem_max 和发送缓冲区大小net.core.wmem_max;
增大 TCP 接收缓冲区大小 net.ipv4.tcp_rmem 和发送缓冲区大小net.ipv4.tcp_wmem。

至于套接字的内核选项,我把它们整理成了一个表格,方便你在需要时参考:

不过有几点需要你注意。

  • tcp_rmem 和 tcp_wmem 的三个数值分别是 min,default,max,系统会根据这些设置,自动调整 TCP 接收 / 发送缓冲区的大小。
  • udp_mem 的三个数值分别是 min,pressure,max,系统会根据这些设置,自动调整UDP 发送缓冲区的大小。

当然,表格中的数值只提供参考价值,具体应该设置多少,还需要你根据实际的网络状况来确定。比如,发送缓冲区大小,理想数值是吞吐量 * 延迟,这样才可以达到最大网络利用率。

除此之外,套接字接口还提供了一些配置选项,用来修改网络连接的行为。

  • 为 TCP 连接设置 TCP_NODELAY 后,就可以禁用 Nagle 算法;
  • 为 TCP 连接开启 TCP_CORK 后,可以让小包聚合成大包后再发送(注意会阻塞小包的发送);
  • 使用 SO_SNDBUF 和 SO_RCVBUF ,可以分别调整套接字发送缓冲区和接收缓冲区的大小。

七、小结

今天,我们一起梳理了常见的 Linux 网络性能优化方法

在优化网络性能时,你可以结合 Linux 系统的网络协议栈和网络收发流程,然后从应用程序、套接字、传输层、网络层再到链路层等,进行逐层优化。

当然,其实我们分析、定位网络瓶颈,也是基于这些进行的。定位出性能瓶颈后,就可以根据瓶颈所在的协议层进行优化。比如,今天我们学了应用程序和套接字的优化思路:

在应用程序中,主要优化 I/O 模型、工作模型以及应用层的网络协议;
在套接字层中,主要优化套接字的缓冲区大小。

而其他各个网络层的优化方法,建议你先自己想一想,下一节,我们再来一起总结。

Linux性能优化实战学习笔记:第四十三讲的更多相关文章

  1. Linux性能优化实战学习笔记:第二十三讲

    一.索引节点和目录 1.索引节点 2.目录项 3.关系 为了帮助你理解目录项.索引节点以及文件数据的关系,我画了一张示意图,你可以对照这张图,来回忆刚刚讲过的内容,把只知识和细节串联起来 4.Slab ...

  2. Linux性能优化实战学习笔记:第十三讲

    问题1:性能工具版本太低,导致指标不全 解决方案1: 这是使用 CentOS 的同学普遍碰到的问题.在文章中,我的pidstat 输出里有一个 %wait 指标,代表进程等待 CPU 的时间百分比, ...

  3. Linux性能优化实战学习笔记:第十八讲

    一.内存的分配和回收 1.管理内存的过程中,也很容易发生各种各样的“事故”, 对应用程序来说,动态内存的分配和回收,是既核心又复杂的一的一个逻辑功能模块.管理内存的过程中,也很容易发生各种各样的“事故 ...

  4. Linux性能优化实战学习笔记:第十二讲

    一.性能优化方法论 不可中断进程案例 二.怎么评估性能优化的效果? 1.评估思路 2.几个为什么 1.为什么要选择不同维度的指标? 应用程序和系统资源是相辅相成的关系 2.性能优化的最终目的和结果? ...

  5. Linux性能优化实战学习笔记:第二十四讲

    一.磁盘 1.机械磁盘 2.固态磁盘 3.相同磁盘随机I/O比连续I/O慢很多 4.最小单位 5.接口 6.RAID陈列卡 7.网路存储 二.通用块层 1.概念 2.第一功能 3.第二功能 4.I/O ...

  6. Linux性能优化实战学习笔记:第十六讲

    一.free数据的来源 1.碰到看不明白的指标时该怎么办吗? 不懂就去查手册.用 man 命令查询 free 的文档.就可以找到对应指标的详细说明.比如,我们执行 man fre... 2.free数 ...

  7. Linux性能优化实战学习笔记:第十讲

    一.坏境准备 1.拓扑图 2.安装包 在第9节的基础上 在VM2上安装hping3依奈包 wget http://www.tcpdump.org/release/libpcap-1.9.0.tar.g ...

  8. Linux性能优化实战学习笔记:第十五讲

    一.内存映射 内存管理也是操作系统最核心的功能之一,内存主要用来存储系统和应用程序的指令.数据.缓存等 1.我们通说的内存指的是物理内存还是虚拟内存? 我们通常说的内存容量,其实这指的是物理内存,物理 ...

  9. Linux性能优化实战学习笔记:第二十八讲

    一.案例环境描述 1.环境准备 2CPU,4GB内存 预先安装docker sysstat工具 apt install docker.io sysstat nake git 案例总共由三个容器组成: ...

  10. Linux性能优化实战学习笔记:第二十六讲

    一.案例环境描述 1.环境准备 2CPU,4GB内存 预先安装docker sysstat工具 2.温馨提示 案例中 Python 应用的核心逻辑比较简单,你可能一眼就能看出问题,但实际生产环境中的源 ...

随机推荐

  1. win7 64bit安装redis

    win7 64bit安装redis 1 先安装redis客户端 1.下载Redis的压缩包 https://github.com/dmajkic/redis/downloads 我下载的是redis- ...

  2. 移动端BUG

    1.解决 Android 系统 设置line-height和height相同,文字却偏上显示(pc端和ios都显示ok) 行高设置为 normal 则可以解决. 然后高度通过padding填充 lin ...

  3. redis的3种过期键删除策略

    Redis的过期键的过期时间都保存在过期字典中,过期键的删除策略有三种,分别是定时删除.惰性删除和定期删除. 定时删除 定时删除策略,是指在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时 ...

  4. MySQL for OPS 04:存储引擎

    写在前面的话 在使用 Linux 的时候,可以经常听到有关文件系统 FS(File System)的东西,MySQL 也有属于自己类似的东西,那就是存储引擎.之前在创建数据表的时候,在 Create ...

  5. QT+OpenGL(03)--libpng库的编译

    1.zlib库的下载 http://www.zlib.net/ zlib1211.zip 2.libpng库的下载 https://libpng.sourceforge.io/index.html l ...

  6. WebApi接口安全性 接口权限调用、参数防篡改防止恶意调用

    背景介绍 最近使用WebApi开发一套对外接口,主要是数据的外送以及结果回传,接口没什么难度,采用WebApi+EF的架构简单创建一个模板工程,使用template生成一套WebApi接口,去掉put ...

  7. mvc5 源码解析1:UrlRoutingModule

    注册在C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG \webconfig中 在该module源码中 我们可以看出注册了application ...

  8. 基于OpenCV.Net连通域分析进行文本块分割

    上一次通过投影的方式进行了文本块分割,(见 https://www.cnblogs.com/BoyTNT/p/11812323.html )但这种方法有很大的局限性,要求分行清晰.不能有字符跨多行.不 ...

  9. 十三道Python练习题

    一.完美立方 编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a^3= b^3 + c^3 + d^3,其中a,b,c,d 大于 1, 小于等于N. 输入 ...

  10. python3测试网站网速

    一.运行环境 1.Windows 10 2.python 3.8 二.安装第三方库pycurl 1.先安装 pip install wheel 2.在安装pycurl https://download ...