Nginx 性能优化实战指南

发布于:2024-03-20 · #nginx

Nginx 性能优化实战指南

Nginx 以其高并发、低内存占用著称,但默认配置往往无法发挥其最大性能。本文将从进程模型连接限制压缩传输超时控制缓冲区调整缓存策略六个维度,详细讲解 Nginx 的核心优化方案。

注意事项

  1. 修改配置前请务必备份原配置文件。
  2. 每次修改后请使用 nginx -t 测试配置语法,并使用 nginx -s reload 重载生效。
  3. 部分参数(如 ulimit)修改后需重新登录或重启服务生效。

配置nginx的work_process

最佳实践是将工作进程数设置为与 CPU 核心数一致,以充分利用多核性能。

Bash
UTF-8|2 Lines|
[root@containerd-master1 ~]# grep processor /proc/cpuinfo | wc -l
8

如果你需要修改更多的工作进程,请修改配置文件中的work_process字段

  • auto: 根据系统的CPU自动的设置工作进程数量
Nginx
UTF-8|5 Lines|
# 推荐设置为 auto,Nginx 会自动绑定到可用 CPU 核心
worker_processes auto;

# 或者手动指定具体数量 (例如 8 核)
# worker_processes 8;

最大化连接处理能力 (Worker Connections)

每个工作进程能处理的最大连接数由worker_connections决定。总最大连接数 = worker_processes × worker_connections

如果需要修改ulimit参数,请修改配置文件/etc/security/limits.conf

  • noproc 是代表最大进程数
  • nofile 是代表最大文件打开数
plaintext
UTF-8|4 Lines|
# * soft nofile <软限制>
# * hard nofile <硬限制>
* soft nofile 65535
* hard nofile 65535

说明

说明:nofile 代表最大文件打开数(连接也是文件)。修改后需重新登录用户或重启系统生效。

配置nginx当中的work_connections

plaintext
UTF-8|5 Lines|
events {
    worker_connections 65535;  # 单个进程最大连接数
    use epoll;                 # Linux 下推荐使用 epoll 模式,性能最优
    multi_accept on;           # 允许一个进程一次性接受多个新连接
}

简单的提一嘴ulimit的作用: 当进程打开的文件数目超过此限制时,该进程就会退出。

启用gzip压缩

开启 Gzip 可以显著减少传输数据量,节省带宽并加快页面加载速度,尤其对文本类资源效果明显。

Nginx
UTF-8|24 Lines|
http {
    # 开启 gzip 压缩
    gzip on;
    
    # 添加 Vary: Accept-Encoding 头,适配代理服务器
    gzip_vary on;
    
    # 仅压缩大于 10KB 的内容 (避免小文件压缩后反而变大)
    gzip_min_length 10240;
    
    # 针对哪些响应头进行压缩
    gzip_proxied expired no-cache no-store private auth;
    
    # 压缩类型 (根据实际需求扩展)
    gzip_types text/plain text/css text/xml text/javascript 
               application/x-javascript application/xml+rss 
               application/json application/javascript;
    
    # 禁用对旧版 IE 的压缩 (避免兼容性问题)
    gzip_disable "MSIE [1-6]\.";
    
    # 压缩级别 (1-9, 1最快但压缩率低, 9最慢但压缩率高, 推荐 4-6)
    gzip_comp_level 4;
}

限制nginx连接的超时

主要是为了减少打开和关闭连接时的处理器和网络开销

  • client_body_timeout: 该指令设置请求体(request body)的读超时时间。仅当在一次readstep中,没有得到请求体,就会设为超时。超时后,nginx返回HTTP状态码408
  • client_header_timeout: 指定等待client发送一个请求头的超时时间(例如
    / HTTP/1.1)仅当在一次read中,没有收到请求头,才会被记录为超时
  • keepalive_timeout: 指定了与clientkeep-alive连接超时时间,超过这个时间后,服务器会关关闭连接。
  • send_timeout: 指定客户端的响应超时时间。这个设置不会用于整个转发器,而是在两次客户端读取操作之间。如果在这段时间内,客户端没有读取任何数据,nginx就会关闭连接。
Nginx
UTF-8|6 Lines|
http {
    client_body_timeout 12s;
    client_header_timeout 12s;
    keepalive_timeout 65s;      # 浏览器默认保持时间通常为 60s+
    send_timeout 10s;
}

调整缓冲区大小

如果缓冲区设置过小,Nginx 会将数据写入临时文件,增加磁盘 I/O 开销。适当调大缓冲区可提升性能。

plaintext
UTF-8|13 Lines|
http {
    # 请求体缓冲区 (默认通常为 8k-16k,根据业务调整)
    client_body_buffer_size 10k;
    
    # 请求头缓冲区 (默认 1k,若 Header 过大可能报错 400)
    client_header_buffer_size 1k;
    
    # 允许客户端请求的最大包体大小 (防止大文件上传攻击)
    client_max_body_size 8m;
    
    # 大型请求头缓冲区 (格式: 数量 大小)。若 Header 很大,会分配更多 buffer
    large_client_header_buffers 4 4k;
}

启用日志访问缓冲区

日志很重要,因为它们有助于解决问题。完全禁用日志不是一个好的做法。在这种情况下,您可以启用访问日志缓冲。这将允许nginx缓冲一系列日志并将它们一次写入日志文件,而不是对每个请求应用不同的日志操作。在nginx配置文件中添加以下行以允许访问日志缓冲

Nginx
UTF-8|12 Lines|
http {
    # 定义日志格式
    log_format main ' $ remote_addr -  $ remote_user [ $ time_local] " $ request" '
                    ' $ status  $ body_bytes_sent " $ http_referer" '
                    '" $ http_user_agent" " $ http_x_forwarded_for"';

    # 开启缓冲: buffer=32k (缓冲池大小), flush=1m (最多缓冲1分钟强制刷盘)
    access_log logs/access.log main buffer=32k flush=1m;
    
    # 错误日志通常不建议缓冲,以便实时排查问题
    # error_log logs/error.log warn;
}

调整静态文件缓存

利用浏览器缓存机制,让静态资源(图片、CSS、JS)在客户端缓存,减少服务器请求压力。

Nginx
UTF-8|13 Lines|
server {
    # 匹配静态资源后缀 (不区分大小写)
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|txt) $  {
        # 设置过期时间为 90 天
        expires 90d;
        
        # 添加缓存控制头
        add_header Cache-Control "public, immutable";
        
        # 可选:禁止访问日志,减少 IO (视需求而定)
        # access_log off;
    }
}