1. 编译安装过程优化
减小编译产物体积
Nginx 默认以 debug 模式编译,会插入大量跟踪与 ASSERT 信息,产物有好几兆。取消 debug 后只有几百 KB。
解压源码后,编辑 auto/cc/gcc,找到并注释掉:
# debug
CFLAGS="$CFLAGS -g"
针对 CPU 做编译优化
默认 GCC 参数是 -O,可改为:
--with-cc-opt='-O3'
--with-cpu-opt=CPU
--with-cpu-opt 的有效值:pentium、pentiumpro、pentium3、pentium4、athlon、opteron、amd64、sparc32、sparc64、ppc64。
查看 CPU 类型:
cat /proc/cpuinfo | grep "model name"
2. 用 TCMalloc 优化内存分配
TCMalloc(Thread-Caching Malloc)来自 Google 的 google-perftools,内存分配效率和速度远高于 glibc 的 malloc,能显著提升高并发下的性能。
安装 libunwind(64 位系统需要)
cd /usr/local/src
wget https://download.savannah.gnu.org/releases/libunwind/libunwind-1.6.2.tar.gz
tar -zxvf libunwind-1.6.2.tar.gz
cd libunwind-1.6.2/
CFLAGS=-fPIC ./configure
make CFLAGS=-fPIC
make CFLAGS=-fPIC install
CentOS 上编译如遇
stdatomic.h: 没有那个文件或目录,是因为自带 gcc 版本过低,需先升级 gcc。
安装 google-perftools
cd /usr/local/src
wget https://github.com/gperftools/gperftools/releases/download/gperftools-2.10/gperftools-2.10.tar.gz
tar -zxvf gperftools-2.10.tar.gz
cd gperftools-2.10/
./configure
make && make install
64 位系统需先装 libunwind,并在 configure gperftools 时加
--enable-frame-pointers参数。
让 Nginx 使用 TCMalloc
编译时加入:
./configure --with-google_perftools_module
make && make install
若 Nginx 在装 google-perftools 之前就已安装,需要考虑平滑升级或平滑重启,在 configure 时补上参数即可。
验证:worker_processes 设为 4 时会生成 4 个线程记录,每个线程文件后面的数字就是该 Nginx 的 pid。
3. 内核参数优化
写入 /etc/sysctl.conf 后执行 /sbin/sysctl -p 生效:
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_syncookies = 1
#net.core.somaxconn = 262144
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30
TCP 参数释义
| 参数 | 说明 |
|---|---|
tcp_max_tw_buckets | timewait 数量上限,默认 180000,这里设 6000 |
ip_local_port_range | 允许系统打开的端口范围。Nginx 作代理时每个到上游的连接都要用一个临时端口,高并发下端口不够用 |
tcp_tw_recycle | 启用 timewait 快速回收 |
tcp_tw_reuse | 允许将 TIME-WAIT sockets 重用于新连接 |
tcp_syncookies | SYN 等待队列溢出时启用 cookies 处理 |
tcp_max_orphans | 最多允许多少 TCP 套接字不关联到用户文件句柄,防止简单 DoS |
tcp_max_syn_backlog | 未收到客户端确认的连接请求最大值,128MB 内存系统默认 1024 |
tcp_synack_retries | 内核放弃连接前发送 SYN+ACK 包的数量 |
tcp_syn_retries | 内核放弃建立连接前发送 SYN 包的数量 |
tcp_fin_timeout | 套接字保持在 FIN-WAIT-2 状态的时间,默认 60 秒 |
tcp_keepalive_time | keepalive 启用时发送 keepalive 消息的频度,默认 2 小时 |
tcp_fin_timeout值得注意:负载很小的 Web 服务器也可能因大量死套接字导致内存溢出。FIN-WAIT-2 危险性比 FIN-WAIT-1 小(最多消耗 1.5KB 内存),但生存期更长。
缓冲区队列
| 参数 | 说明 |
|---|---|
net.core.somaxconn | 调节系统同时发起的 TCP 连接数,默认 128。高并发下默认值会导致链接超时或重传;若设置大于 512,需同步调整 Nginx listen 指令的 backlog 参数 |
net.core.netdev_max_backlog | 网络接口收包速率快于内核处理速率时,允许发送到队列的数据包最大数目 |
4. PHP-FPM 优化
高负载站点用 PHP-FPM 管理 FastCGI 时:
- 增加 FastCGI 进程数:PHP FastCGI 子进程数调到 100 以上,4G 内存的服务器上 200 即可,建议用压力测试获取最佳值;
- 增加 PHP-FPM 打开文件描述符的限制:在 php-fpm 启动脚本或服务文件中提高
ulimit -n,并与worker_rlimit_nofile对齐。
pm = dynamic
pm.max_children = 200
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
rlimit_files = 65536
5. nginx.conf 参数优化
| 指令 | 建议 |
|---|---|
worker_processes | 设为 CPU 核心数或 auto |
worker_cpu_affinity | 多核机器可绑定 CPU,减少进程切换开销 |
worker_rlimit_nofile | 与 ulimit -n 一致,避免并发高时返回 502 |
worker_connections | 尽量大,最大并发 ≈ worker_processes × worker_connections |
use epoll | Linux 2.6+ 用 epoll 事件模型 |
sendfile on | 开启零拷贝传输 |
tcp_nopush / tcp_nodelay | 配合 sendfile 开启 |
gzip on | 开启压缩,注意 gzip_comp_level 不宜过高 |
keepalive_timeout | 长连接超时,按业务调整,过长会占用连接资源 |
open_file_cache | 缓存打开的文件描述符,减少 stat 调用 |
优化顺序建议
- 先确认瓶颈在哪:CPU 密集、IO 密集还是连接数打满;
- 编译期优化收益有限,优先调
worker_*与内核参数; - 每次只改一处并用压测对比,避免参数堆叠掩盖真实问题;
somaxconn与listen ... backlog、worker_rlimit_nofile与ulimit -n这两对参数必须成对调整。