系统极客一直在努力
专注于操作系统及软件使用教程

Nginx性能优化指南

nginx-optimized-performance

Nginx 是世界知名的高性能 Web 服务器和负载均衡器,本 Nginx 性能优化指南旨在帮助大家快速进行 Nginx 服务器性能优化,以便快速向用户交付网站内容。

配置工作进程

最简单的优化便是修改工作进程和配置连接数。

工作进程

一般来说,设置成 CPU 核的数量即可,另外不要忘了设置 worker_cpu_affinity,这个配置用于将 worker process 与指定 CPU 核绑定,降低由于多 CPU 核切换造成的寄存器等重建带来的性能损耗。(打酱油的挨踢民工提示:worker_cpu_affinity一般要设置,绑定cpu核心,避免因为频繁的cpu核切换而引起的等待时间。一般来说,空出前面1-2个核心。)

如果你网站流量较大或 Nginx 作为单服务器运行,便可以为每 CPU 核心分配 Worker,worker_processes auto;(打酱油的挨踢民工提示:worker_processes auto这个是不建议的,最好是设置成固定数值)

如果你不想自动配置而要手动设置的话,可以使用如下命令查看 CPU 核心数并更改 worker_processes 数量。

grep ^processor /proc/cpuinfo | wc –l

Worker连接数

worker_connections 设置可以配置每 Worker 进程在同一时间的最大连接数。默认情况下,Worker 连接数被限制为 512,但事实上系统可以处理更多在连接。

  • 在纯 Nginx 下,Web 服务器的最大访问客户数 max clients = worker_processes 乘以 worker_connections。
  • Nginx 作为反向代理的时候 max clients = worker_processes 乘以 worker_connections 再除以 4。

Worker 连接数设置为多少其实可以通过查看系统核心的限制找到,只需使用如下命令即可:

ulimit –n

我们还可以设置使用 use epoll 机制,对于 Linux 2.6+ 系统来说选择 epoll,每个线程可以服务更多的客户端。

最后,我们可以使用 multi_accept 告诉 Nginx 收到一个新连接通知后接受尽可能多的连接。(打酱油的挨踢民工提示:在设置了 accept_mutex on后,最好设置下accept_mutex_delay 50ms;

以上事件机制配置好之后 /etc/nginx/nginx.conf 配置文件类似如下:

events {
    worker_connections 66536;
    use epoll;
    multi_accept on;
}

HTTP和TCP优化

Keep Alive

Keep Alive 可以实现客户端浏览器较少的重连:

  • keepalive_timeoutkeepalive_requests 用于控制客户端keep-alivekeep-alive设置
  • sendfile 可以让sendfile()发挥作用,sendfile()可以在磁盘和 TCP Socket 之间互相拷贝数据(或任意两个文件描述符)。(打酱油的挨踢民工提示:是否启用sendfile 需要根据文件系统格式来考虑,比如现在linux引入的zfs,就要务必关闭sendfile.)
  • tcp_nodelay 用于告诉 Nginx 不要缓存数据,而是一段一段的发送。
  • tcp_nopush 告诉 Nginx 在一个数据包里发送所有头文件,而不一个接一个的发送。

配置好之后 /etc/nginx/nginx.conf 配置文件类似如下:

keepalive_timeout 65;
keepalive_requests 100000;
sendfile on;
tcp_nopush on;
tcp_nodelay on;

Buffer大小

Buffer 的相关配置用于调整缓冲区大小,如果 Buffer 配置过低,Nginx 将需要写入临时文件,则会发到过多的磁盘 I/O。

  • client_body_buffer_size 设置缓冲区代理缓冲用户端请求的最大字节数,大多数客户端 buffer 来自由 POST 方式提交的表单,因此将其设置为 128K 是个不错的选择。
  • client_max_body_size 这个参数限制了上传文件的大小,默认是 1M。
  • client_header_buffer_size 配置客户端请求头部的缓冲区大小,这个可以根据系统分页大小来设置,一般一个请求头的大小不会超过 1K,不过由于一般系统分页都要大于 1K,所以这里设置为分页大小。
  • large_client_header_buffers Nginx默认会用 client_header_buffer_size 这个 buffer 来读取 header 值,如果header过大,它会使用large_client_header_buffers来读取。

配置好之后 /etc/nginx/nginx.conf 配置文件类似如下:

client_body_buffer_size      16k; (如果网站加载了waf ngx_lua,则需要设置到3m左右。)
client_max_body_size         10m;
client_header_buffer_size    1k;
large_client_header_buffers  4 4k;
output_buffers               1 32k;
postpone_output              1460;

连接队列

/etc/sysctl.conf 配置文件选项可用于优化 Nginx 服务器内核 TCP 参数。

  • net.core.somaxconn 定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数,默认值为1024。
  • net.ipv4.tcp_max_tw_buckets 表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。

配置好之后 /etc/sysctl.conf 配置文件类似如下:

net.core.somaxconn = 65536
net.ipv4.tcp_max_tw_buckets = 1440000

超时配置

超时配置其实也可以显著提高 Nginx 性能:

  • client_body_timeout HTTP 核心模块指令,用于指定读取请求实体的超时时间。这里的超时是指一个请求实体没有进入读取步骤,如果连接超过这个时间而客户端没有任何响应,Nginx 将返回一个”Request time out” (408)错误。
  • sent_timeout 指定响应客户端的超时时间,这个超时仅限于两个阅读活动之间的时间,如果这个时间后客户端没有任何活动,Nginx 将会关闭连接。
  • client_header_timeout 设置请求头的超时时间。

配置好之后 /etc/nginx/nginx.conf 配置文件类似如下:

client_header_timeout  10s;
client_body_timeout    10s;
send_timeout           10s;

gzip压缩

对于纯文本内容,Nginx 可以使用 gzip 压缩,我们可以使用如下参数指定需要压缩的类型。

配置好之后 /etc/nginx/nginx.conf 配置文件类似如下:

gzip on;
gzip_min_length 1000;
gzip_types: text/html application/x-javascript text/css application/javascript text/javascript text/plain text/xml application/json application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/xml font/eot font/opentype font/otf image/svg+xml image/vnd.microsoft.icon;
gzip_disable "MSIE [1-6]\.";

静态文件缓存

如果你的网站在大量静态资源(如CSS/JS/图片),Nginx 可以配置静态文件缓存。我们可以使用如下配置来设置缓存文件类型及缓存时间:

location ~* .(woff|eot|ttf|svg|mp4|webm|jpg|jpeg|png|gif|ico|css|js)$ {
    expires 365d;
}

文件系统优化

以下配置会提高系统对内存的管理能力,我们需要修改 /etc/sysctl.conf 配置文件。

当 Nginx 作为代理服务器使用时,每当连接到上游服务器都会使用一个临时的端口。我们可以使用如下命令将服务器本地 IPv4 端口限定在一个固定的区间:

net.ipv4.ip_local_port_range 1024 65000

修改系統默认的 TIMEOUT 时间,默认超时时间为 60 秒,我们可以将其减少为 30 秒甚至 15 秒:


net.ipv4.tcp_fin_timeout 15

设置 TCP/IP 会话的滑动窗口大小是否可变。参数值为布尔值,为 1 时表示可变,为 0 时表示不可变。TCP/IP 通常使用的窗口最大可达到 65535 字节,对于高速网络,该值可能太小,这时候如果启用了该功能,可以使 TCP/IP 滑动窗口大小增大数个数量级,从而提高数据传输的能力。

net.ipv4.tcp_window_scaling = 1

进入 SYN 包的最大请求队列,默认1024。对重负载服务器,增加该值显然有好处,可调整到2048。

net.ipv4.tcp_max_syn_backlog = 3240000

设置客户端读请求的超时时间,默认是60秒。

reset_timedout_connection on;

当然,管理员可以选择有条件的记录日志,以下配置示例将不记录 HTTP 响应代码为 2XX 和 3XX 的日志:

/etc/nginx/nginx.conf 配置文件添加

map $status $loggable {
    ~^[23]  0;
    default 1;
}

致谢

非常感谢网友打酱油的挨踢民工在评论中对本文中的错误进行指正并提出修改意见,在此表示由衷感谢。

分享到:更多 ()
      • worker_processes auto这个是不建议的,最好是设置成固定数值
        worker_cpu_affinity一般要设置,绑定cpu核心,避免因为频繁的cpu核切换而引起的等待时间。一般来说,空出前面1-2个核心。
        在设置了 accept_mutex on后,最好设置下accept_mutex_delay 50ms;

        是否启用sendfile 需要根据文件系统格式来考虑,比如现在linux引入的zfs,就要务必关闭sendfile.
        lient_body_buffer_size 128K这个实在太大了,一般来说,16k足够。但是如果网站加载了waf ngx_lua,则需要设置到3m左右。

        client_header_timeout 3m;
        client_body_timeout 3m;
        send_timeout 3m;
        这3个值我个人建议设置到10s-15s,3分钟实在是太长了