3. Linux 服务器基础配置:内核参数优化与资源限制
吞吐测试的环境搭建,说白了就是给被测系统「铺路」。路铺得不好,车再好也跑不快。我个人习惯,拿到一台新服务器,第一件事不是装软件,而是先看内核参数和资源限制。这些底层的配置,往往决定了压测能跑到什么量级。
我记得有一次帮客户做性能调优,压测机配置很高,但吞吐死活上不去。查了半天,发现是 net.core.somaxconn 默认只有 128。高并发下连接队列直接满了,请求全被丢掉。嗯,这种坑,踩过一次就记住了。
核心观点:内核参数和资源限制是吞吐测试的「地基」。地基不稳,上层再优化也是白搭。
3.1 内核参数优化:让网络栈跑得更快
Linux 内核的网络栈有很多可调参数。我挑几个跟吞吐测试关系最密切的来讲。
3.1.1 net.core.somaxconn
这个参数控制的是「TCP 全连接队列」的最大长度。说白了,就是服务端还没调用 accept() 时,内核能帮你暂存多少个已完成三次握手的连接。
默认值通常是 128。对于高并发场景,这远远不够。我曾经压过一个 Web 服务,QPS 刚过 2000 就开始丢连接,一看 ss -lnt 的 Send-Q 列,队列满了。调大 somaxconn 后,问题立刻解决。
我的建议:对于吞吐测试场景,建议设置为 1024 或 4096。如果应用层也有限制(比如 Nginx 的 backlog),记得两边一起调。
# 临时生效
sysctl -w net.core.somaxconn=4096
# 永久生效(写入 /etc/sysctl.conf)
echo "net.core.somaxconn = 4096" >> /etc/sysctl.conf
sysctl -p
3.1.2 net.ipv4.tcp_tw_reuse 与 tcp_tw_recycle
这两个参数跟 TIME_WAIT 状态有关。高并发下,客户端主动关闭连接会产生大量 TIME_WAIT,占用端口资源。
tcp_tw_reuse 允许内核重用 TIME_WAIT 状态的连接。我个人习惯开启它,尤其是压测客户端。
tcp_tw_recycle 更激进,但要注意:从 Linux 4.12 开始,这个参数已经被移除了。而且它在 NAT 环境下有严重问题,会导致连接异常。我曾经在线上环境吃过这个亏,后来再也不敢开了。
避坑指南:千万不要在生产环境开启 tcp_tw_recycle。如果你用的是较新内核,这个参数已经不存在了,不用纠结。
# 推荐配置
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
3.1.3 net.core.rmem_max 与 net.core.wmem_max
这两个参数控制内核 socket 接收和发送缓冲区的最大值。对于大流量场景,默认值太小会导致吞吐上不去。
我一般会配合 net.ipv4.tcp_rmem 和 net.ipv4.tcp_wmem 一起调。这三个参数共同决定了 TCP 连接的读写缓冲区大小。
| 参数 | 默认值 | 推荐值(压测场景) | 说明 |
|---|---|---|---|
| net.core.rmem_max | 212992 | 16777216 | 接收缓冲区最大值(16MB) |
| net.core.wmem_max | 212992 | 16777216 | 发送缓冲区最大值(16MB) |
| net.ipv4.tcp_rmem | 4096 87380 6291456 | 4096 87380 16777216 | TCP 接收缓冲区(min default max) |
| net.ipv4.tcp_wmem | 4096 16384 4194304 | 4096 16384 16777216 | TCP 发送缓冲区(min default max) |
3.2 文件描述符限制:别让系统「没手」干活
在 Linux 里,一切皆文件。socket 连接、打开的文件、管道……都占用文件描述符(FD)。默认情况下,单个进程能打开的 FD 数量是 1024。对于吞吐测试,这个值太小了。
你想想看,压测工具要建立几千甚至几万个并发连接,每个连接就是一个 FD。如果 FD 不够,系统会直接报 Too many open files 错误。
3.2.1 用户级限制
修改 /etc/security/limits.conf,对指定用户放开限制。
# 对 testuser 用户放开限制
testuser soft nofile 65535
testuser hard nofile 65535
# 对所有用户放开限制
* soft nofile 65535
* hard nofile 65535
这里要注意,soft 是软限制,hard 是硬限制。普通用户只能把软限制调到硬限制以内。我习惯把两个都设成一样,省得后面出问题。
3.2.2 系统级限制
除了用户级,系统还有一个全局的 FD 上限,由 fs.file-max 控制。
# 查看当前系统级 FD 上限
cat /proc/sys/fs/file-max
# 临时修改
sysctl -w fs.file-max=1000000
# 永久修改
echo "fs.file-max = 1000000" >> /etc/sysctl.conf
sysctl -p
我的经验:系统级 FD 上限一般设成 100 万就够用了。如果压测机内存很大(比如 128GB),可以设到 200 万。但别设太大,每个 FD 会占用内核内存。
3.3 系统资源限制配置:别让 ulimit 卡住你
ulimit 命令是查看和设置当前 shell 会话资源限制的工具。很多新手改了 limits.conf 后,发现新开的 shell 还是 1024,就是因为没重新登录。
3.3.1 常用 ulimit 参数
| 参数 | 含义 | 推荐值 |
|---|---|---|
| -n | 最大打开文件数 | 65535 |
| -u | 最大用户进程数 | 65535 |
| -s | 栈大小 | 8192(KB) |
| -c | core 文件大小 | 0(压测时建议关闭) |
3.3.2 验证配置是否生效
改完配置后,一定要验证。我见过太多人改了文件,但没生效,结果排查半天。
# 查看当前用户限制
ulimit -a
# 查看进程实际限制(PID 替换为实际进程号)
cat /proc/<PID>/limits
避坑指南:如果你用 systemd 启动压测工具,limits.conf 可能不生效。需要在 service 文件里单独设置 LimitNOFILE=65535。我曾经因为这个坑,浪费了一整个下午。
3.4 知识体系总览
下面这张图,把本章的核心知识点串起来了。你可以把它当作配置前的检查清单。
3.5 一键配置脚本
最后,我分享一个我常用的初始化脚本。你可以根据实际环境调整。
#!/bin/bash
# Linux 服务器吞吐测试初始化脚本
# 内核参数优化
cat >> /etc/sysctl.conf << EOF
net.core.somaxconn = 4096
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 16384 16777216
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
fs.file-max = 1000000
EOF
sysctl -p
# 用户级 FD 限制
cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
EOF
echo "配置完成,请重新登录使 limits.conf 生效"
我的习惯:每次配置完,我都会用 sysctl -a | grep net.core 和 ulimit -n 双重确认。别嫌麻烦,这一步能省掉后面很多排查时间。