Nginx 服务配置优化

1. 进程数设置 (worker_processes)

worker_processes 定义了 Nginx 对外提供 Web 服务时的 worker 进程数。最优值取决于许多因素,包括(但不限于)CPU 核的数量、存储数据的硬盘数量及负载模式。

  • 建议:按照 CPU 数目来指定,一般为它的倍数。
  • 不确定时:将其设置为可用的 CPU 内核数将是一个好的开始(可以设置为 auto 将尝试自动检测它)。
worker_processes 8;

2. CPU 亲和性 (worker_cpu_affinity)

为每个进程分配 CPU。上例中将 8 个进程分配到 8 个 CPU,当然可以写多个,或者将一个进程分配到多个 CPU。

worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

3. 最大文件句柄数

指定 worker 进程能够打开的最大句柄数,默认选择与 ulimit -n 的值一致。可通过 ulimit 命令或修改系统配置文件进行调整。

# 临时修改当前会话限制
ulimit -n 65535

# 永久修改需编辑 /etc/security/limits.conf

4. 事件模型 (use)

Nginx 使用 epoll 模型,适用于 Linux 系统高并发场景。

use epoll;

5. 单个进程连接数 (worker_connections)

单个 worker 进程连接数限制。理论上每台 Nginx 服务器的最大连接数为 worker_processes * worker_connections

worker_connections 102400;

6. Keepalive 超时时间

Keepalive 超时时间设置,建议为 60s,不要设置太大。

keepalive_timeout 60;

7. 客户端请求头部缓冲区

客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置。一般一个请求的头部大小不会超过 1k,不过由于一般系统分页都要大于 1k,所以这里设置为分页大小。分页大小可以用命令 getconf PAGESIZE 取得。

client_header_buffer_size 4k;
[root@localhost ~]# getconf PAGESIZE
4096
[root@localhost ~]# 

8. 打开文件缓存 (open_file_cache)

这个将为打开文件指定缓存,默认是没有启用的。

  • max:指定缓存数量,建议和打开文件数一致。
  • inactive:指经过多长时间文件没被请求后删除缓存。
open_file_cache max=102400 inactive=20s;

9. 缓存有效性检查

指定多长时间检查一次缓存的有效性。

open_file_cache_valid 30s;

10. 缓存最小使用次数

open_file_cache 指令中的 inactive 参数时间内文件的最少使用次数。如果超过这个数字,文件描述符一直是在缓存中打开的。如上例,如果有一个文件在 inactive 时间内一次没被使用,它将被移除。

open_file_cache_min_uses 1;

内核参数优化

1. TIME_WAIT 状态 Socket 数量

表示系统同时保持 TIME_WAIT 状态的 socket 数量。如果超过这个值,TIME_WAIT 状态的 socket 会被清除,同时打印警告日志。默认 18000,减少这个值可以加快无效连接的回收。

net.ipv4.tcp_max_tw_buckets = 6000

2. 本地端口范围

允许打开的端口范围。

net.ipv4.ip_local_port_range = 1024 65000

3. TIME_WAIT 快速回收 (tcp_tw_recycle)

tcp_tw_recycle 参数使处于 TIME_WAIT 状态的 socket 被快速回收(默认是 2msl 时间)。

  • 注意:该参数想要正常工作,还依赖于 tcp_timestamps 选项,它要求数据包的时间戳严格顺序。所以在公网环境下,如果多 client 在同一 NAT 中,上行包的 timestamp 无法保证顺序,会出现严重问题。因此 tcp_tw_recycle 参数一般不建议打开,保持默认为 0。
net.ipv4.tcp_tw_recycle = 1

4. TIME_WAIT 快速重用 (tcp_tw_reuse)

开启处于 TIME_WAIT 状态下的 socket 快速重用,用于新的 TCP 连接。

net.ipv4.tcp_tw_reuse = 1

5. 开启 SYN Cookies

当出现 SYN 等待队列溢出时,启用 cookies 来处理。

net.ipv4.tcp_syncookies = 1

6. 监听队列大小 (somaxconn)

Web 应用中 listen 函数的 backlog 默认会给我们内核参数的 net.core.somaxconn 限制到 128,而 Nginx 定义的 NGX_LISTEN_BACKLOG 默认为 511,所以有必要调整这个值。

net.core.somaxconn = 262144

7. 网卡接收队列长度

当网卡接受数据包的速率,比 kernel 处理来的快时,即 kernel 处理跟不上包率时,cache 这些数据包的队列长度。

  • 默认值是 1k,可以适当调大到 2k 或者 4k,再大的意义不是很大,kernel 都忙不过来了,cache 再多也只能治标不治本。
net.core.netdev_max_backlog = 4096

8. 孤儿 Socket 最大数量

表示没有任何 handle 的 socket 的最大数量,通俗一点说,即不属于任何进程的 TCP socket 最大数量。超过这个数量的 socket 会被 reset,并同时告警。

  • 这个参数是为了防御简单的 DDOS 攻击,一般系统给的默认大多是 8k 或者 16k,某些防火墙会把它改成 2k。
  • 在网络特别繁忙时,为了避免大量的告警信息,也有将这个参数调大的,例如 256k。
  • 建议这个参数保持默认就好。
net.ipv4.tcp_max_orphans = 262144

9. SYN 队列最大值

记录的那些尚未收到客户端确认信息的连接请求的最大值。对于有 128M 内存的系统而言,缺省值是 1024,小内存的系统则是 128。

net.ipv4.tcp_max_syn_backlog = 262144

10. 时间戳 (tcp_timestamps)

时间戳可以避免序列号的卷绕。一个 1Gbps 的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉。

net.ipv4.tcp_timestamps = 0

11. 握手重传次数

  • tcp_syn_retries:顾名思义,即握手时 SYN 的最大重发次数,默认是 6。这是一个客户端行为,默认值是 5,在网络情况良好的情况下可以调小到 2。
  • tcp_synack_retries:是指握手时 Server 重发 ACK 的最大次数,默认是 5。这个值也可以设置到 2,来提高 Server 的效率。
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

12. FIN_WAIT_2 超时时间

TCP 连接保持在 FIN_WAIT_2 的时间,默认值是 60,这个参数可以适当调低:30 乃至更低都可以,从而减少内存的消耗。

net.ipv4.tcp_fin_timeout = 30

13. Keepalive 超时时间

当 keepalive 选项开启时,TCP 连接的超时时间,默认是 7200。为了提高效率及更高的安全性,可以调整这个参数到 1800。

  • 注意:业务不应该只依赖于 TCP 的超时机制,特别是长连接的业务,应该保证自己的心跳超时机制,来防止恶意空连接。
net.ipv4.tcp_keepalive_time = 300

14. 完整的内核优化配置示例

以下为一个完整的内核优化配置参考:

net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 16384 4194304
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 262144
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30
net.ipv4.ip_local_port_range = 1024 65000

配置生效方法

1. 修改配置文件

编辑 /etc/sysctl.conf 配置文件,添加如上内容。

2. 使配置生效

执行以下命令使配置立即生效:

[root@nginx sbin]# sysctl -p   # 配置生效

3. sysctl 命令说明

sysctl 命令用于运行时配置内核参数,这些参数位于 /proc/sys 目录下。用户只需要编辑 /etc/sysctl.conf 文件,即可手工或自动执行由 sysctl 控制的功能。

常用命令格式:

sysctl [-n] [-e] -w variable=value   # 临时改变某个指定参数的值
sysctl [-n] [-e] -p <filename>       # 从指定的文件加载系统参数 (默认 /etc/sysctl.conf)
sysctl [-n] [-e] -a                  # 显示所有的系统参数

常用参数意义:

  • -w:临时改变某个指定参数的值,如 sysctl -w net.ipv4.ip_forward=1
  • -a:显示所有的系统参数。
  • -p:从指定的文件加载系统参数,如不指定即从 /etc/sysctl.conf 中加载。

临时与永久生效:
如果仅仅是想临时改变某个系统参数的值,可以用两种方法来实现,例如想启用 IP 路由转发功能:

  1. echo 1 > /proc/sys/net/ipv4/ip_forward
  2. sysctl -w net.ipv4.ip_forward=1

以上两种方法都可能立即开启路由功能,但如果系统重启,或执行了 service network restart 命令,所设置的值即会丢失。如果想永久保留配置,可以修改 /etc/sysctl.conf 文件,将 net.ipv4.ip_forward=0 改为 net.ipv4.ip_forward=1

参考链接

说明

  • 内核版本兼容性:文中部分参数(如 net.ipv4.tcp_tw_recycle)在 Linux Kernel 4.12 及更高版本中已被移除或不再推荐使用,特别是在 NAT 环境下可能导致连接问题。请根据实际操作系统版本调整配置。
  • 时间戳设置:关闭 tcp_timestamps 可能影响某些高性能场景下的序列号回绕处理,请根据实际网络环境测试后调整。