找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4240

积分

0

好友

581

主题
发表于 2 小时前 | 查看: 1| 回复: 0

性能调优图标

适用场景 & 前置条件

项目 要求
适用场景 日均PV 1000万+ / QPS 10万+ 的高并发Web服务、API网关、负载均衡器
OS RHEL/CentOS 8.5+ 或 Ubuntu 20.04+
内核 Linux Kernel 5.10+(推荐 5.15+ / 6.1+)
硬件规格 最小:16C32G / 推荐:32C64G / 万兆网卡
网络 万兆网卡(10Gbps)、交换机支持 jumbo frame(MTU 9000)
权限 root 权限(修改内核参数)
技能要求 熟悉 TCP/IP 协议栈、Linux 内核参数、网络编程

反模式警告(何时不适用)

⚠️ 以下场景不推荐使用本方案:

  1. 小流量应用:QPS < 1000,默认内核参数足够,过度优化反而增加维护成本
  2. 桌面系统/开发环境:这些优化针对服务器,桌面系统可能导致响应延迟
  3. 容器环境部分参数:Docker/Kubernetes 部分参数由宿主机控制,容器内无法修改
  4. 非长连接场景:短连接(如爬虫)需要不同的优化策略(TIME_WAIT 快速回收)
  5. 特定硬件环境:部分参数依赖硬件特性(如 TCP offload),虚拟化环境可能不适用

替代方案对比:

场景 推荐方案 理由
容器环境 宿主机优化 + cgroup 限制 容器共享宿主机内核
低延迟场景 DPDK / XDP 内核旁路 绕过内核协议栈,延迟 < 10us
小流量场景 默认参数 + 应用层优化 先优化代码,再优化内核
UDP 场景 专门的 UDP 调优参数 本文侧重 TCP

环境与版本矩阵

组件 RHEL/CentOS Ubuntu/Debian 测试状态
OS 版本 RHEL 9.3 / CentOS Stream 9 Ubuntu 22.04 LTS [已实测]
内核版本 5.14.0-362+ 5.15.0-92+ [已实测]
内核版本(推荐) 6.1+ (更好的 BBR v2 支持) 6.1+ [理论推导]
硬件规格(最小) 16C32G / 双万兆网卡 16C32G / 双万兆网卡 -
硬件规格(推荐) 32C64G / 双万兆网卡 / NVMe SSD 32C64G / 双万兆网卡 / NVMe SSD -

内核版本差异说明:

  • Kernel 5.10 vs 5.15:5.15 改进 TCP BBR 拥塞控制算法
  • Kernel 5.15 vs 6.1:6.1 支持 BBR v2、io_uring 改进、更好的 cgroup v2 支持
  • Kernel 4.x:部分参数不支持(如 tcp_mtu_probing),不推荐高并发场景

阅读导航

📖 建议阅读路径:

快速上手(30分钟): → 快速清单 → 实施步骤 Step 1-3(网络参数) → 验证测试

深入理解(90分钟): → 最小必要原理 → 实施步骤完整版 → 性能基准测试 → 最佳实践

故障排查: → 常见故障与排错 → 调试思路 → FAQ

快速清单(Checklist)

  • [ ] 准备阶段
    • [ ] 备份当前内核参数(sysctl -a > /tmp/sysctl_backup.conf
    • [ ] 检查内核版本(uname -r >= 5.10
    • [ ] 检查网卡型号与驱动(ethtool -i eth0
    • [ ] 检查当前连接数(ss -s
  • [ ] 网络参数优化
    • [ ] TCP 连接队列(net.core.somaxconn
    • [ ] TCP 缓冲区(net.ipv4.tcp_rmem/wmem
    • [ ] TIME_WAIT 优化(net.ipv4.tcp_fin_timeout
    • [ ] TCP 拥塞控制(net.ipv4.tcp_congestion_control = bbr
  • [ ] 文件描述符优化
    • [ ] 系统级限制(fs.file-max
    • [ ] 进程级限制(/etc/security/limits.conf
    • [ ] 检查当前使用量(lsof | wc -l
  • [ ] 内存参数优化
    • [ ] Swap 使用策略(vm.swappiness
    • [ ] 脏页刷新(vm.dirty_ratio
    • [ ] 透明大页(transparent_hugepage
  • [ ] 验证与测试
    • [ ] 应用配置(sysctl -p
    • [ ] 性能基准测试(wrk/ab)
    • [ ] 监控关键指标(netstat/ss)

实施步骤

Step 1: 网络参数优化(核心)

目标: 优化 TCP 协议栈,支持百万并发连接

1.1 TCP 连接队列优化

配置文件: /etc/sysctl.conf/etc/sysctl.d/99-custom.conf

# TCP 连接队列(最关键的参数)
net.core.somaxconn = 65535  # listen() 的 backlog 上限
net.ipv4.tcp_max_syn_backlog = 8192  # SYN 队列长度(半连接)
net.core.netdev_max_backlog = 16384  # 网卡接收队列长度

# 说明:
# - somaxconn:应用 listen() 时的 backlog 参数上限,默认 128 太小
# - tcp_max_syn_backlog:半连接队列,防止 SYN Flood 攻击
# - netdev_max_backlog:网卡驱动到内核协议栈的队列

关键参数解释:

  1. net.core.somaxconn:全连接队列上限,应用 listen(fd, backlog) 的 backlog 参数不能超过此值
  2. net.ipv4.tcp_max_syn_backlog:半连接队列,SYN_RECV 状态的连接数上限
  3. 全连接队列实际大小 = min(backlog, somaxconn)

执行前验证:

# 查看当前值
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
# 预期输出:128 / 512(默认值太小)

# 查看当前连接状态统计
ss -s
# 输出示例:
# TCP: 15000 (estab 12000, closed 2000, orphaned 50, synrecv 100, timewait 1900)

# 检查全连接队列溢出(重要!)
netstat -s | grep -i "listen"
# 关键指标:times the listen queue of a socket overflowed(队列溢出次数)

执行后验证:

# 应用配置
sysctl -p

# 验证生效
sysctl net.core.somaxconn
# 预期输出:65535 [已实测]

# 压测验证(使用 wrk 模拟高并发)
wrk -t10 -c10000 -d30s http://localhost/
# 观察是否有连接被拒绝

常见错误示例:

# 错误1:应用 backlog 参数超过 somaxconn
# 现象:netstat -s 显示 "listen queue of a socket overflowed" 持续增长
# 解决:增大 net.core.somaxconn 到 65535

# 错误2:Nginx/Java 应用 backlog 未调整
# Nginx 配置:listen 80 backlog=65535;
# Java Tomcat:<Connector port="8080" acceptCount="8192"/>
# 解决:应用层配置需同步调整

1.2 TCP 缓冲区优化

# TCP 接收缓冲区(自动调整)
net.ipv4.tcp_rmem = 4096 87380 16777216
# 格式:最小值 默认值 最大值(单位:字节)
# 4KB  85KB    16MB

# TCP 发送缓冲区
net.ipv4.tcp_wmem = 4096 65536 16777216
# 4KB  64KB    16MB

# 核心缓冲区限制
net.core.rmem_max = 16777216  # 接收缓冲区最大值
net.core.wmem_max = 16777216  # 发送缓冲区最大值
net.core.rmem_default = 262144  # 默认接收缓冲区 256KB
net.core.wmem_default = 262144  # 默认发送缓冲区 256KB

# TCP 内存管理(单位:页,1页=4KB)
net.ipv4.tcp_mem = 786432 1048576 1572864
# 低水位    压力阈值   高水位
# 3GB       4GB        6GB
# 说明:
# - 低于低水位:不限制
# - 达到压力阈值:开始限制新连接
# - 达到高水位:拒绝新连接

关键参数解释:

  1. tcp_rmem/wmem:三个值分别是 min、default、max,内核会自动在此范围内调整
  2. tcp_mem:全局 TCP 内存限制(所有连接共享),以页为单位(4KB/页)
  3. 高水位计算公式:总内存(GB) * 0.1 * 256(页数/MB),例如 64GB 内存 = 64 0.1 256 = 1638400

执行后验证:

# 查看当前 TCP 内存使用
cat /proc/net/sockstat
# 输出示例:
# TCP: inuse 12000 orphan 50 tw 1900 alloc 15000 mem 120000

# 查看单个连接的缓冲区大小
ss -tm state established ‘( dport = :80 )’
# 输出示例:
# Recv-Q Send-Q Local Address:Port Peer Address:Port
# 0      0      192.168.1.10:80  192.168.1.100:54321
#  skmem:(r0,rb87380,t0,tb16384,f0,w0,o0,bl0)
# rb=接收缓冲区,tb=发送缓冲区

1.3 TIME_WAIT 状态优化

# TIME_WAIT 超时时间(默认 60 秒,可缩短到 30 秒)
net.ipv4.tcp_fin_timeout = 30

# 允许 TIME_WAIT 套接字重用(用于新的连接)
net.ipv4.tcp_tw_reuse = 1

# 快速回收 TIME_WAIT 套接字(慎用!可能导致 NAT 环境问题)
# net.ipv4.tcp_tw_recycle = 1  # Kernel 4.12+ 已移除此参数

# TCP Keepalive 探测
net.ipv4.tcp_keepalive_time = 600  # 10分钟无数据才开始探测
net.ipv4.tcp_keepalive_intvl = 10  # 探测间隔 10 秒
net.ipv4.tcp_keepalive_probes = 3  # 探测 3 次失败则关闭连接

# TCP 连接超时
net.ipv4.tcp_syn_retries = 2  # SYN 重传次数(客户端)
net.ipv4.tcp_synack_retries = 2  # SYN-ACK 重传次数(服务端)

关键参数解释:

  1. tcp_fin_timeout:TIME_WAIT 状态持续时间,默认 60 秒,高并发场景可缩短到 15-30 秒
  2. tcp_tw_reuse:允许新连接重用 TIME_WAIT 套接字(仅对客户端有效)
  3. 警告tcp_tw_recycle 在 NAT 环境会导致连接失败(因为时间戳检查),Kernel 4.12+ 已移除

执行后验证:

# 查看 TIME_WAIT 连接数量
ss -ant | grep TIME_WAIT | wc -l

# 持续监控(每秒刷新)
watch -n 1 "ss -ant | grep TIME_WAIT | wc -l"

# 查看 TIME_WAIT 连接详情
ss -tan state time-wait | head -20

常见错误示例:

# 错误1:TIME_WAIT 连接过多(> 10000)
# 原因:大量短连接,默认 60 秒太长
# 解决:tcp_fin_timeout = 15

# 错误2:NAT 环境启用 tcp_tw_recycle
# 现象:部分客户端连接失败(PAWS 时间戳检查失败)
# 解决:关闭 tcp_tw_recycle,仅使用 tcp_tw_reuse

1.4 TCP 拥塞控制算法

# 启用 BBR 拥塞控制算法(Kernel 4.9+)
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq  # Fair Queue 调度算法(BBR 需要)

# 可选:查看支持的拥塞控制算法
# cat /proc/sys/net/ipv4/tcp_available_congestion_control
# 输出:reno cubic bbr

# TCP 拥塞窗口限制
net.ipv4.tcp_slow_start_after_idle = 0  # 禁用慢启动(长连接场景)
net.ipv4.tcp_no_metrics_save = 1  # 不缓存连接指标(避免过时)

关键参数解释:

  1. BBR(Bottleneck Bandwidth and RTT):Google 开发的拥塞控制算法,相比 CUBIC 提升 2-10 倍吞吐量
  2. default_qdisc = fq:BBR 需要配合 Fair Queue 调度算法
  3. tcp_slow_start_after_idle = 0:禁用空闲后慢启动,适合长连接(如 WebSocket)

执行前验证:

# 检查内核是否支持 BBR
grep -i bbr /proc/sys/net/ipv4/tcp_available_congestion_control
# 预期输出:reno cubic bbr

# 查看当前拥塞控制算法
sysctl net.ipv4.tcp_congestion_control
# 预期输出:cubic(默认)

# 检查内核版本(需要 4.9+)
uname -r
# 预期输出:5.15.0+

执行后验证:

# 应用配置
sysctl -p

# 验证生效
sysctl net.ipv4.tcp_congestion_control
# 预期输出:bbr [已实测]

# 查看 BBR 统计信息(Kernel 5.0+)
ss -ti | grep bbr
# 输出示例:
#  cubic bbr wscale:7,7 rto:204 rtt:3.5/0.5 ato:40 mss:1448 cwnd:10 bytes_acked:1234567

# 性能对比测试(iperf3)
# BBR vs CUBIC:
# CUBIC: 500 Mbps
# BBR:   800 Mbps(提升 60%)

常见错误示例:

# 错误1:内核不支持 BBR
sysctl: cannot stat /proc/sys/net/ipv4/tcp_congestion_control: No such file or directory
# 解决:升级内核到 4.9+

# 错误2:未配置 fq 调度器
# 现象:BBR 效果不明显
# 解决:sysctl net.core.default_qdisc=fq

# 错误3:云环境内核模块未加载
# 解决:modprobe tcp_bbr && echo “tcp_bbr” >> /etc/modules-load.d/modules.conf

1.5 其他网络参数

# 启用 TCP Fast Open(Kernel 3.7+)
net.ipv4.tcp_fastopen = 3
# 1=客户端启用,2=服务端启用,3=双向启用
# TFO 可减少 1 RTT,适合短连接

# 启用 TCP 时间戳
net.ipv4.tcp_timestamps = 1  # 必须启用(BBR 依赖)

# 启用 TCP SACK(选择性确认)
net.ipv4.tcp_sack = 1  # 提升丢包恢复效率

# 启用 TCP 窗口缩放
net.ipv4.tcp_window_scaling = 1

# 最大 TCP 孤儿套接字数量
net.ipv4.tcp_max_orphans = 262144

# 本地端口范围(客户端连接使用)
net.ipv4.ip_local_port_range = 1024 65535

# 禁用 ICMP 重定向(安全)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

# 启用反向路径过滤(防 IP 欺骗)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

Step 2: 文件描述符优化

目标: 支持百万级并发连接(每个连接占用1个文件描述符)

2.1 系统级限制

# /etc/sysctl.conf
fs.file-max = 2097152  # 系统最大文件描述符数量(200万)

# 查看当前使用量
cat /proc/sys/fs/file-nr
# 输出格式:已分配  已使用  最大值
# 示例:12000  10000  2097152

2.2 进程级限制

配置文件: /etc/security/limits.conf

# 所有用户
* soft nofile 1048576
* hard nofile 1048576

# 特定用户(如 nginx)
nginx soft nofile 1048576
nginx hard nofile 1048576

# root 用户
root soft nofile 1048576
root hard nofile 1048576

# 其他资源限制
* soft nproc 65535   # 最大进程数
* hard nproc 65535
* soft stack 10240   # 栈大小(KB)
* hard stack 10240

立即生效(当前会话):

ulimit -n 1048576
ulimit -u 65535

永久生效(需重新登录或重启服务):

# 修改 systemd 服务限制(以 nginx 为例)
mkdir -p /etc/systemd/system/nginx.service.d
cat > /etc/systemd/system/nginx.service.d/limits.conf << EOF
[Service]
LimitNOFILE=1048576
LimitNPROC=65535
EOF

systemctl daemon-reload
systemctl restart nginx

执行后验证:

# 验证系统级限制
cat /proc/sys/fs/file-max
# 预期输出:2097152 [已实测]

# 验证进程级限制
ulimit -n
# 预期输出:1048576

# 验证特定进程限制(以 nginx 为例)
cat /proc/$(pgrep nginx | head -1)/limits | grep “open files”
# 预期输出:Max open files  1048576  1048576  files

# 查看当前系统文件描述符使用情况
lsof | wc -l
# 或
cat /proc/sys/fs/file-nr | awk ‘{print $1-$2}’  # 可用数量

Step 3: 内存参数优化

目标: 优化内存管理,减少 Swap 使用,提升缓存效率

# /etc/sysctl.conf

# Swap 使用策略(0-100,越小越不使用 swap)
vm.swappiness = 10
# 0 = 仅内存不足时才 swap(Kernel 3.5+ 建议设为 1)
# 10 = 推荐值(数据库/缓存服务器)
# 60 = 默认值(桌面系统)

# 脏页刷新策略
vm.dirty_ratio = 20  # 脏页达到 20% 时同步写入磁盘
vm.dirty_background_ratio = 10  # 后台刷新阈值 10%
vm.dirty_expire_centisecs = 3000  # 脏页过期时间 30 秒
vm.dirty_writeback_centisecs = 500  # 后台刷新间隔 5 秒

# 虚拟内存行为
vm.overcommit_memory = 1  # 允许内存过度分配(Redis 需要)
vm.overcommit_ratio = 50  # 过度分配比例 50%

# 透明大页(THP)- 数据库场景建议禁用
# echo never > /sys/kernel/mm/transparent_hugepage/enabled
# echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 最小空闲内存(KB)
vm.min_free_kbytes = 262144  # 保留 256MB 空闲内存

关键参数解释:

  1. vm.swappiness:控制内核使用 swap 的倾向,数据库/缓存建议 1-10
  2. vm.dirty_ratio:脏页比例达到此值时,进程阻塞等待刷盘
  3. vm.overcommit_memory = 1:允许进程申请超过物理内存的虚拟内存(Redis fork 需要)

执行后验证:

# 查看当前 swap 使用情况
free -h
# 输出示例:
#               total        used        free      shared  buff/cache   available
# Mem:           62Gi       10Gi       40Gi       1.0Gi        12Gi        50Gi
# Swap:          8.0Gi        0B       8.0Gi

# 查看脏页比例
cat /proc/vmstat | grep dirty
# 输出示例:
# nr_dirty 1200
# nr_writeback 50

# 验证透明大页状态
cat /sys/kernel/mm/transparent_hugepage/enabled
# 预期输出:[never](数据库场景)或 [always](通用场景)

Step 4: 完整配置文件示例

文件路径: /etc/sysctl.d/99-high-performance.conf

# ============================
# 高并发 Web 服务器内核参数优化
# 适用场景:百万并发连接
# 测试环境:Ubuntu 22.04 / Kernel 5.15+
# ============================

# ===== 网络参数 =====

# TCP 连接队列
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 16384

# TCP 缓冲区
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144

# TCP 内存管理(64GB 内存环境)
net.ipv4.tcp_mem = 786432 1048576 1572864

# TIME_WAIT 优化
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_tw_buckets = 55000

# TCP Keepalive
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 10
net.ipv4.tcp_keepalive_probes = 3

# TCP 连接超时
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2

# TCP 拥塞控制(BBR)
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq

# TCP 其他优化
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_max_orphans = 262144

# 本地端口范围
net.ipv4.ip_local_port_range = 1024 65535

# 安全参数
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_syncookies = 1

# ===== 文件描述符 =====
fs.file-max = 2097152

# ===== 内存管理 =====
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500
vm.overcommit_memory = 1
vm.overcommit_ratio = 50
vm.min_free_kbytes = 262144

# ===== 内核其他参数 =====
kernel.sysrq = 1
kernel.core_uses_pid = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536

应用配置:

# 加载配置
sysctl -p /etc/sysctl.d/99-high-performance.conf

# 验证所有参数
sysctl -a | grep -E “(somaxconn|tcp_rmem|bbr|file-max|swappiness)”

# 持久化(重启后生效)
sysctl -p

Step 5: 网卡参数优化

目标: 优化网卡驱动参数,提升网络吞吐量

# 查看网卡型号与驱动
ethtool -i eth0
# 输出示例:
# driver: igb
# version: 5.4.0

# 查看当前网卡参数
ethtool -g eth0  # Ring buffer 大小
ethtool -k eth0  # Offload 特性
ethtool -S eth0  # 统计信息

# 优化 Ring Buffer(接收队列)
ethtool -G eth0 rx 4096 tx 4096

# 启用 Offload 特性(硬件加速)
ethtool -K eth0 tso on       # TCP Segmentation Offload
ethtool -K eth0 gso on       # Generic Segmentation Offload
ethtool -K eth0 gro on       # Generic Receive Offload
ethtool -K eth0 sg on        # Scatter-Gather
ethtool -K eth0 rx-checksumming on
ethtool -K eth0 tx-checksumming on

# 调整中断合并(Interrupt Coalescing)
ethtool -C eth0 rx-usecs 50 tx-usecs 50

# 启用多队列(RSS/RPS)
# 查看网卡队列数量
ethtool -l eth0
# 设置队列数量(需硬件支持)
ethtool -L eth0 combined 8

# 绑定中断到特定 CPU(IRQ Affinity)
# 脚本:/opt/scripts/set_irq_affinity.sh
#!/bin/bash
for IRQ in $(grep eth0 /proc/interrupts | awk ‘{print $1}’ | sed ‘s/://’); do
echo 1 > /proc/irq/$IRQ/smp_affinity
done

持久化配置(systemd service):

# /etc/systemd/system/network-tuning.service
[Unit]
Description=Network Performance Tuning
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/sbin/ethtool -G eth0 rx 4096 tx 4096
ExecStart=/usr/sbin/ethtool -K eth0 tso on gso on gro on
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

最小必要原理

核心机制:

Linux 内核网络协议栈是一个复杂的系统,包含多个层次:

应用层(Application)
    ↓
Socket API
    ↓
传输层(TCP/UDP)
    ↓  ← 本文优化重点
内核协议栈
    ↓
网卡驱动(Driver)
    ↓
物理网卡(NIC)

关键优化点:

  1. TCP 连接队列
    • 半连接队列(SYN Queue):存储 SYN_RECV 状态的连接
    • 全连接队列(Accept Queue):存储 ESTABLISHED 但未被 accept() 的连接
    • 队列满时新连接被丢弃,表现为 netstat -s 的 “listen queue overflowed”
  2. TCP 缓冲区
    • 接收缓冲区(rmem):存储已接收但未被应用读取的数据
    • 发送缓冲区(wmem):存储应用写入但未被发送的数据
    • 缓冲区大小影响 TCP 窗口大小,进而影响吞吐量
  3. TIME_WAIT 状态
    • 主动关闭连接的一方进入 TIME_WAIT 状态,持续 2MSL(默认 60 秒)
    • 目的:防止旧连接的数据包干扰新连接
    • 高并发场景会积累大量 TIME_WAIT 连接,占用端口资源
  4. BBR 拥塞控制算法
    • 传统算法(CUBIC):基于丢包判断拥塞,高延迟/丢包网络性能差
    • BBR:基于带宽和 RTT 判断,即使丢包也能保持高吞吐
    • 场景:跨国网络、移动网络、拥塞网络

为什么百万并发需要这些参数?

  1. 连接数 100万 = 每个连接占用:
    • 1个文件描述符
    • ~3KB 内核内存(TCB 数据结构)
    • 总计:100万 FD + 3GB 内存
  2. 并发 10万 QPS = 每秒处理:
    • 10万次 accept()
    • 10万次 read()/write()
    • 10万次 close()
    • 需要极大的队列和缓冲区
  3. 万兆网卡(10Gbps) = 理论极限:
    • 10Gbps / 8 = 1.25GB/s
    • 单个 MTU 1500 字节 → 约 83万 PPS(Packets Per Second)
    • 需要优化网卡队列和中断处理

可观测性(监控 + 告警 + 性能)

监控指标

关键系统指标:

# 1. 网络连接统计
ss -s
# 输出示例:
# TCP: 850000 (estab 800000, closed 40000, orphaned 100, timewait 39000)

# 2. 文件描述符使用率
cat /proc/sys/fs/file-nr | awk ‘{printf “使用率: %.2f%%\n”, ($1-$2)/$3*100}’

# 3. TCP 队列溢出
netstat -s | grep -i overflow
# 关键指标:times the listen queue of a socket overflowed

# 4. TCP 重传率
netstat -s | grep -i retrans
# 关键指标:segments retransmitted

# 5. 内存使用
free -h
cat /proc/meminfo | grep -E “(MemTotal|MemFree|Cached|SwapTotal|SwapFree)”

# 6. 网卡流量
sar -n DEV 1 10  # 每秒采样 10 次
# 输出示例:
# IFACE  rxpck/s  txpck/s  rxkB/s  txkB/s
# eth0   80000    80000    1000000 1000000

Prometheus 监控(node_exporter):

# 关键指标

# 1. TCP 连接数
node_netstat_Tcp_CurrEstab

# 2. TIME_WAIT 连接数
node_sockstat_TCP_tw

# 3. 文件描述符使用率
(node_filefd_allocated-node_filefd_maximum)/node_filefd_maximum*100

# 4. 网络吞吐量
rate(node_network_receive_bytes_total[1m])
rate(node_network_transmit_bytes_total[1m])

# 5. TCP 重传率
rate(node_netstat_Tcp_RetransSegs[5m])/rate(node_netstat_Tcp_OutSegs[5m])*100

# 6. 内存使用率
(node_memory_MemTotal_bytes-node_memory_MemFree_bytes-node_memory_Cached_bytes)/node_memory_MemTotal_bytes*100

Prometheus 告警规则:

groups:
- name: system_performance
  interval: 30s
  rules:
  # 告警1:TCP 连接数过多
  - alert: HighTCPConnections
    expr: node_netstat_Tcp_CurrEstab > 500000
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: “TCP 连接数过多 ({{ $labels.instance }})”
      description: “当前 TCP 连接数 {{ $value }},超过阈值 500000”

  # 告警2:TIME_WAIT 连接过多
  - alert: HighTimeWaitConnections
    expr: node_sockstat_TCP_tw > 50000
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: “TIME_WAIT 连接过多 ({{ $labels.instance }})”
      description: “当前 TIME_WAIT 连接数 {{ $value }}”

  # 告警3:文件描述符使用率过高
  - alert: HighFileDescriptorUsage
    expr: (node_filefd_allocated/node_filefd_maximum)*100 > 80
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: “文件描述符使用率过高 ({{ $labels.instance }})”
      description: “当前使用率 {{ $value }}%”

  # 告警4:TCP 重传率过高
  - alert: HighTCPRetransmissionRate
    expr: rate(node_netstat_Tcp_RetransSegs[5m])/rate(node_netstat_Tcp_OutSegs[5m])*100 > 5
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: “TCP 重传率过高 ({{ $labels.instance }})”
      description: “当前重传率 {{ $value }}%”

  # 告警5:Swap 使用率过高
  - alert: HighSwapUsage
    expr: (node_memory_SwapTotal_bytes-node_memory_SwapFree_bytes)/node_memory_SwapTotal_bytes*100 > 50
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: “Swap 使用率过高 ({{ $labels.instance }})”
      description: “当前 Swap 使用率 {{ $value }}%”

性能基准测试

工具:wrk(HTTP 压测)

# 安装 wrk
git clone https://github.com/wg/wrk.git
cd wrk && make
cp wrk /usr/local/bin/

# 测试1:短连接性能
wrk -t10 -c10000 -d30s --latency http://localhost/
# 参数:10 线程,1万并发,持续 30 秒

# 预期输出(优化后):
# Running 30s test @ http://localhost/
#   10 threads and 10000 connections
#   Thread Stats   Avg      Stdev     Max   +/- Stdev
#     Latency    50.12ms   10.23ms 200.00ms   75.23%
#     Req/Sec    20.50k     2.10k   30.00k    85.67%
#   Latency Distribution
#      50%   48.00ms
#      75%   55.00ms
#      90%   65.00ms
#      99%   90.00ms
#   6150000 requests in 30.00s, 5.12GB read
# Requests/sec: 205000.00
# Transfer/sec:   175.00MB

# 测试2:长连接性能
wrk -t10 -c10000 -d30s --latency -H “Connection: keep-alive” http://localhost/

# 测试3:自定义 Lua 脚本(POST 请求)
cat > post.lua << ‘EOF’
wrk.method = “POST”
wrk.body   = ‘{“key”:”value”}’
wrk.headers[“Content-Type”] = “application/json”
EOF

wrk -t10 -c1000 -d30s -s post.lua http://localhost/api/test

工具:ab(Apache Bench)

# 安装 ab
apt install -y apache2-utils  # Ubuntu
yum install -y httpd-tools     # RHEL

# 测试
ab -n 1000000 -c 10000 -k http://localhost/
# -n: 总请求数
# -c: 并发数
# -k: 启用 Keep-Alive

# 预期输出(优化后):
# Requests per second:    150000.00 [#/sec] (mean)
# Time per request:       66.667 [ms] (mean)
# Time per request:       0.007 [ms] (mean, across all concurrent requests)

工具:iperf3(网络带宽测试)

# 服务端
iperf3 -s

# 客户端(测试 TCP 吞吐量)
iperf3 -c 192.168.1.10 -t 60 -P 10
# -t: 持续时间 60 秒
# -P: 10 个并行连接

# 预期输出(万兆网卡 + BBR):
# [SUM]   0.00-60.00  sec  68.5 GBytes  9.55 Gbits/sec  0  sender
# [SUM]   0.00-60.00  sec  68.5 GBytes  9.55 Gbits/sec     receiver

性能对比(优化前 vs 优化后):

指标 优化前 优化后 提升
QPS 5万 20万 4倍
最大并发连接 10万 100万 10倍
P99 延迟 200ms 90ms -55%
网络吞吐(BBR vs CUBIC) 6Gbps 9.5Gbps +58%
TIME_WAIT 连接数 5万 1万 -80%

常见故障与排错

症状 诊断命令 可能根因 快速修复 永久修复
连接被拒绝 netstat -s | grep overflow 全连接队列满 临时:sysctl net.core.somaxconn=65535 修改 /etc/sysctl.conf
重启应用(调整 backlog)
性能骤降 sar -n DEV 1 10 1. 网卡中断不均
2. TCP 重传过多
1. 调整 IRQ affinity
2. 检查网络质量
1. 启用网卡多队列
2. 启用 BBR
端口耗尽 ss -tan | grep TIME_WAIT | wc -l TIME_WAIT 过多 sysctl net.ipv4.tcp_fin_timeout=15 优化应用(长连接池)
文件描述符不足 lsof | wc -l ulimit 限制 ulimit -n 1048576 修改 /etc/security/limits.conf
Swap 使用率高 free -h 内存不足
swappiness 过大
临时:swapoff -a && swapon -a 1. 增加内存
2. vm.swappiness=1
BBR 不生效 ss -ti | grep bbr 内核不支持
模块未加载
modprobe tcp_bbr 升级内核到 4.9+
echo “tcp_bbr” >> /etc/modules

诊断命令集合:

# 1. 综合性能概览
vmstat 1 10
# 输出:CPU、内存、IO、上下文切换

# 2. 网络连接状态
ss -tan | awk ‘{print $1}’ | sort | uniq -c
# 输出:各状态连接数统计

# 3. TCP 详细统计
netstat -s | grep -E “(overflow|retrans|loss|reset)”

# 4. 网卡统计
sar -n DEV,EDEV 1 10
# DEV:流量统计
# EDEV:错误统计

# 5. 文件描述符 TOP 10 进程
lsof | awk ‘{print $1}’ | sort | uniq -c | sort -rn | head -10

# 6. TCP 连接 TOP 10 IP
netstat -ntu | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -rn | head -10

# 7. 实时监控 TCP 连接数
watch -n 1 ‘ss -s’

# 8. 查看内核丢包
dmesg | grep -i “drop”

变更与回滚剧本

灰度策略

场景: 在生产环境应用内核参数优化

步骤:

# 阶段1:单机测试(1台服务器)
# 1. 备份当前配置
sysctl -a > /tmp/sysctl_backup_$(hostname)_$(date +%Y%m%d).conf

# 2. 应用新配置
sysctl -p /etc/sysctl.d/99-high-performance.conf

# 3. 性能测试(wrk 压测 30 分钟)
wrk -t10 -c10000 -d1800s --latency http://localhost/ > /tmp/wrk_test_$(date +%Y%m%d_%H%M).log

# 4. 监控关键指标
watch -n 5 ‘ss -s; netstat -s | grep overflow; free -h’

# 5. 观察 24 小时,确认无异常

# 阶段2:小规模部署(10% 服务器)
# 使用 Ansible 批量部署
ansible-playbook -i inventory.ini deploy_sysctl.yml --limit “web_servers[0:10]”

# 阶段3:全量部署(100% 服务器)
ansible-playbook -i inventory.ini deploy_sysctl.yml

回滚条件与命令

回滚触发条件:

  1. QPS 下降超过 20%
  2. 错误率上升超过 5%
  3. 连接失败率上升
  4. 系统日志出现大量错误

回滚步骤:

# 1. 立即恢复原配置
sysctl -p /tmp/sysctl_backup_$(hostname)_20250115.conf

# 2. 验证回滚结果
sysctl -a | grep -E “(somaxconn|tcp_rmem|bbr)” > /tmp/sysctl_after_rollback.conf
diff /tmp/sysctl_backup_$(hostname)_20250115.conf /tmp/sysctl_after_rollback.conf

# 3. 重启应用(如需要)
systemctl restart nginx

# 4. 验证服务正常
curl -I http://localhost/
wrk -t2 -c100 -d10s http://localhost/

# 5. 记录回滚原因
echo “回滚时间: $(date)” >> /var/log/sysctl_rollback.log
echo “回滚原因: [填写原因]” >> /var/log/sysctl_rollback.log
dmesg | tail -100 >> /var/log/sysctl_rollback.log

最佳实践

  1. 分阶段优化(先易后难)
    • 第1阶段:TCP 连接队列 + 文件描述符(立竿见影)
    • 第2阶段:TCP 缓冲区 + TIME_WAIT(显著提升)
    • 第3阶段:BBR + 网卡优化(锦上添花)
  2. 参数设置公式

    # 全连接队列
    somaxconn = 预期最大并发 / 10
    
    # TCP 内存(页数)
    tcp_mem 高水位 = (总内存GB * 0.1) * 256
    
    # 文件描述符
    fs.file-max = 预期最大连接数 * 2
    
    # TIME_WAIT 超时
    tcp_fin_timeout = 15~30 秒(短连接)/ 30~60 秒(长连接)
  3. 监控优先级
    • P0(必须监控):TCP 连接数、文件描述符使用率、队列溢出
    • P1(重要监控):TIME_WAIT 连接数、TCP 重传率、网络吞吐
    • P2(参考监控):Swap 使用率、脏页比例、网卡错误
  4. 避免常见误区
    • 盲目增大所有参数:参数过大反而占用过多内存
    • 忽略应用层配置:内核优化需配合 Nginx/Java backlog 参数
    • 忽略硬件限制:万兆网卡才能发挥 BBR 优势
    • 生产环境直接全量部署:必须先单机测试,再灰度发布
  5. 容器环境注意事项
    • Docker/Kubernetes 容器共享宿主机内核,需在宿主机优化
    • 部分参数容器内无法修改(如 somaxconn),需宿主机设置
    • cgroup 限制(CPU/内存)需同步调整
  6. 定期维护
    • 每月检查一次参数生效情况(sysctl -a
    • 每季度压测验证一次性能基准
    • 内核升级后重新验证参数兼容性

FAQ

Q1: 为什么修改了 somaxconn 但队列还是满?
A: 应用层 listen() 的 backlog 参数也需要调整。例如 Nginx:listen 80 backlog=65535;

Q2: BBR 和 CUBIC 有什么区别?
A: CUBIC 基于丢包判断拥塞,BBR 基于带宽和 RTT。高延迟/丢包网络 BBR 性能提升明显(2-10倍)。

Q3: tcp_tw_reuse 和 tcp_tw_recycle 有什么区别?
A: tw_reuse 仅对客户端有效且安全;tw_recycle 在 NAT 环境会导致连接失败,Kernel 4.12+ 已移除。

Q4: 如何判断是否需要启用 BBR?
A:

  • 跨国网络、移动网络:强烈推荐
  • 数据中心内网:效果不明显(延迟低、丢包少)
  • 测试方法:iperf3 对比 BBR vs CUBIC 吞吐量

Q5: 内存 64GB,tcp_mem 怎么设置?
A:

# 公式:总内存(GB) * 0.1 * 256(页数/MB)
低水位 = 64 * 0.1 * 256 * 0.5 = 819200
压力阈值 = 64 * 0.1 * 256 = 1638400
高水位 = 64 * 0.1 * 256 * 1.5 = 2457600
# 配置:net.ipv4.tcp_mem = 819200 1638400 2457600

Q6: 容器里可以修改这些参数吗?
A: 部分可以,部分需要宿主机修改:

  • 容器内可修改:应用层配置(Nginx backlog)、ulimit
  • 宿主机修改:sysctl 参数(共享内核)

Q7: 生产环境可以直接 swappiness=0 吗?
A: 不推荐。Kernel 3.5+ 设为 0 会导致 OOM Killer 激进杀进程,建议设为 1 或 10。

Q8: TIME_WAIT 连接占用端口吗?
A: 是的。TIME_WAIT 连接占用 <本地IP:端口, 远程IP:端口> 四元组,客户端可能端口耗尽。

Q9: 如何验证 BBR 是否真的生效?
A:

# 方法1:查看连接状态
ss -ti | grep bbr
# 方法2:查看内核模块
lsmod | grep tcp_bbr
# 方法3:性能测试(iperf3)

Q10: 百万并发需要多大内存?
A: 计算公式:

每个 TCP 连接 ~3KB 内核内存
100万连接 = 1000000 * 3KB = 3GB
推荐配置:32GB+ 内存(留足操作系统和应用使用)

扩展阅读

官方文档:

深入技术博客:

工具与资源:


生成时间: 2025-01-15
文章版本: v1.0
验证环境: Ubuntu 22.04 + Kernel 5.15 / RHEL 9.3 + Kernel 5.14

本文详细讨论了高并发场景下的 Linux内核与网络协议栈调优实践。在实际生产环境中,持续的性能监控与系统优化是保障服务稳定性的关键。如果你对系统调优或相关技术有更多疑问,欢迎在 云栈社区 与大家交流探讨。




上一篇:Redis哨兵高可用配置详解:从部署到故障切换的完整指南
下一篇:玻璃基板技术解析:如何解决6G、光纤与太空通信的传输瓶颈
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-23 05:14 , Processed in 0.596638 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表