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 知识体系总览

下面这张图,把本章的核心知识点串起来了。你可以把它当作配置前的检查清单。

Linux 服务器基础配置知识体系 Linux 服务器基础配置知识体系 内核参数优化 net.core.somaxconn tcp_tw_reuse rmem/wmem tcp_fin_timeout 文件描述符限制 用户级限制 系统级限制 limits.conf fs.file-max 系统资源限制 ulimit 配置 systemd 配置 进程数限制 栈大小限制 配置完成后,务必使用 sysctl -p 和 ulimit -a 验证生效 三个模块相互独立,但缺一不可。建议按「内核参数 → FD 限制 → 资源限制」的顺序配置。 压测前检查:/proc/sys/net/core/somaxconn 和 ulimit -n

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 双重确认。别嫌麻烦,这一步能省掉后面很多排查时间。