Nginx默认配置上线后,日常运行一切正常,但遇到流量洪峰就频繁出现502错误、响应延迟飙升,甚至服务器宕机。其实,Nginx的默认配置只是“通用兜底”,针对高并发、低延迟的生产场景,只要找对方向、调对参数,就能用同样的硬件资源,就能实现并发能力和响应速度的质的飞跃。一、Nginx性能瓶颈到底出在哪?
在调优之前,我们先明确核心瓶颈点,避免盲目修改参数、做无用功。Nginx的性能瓶颈主要集中在4个方面,每个瓶颈点对应明确的调优方向,且不同瓶颈在生产环境中会有明显的特征,方便我们快速定位:
进程与连接限制:Worker进程数不合理、单个进程最大连接数过低,导致CPU核心未充分利用(表现为CPU利用率低于50%但并发上不去),并发能力被人为限制;此外,进程上下文切换过于频繁(表现为CPU sy使用率过高),也会消耗大量资源,拖慢请求处理速度。
系统内核限制:Linux系统默认的文件描述符、TCP连接参数,是Nginx并发能力的“天花板”。默认情况下,系统级文件描述符限制通常为1024,TCP连接队列长度、TIME_WAIT连接回收机制等配置,在高并发场景下会直接限制Nginx的并发潜力,表现为大量连接被拒绝、TIME_WAIT连接堆积。
IO与传输开销:静态资源(图片、CSS、JS、视频等)未做缓存,导致每次请求都需要读取磁盘(表现为磁盘IO使用率过高、iowait值飙升);未启用压缩或压缩配置不合理,导致网络带宽被大量占用,响应延迟增加(表现为网络出口带宽满载,请求响应时间长)。
后端联动瓶颈(反向代理场景突出):反向代理时未优化连接复用,导致每次请求都需要与后端服务建立新的TCP连接(表现为后端服务连接数飙升、端口耗尽);未做负载均衡或负载均衡算法不合理,导致单节点过载、其他节点闲置(表现为部分后端节点CPU/内存满载,部分节点资源空闲),最终拖慢整体响应。
调优的核心逻辑:让CPU、内存、网络资源充分利用,减少不必要的IO和连接开销,让Nginx专注于“转发和响应”核心工作,同时打破系统和软件本身的限制,实现资源利用最大化。
二、基础配置调优
基础配置调优主要针对Nginx的核心进程和连接参数,无需复杂操作,仅需修改nginx.conf主配置文件即可,适合所有Nginx部署场景(无论是静态站点、API网关还是反向代理)。
1. Worker进程优化(充分利用CPU,减少上下文切换)
Nginx的Worker进程是实际处理请求的进程,Master进程仅负责管理Worker进程(启动、停止、重启),不处理具体请求。因此,Worker进程的数量和绑定方式,直接决定了CPU的利用率和请求处理效率。默认配置中worker_processes通常为1,这会导致多核心CPU资源严重浪费,即便服务器是8核CPU,也只有1个核心在处理请求。
(nginx.conf顶部配置):
nginx # Worker进程数,推荐设置为CPU逻辑核心数或auto(优先选auto) # 说明:Nginx 1.9+ 版本支持auto,会自动检测服务器CPU逻辑核心数,自动分配对应数量的Worker进程 # 注意:逻辑核心数 ≠ 物理核心数,比如4核8线程的CPU,逻辑核心数为8,需设置为8 worker_processes auto; # 手动设置示例(4核8线程CPU):worker_processes 8; # 手动设置示例(2核4线程CPU):worker_processes 4; # 可选优化:将Worker进程绑定到固定CPU核心,减少进程上下文切换开销 # 说明:进程在不同CPU核心间切换时,会消耗系统资源,绑定后每个Worker进程固定在一个核心上运行 worker_cpu_affinity auto; # 自动绑定(推荐,Nginx 1.19+ 支持) # 手动绑定示例(4核CPU,逻辑核心0-3):worker_cpu_affinity 0001 0010 0100 1000; # 手动绑定示例(8核CPU,逻辑核心0-7):worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000; |
调优原则:
CPU密集型场景(如SSL/TLS加密解密、Gzip/Brotli压缩、大量反向代理请求处理):Worker进程数严格设置为CPU逻辑核心数,避免进程过多导致上下文切换开销增加,反而降低效率。常见场景:API网关、HTTPS站点、需要频繁压缩的文本类站点。
I/O密集型场景(如静态文件代理、大文件下载、后端服务响应较慢的反向代理):可设置为CPU逻辑核心数的1.5-2倍,充分利用CPU空闲时间处理更多请求(因为I/O操作时CPU会处于空闲状态)。常见场景:静态资源服务器、视频下载站点、后端为数据库查询的API服务。
补充注意:如果服务器内存较小(如2G以下),建议Worker进程数不要过多(不超过CPU核心数),避免多个进程占用过多内存,导致系统内存不足、Swap使用率飙升。
2. 连接数优化(提升并发上限,避免连接耗尽)
Nginx的最大并发连接数由worker_processes(Worker进程数)和worker_connections(单个Worker进程最大连接数)共同决定,核心公式为:最大并发连接数 = worker_processes × worker_connections。默认情况下,worker_connections为512,即便Worker进程数为8,最大并发连接数也仅为4096,远不足以应对高并发场景(如每秒1万+请求)。
(events块配置):
nginx events { # 事件模型选择:Linux系统最优事件模型为epoll,替代默认的select/poll # 说明:select/poll模型在并发连接数较多时,会出现“句柄溢出”问题,效率急剧下降 # epoll模型支持百万级并发连接,是高并发场景的必配 use epoll; # 单个Worker进程最大连接数,推荐设置为10240及以上(根据服务器配置调整) # 说明:该值不能超过系统级文件描述符限制,后续会配合系统内核调 worker_connections 10240; # 开启后,Worker进程一次接受所有新连接,减少连接建立的开销 # 说明:默认关闭,开启后可提升高并发场景下的连接建立效率 multi_accept on; } # 配套优化:提升Nginx进程可打开的文件描述符限制 # 说明:每个TCP连接对应一个文件描述符,文件描述符不足会导致连接失败 # 取值必须大于worker_connections,设置为200000以上,预留足够冗余 worker_rlimit_nofile 200000; |
注意:
worker_connections的取值不是越大越好:单个Worker进程的连接数过多,会导致内存占用增加(每个连接约占用几KB内存),建议根据服务器内存调整,8G内存服务器可设置为10240-20480,16G内存可设置为20480-40960。
worker_rlimit_nofile必须与系统级文件描述符限制匹配:如果系统级文件描述符限制(fs.file-max)小于worker_rlimit_nofile,那么worker_rlimit_nofile的配置会失效,实际生效的是系统级限制。
multi_accept参数的适用场景:仅在高并发、短连接场景(如API接口、小程序接口)下启用效果明显,长连接场景(如WebSocket、长连接API)启用效果不明显,可根据业务场景选择是否开启。
3. HTTP连接优化
HTTP长连接(Keep-Alive)是提升Nginx性能的关键优化点之一,其核心作用是:在一次TCP连接中,处理多个HTTP请求,避免每次请求都建立和关闭TCP连接(每次TCP连接需要3次握手、4次挥手,消耗大量时间和资源)。尤其适合API网关、高频请求、短连接密集的场景,启用后可减少30%-50%的响应延迟。
(http块配置):
nginx http { # 长连接超时时间:客户端与Nginx建立长连接后,无请求的空闲时间超过该值则关闭连接 # 说明:设置过长会占用大量连接资源(导致连接耗尽),过短则失去长连接意义 # 推荐值:普通站点15-30s,API网关、高频请求场景10-15s(减少空闲连接占用) keepalive_timeout 20s; # 单个长连接上最多处理的请求数:设置越大越好,直到超时 # 说明:默认值为1000,调大后可充分利用长连接,减少连接重建次数 # 推荐值:100000以上(根据并发量调整,8G内存可设置为100000-200000) keepalive_requests 100000; # 后端连接复用(反向代理场景必配,核心优化) # 说明:反向代理时,Nginx与后端服务(如Tomcat、Node.js)建立长连接,避免每次请求都重建连接 upstream backend { server 127.0.0.1:8080; # 后端服务地址,可配置多个节点(负载均衡场景) keepalive 64; # 保持与后端服务的长连接数量,根据后端服务并发能力调整 # 补充:如果后端服务是集群,keepalive值建议设置为每个后端节点并发上限的1/5-1/3 # 示例:后端每个节点最大并发1000,3个节点,keepalive可设置为600-1000 } # 反向代理时启用HTTP/1.1协议:HTTP/1.0不支持长连接,必须启用HTTP/1.1 proxy_http_version 1.1; # 清空Connection请求头:避免客户端请求头中的Connection: close影响长连接 proxy_set_header Connection ""; } |
补充优化(针对长连接场景):
针对WebSocket场景:需额外添加配置,确保长连接不被中断,配置如下: location /ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 3600s;
# WebSocket长连接超时时间,根据业务调整 }
针对高频短连接场景:可启用keepalive_disable参数,禁止对特定浏览器(如旧版IE)启用长连接,避免无效连接占用资源: http { keepalive_disable msie6;
# 禁止IE6浏览器使用长连接 }
三、系统内核调优
Nginx的性能不仅取决于自身配置,还受Linux系统内核限制——即便Nginx配置调至最优,如果系统内核参数未优化,也无法发挥Nginx的最大潜力(比如系统文件描述符限制过低,即便Nginx配置了200000的文件描述符,实际也只能使用系统默认的1024)。系统内核调优主要修改/etc/sysctl.conf(系统内核参数配置文件)和/etc/security/limits.conf(用户级资源限制文件),修改后需执行对应命令生效,全程无需重启服务器(部分参数需重启Nginx)。
bash # /etc/sysctl.conf 核心优化参数(逐条解读,避免盲目复制) # 1. 提升系统最大文件描述符数(核心参数,解决“too many open files”错误) # 说明:系统级别的最大文件描述符限制,所有进程共享,必须大于Nginx的worker_rlimit_nofile fs.file-max = 655350 # 2. TCP连接队列优化,减少SYN洪水风险,提升连接建立效率 # net.core.somaxconn:监听队列最大长度,需大于Nginx的worker_connections # 说明:当请求量超过监听队列长度时,新的连接会被拒绝,导致502错误 net.core.somaxconn = 65535 # net.ipv4.tcp_max_syn_backlog:SYN队列长度,提升TCP连接建立效率 # 说明:TCP三次握手时,客户端发送SYN包后,服务器会将连接放入SYN队列,队列满则拒绝连接 net.ipv4.tcp_max_syn_backlog = 65535 # 3. 启用SYN Cookie,防止SYN攻击(高并发场景必配) # 说明:SYN攻击是通过发送大量SYN包,耗尽SYN队列,导致正常连接无法建立 # 启用后,服务器会生成SYN Cookie,无需占用SYN队列资源,有效抵御SYN攻击 net.ipv4.tcp_syncookies = 1 # 4. 优化TCP连接回收,减少TIME_WAIT状态连接堆积(核心优化) # net.ipv4.tcp_fin_timeout:TIME_WAIT状态连接的超时时间,默认60s,缩短为15s # 说明:TIME_WAIT状态是TCP连接关闭后,等待确认的状态,默认60s会占用大量端口和连接资源 # 缩短为15s,可快速回收连接资源,避免端口耗尽 net.ipv4.tcp_fin_timeout = 15 # net.ipv4.tcp_tw_reuse:允许TIME_WAIT状态的连接重新用于新连接(推荐开启) # 说明:开启后,可复用TIME_WAIT状态的连接,减少新连接建立的开销 net.ipv4.tcp_tw_reuse = 1 # net.ipv4.tcp_tw_recycle:快速回收TIME_WAIT连接(注意:NAT环境下不建议开启) # 说明:开启后会加速TIME_WAIT连接回收,但在NAT网络(如局域网、云服务器内网)中,可能导致连接异常 # 建议:公网服务器开启,内网NAT环境关闭 net.ipv4.tcp_tw_recycle = 1 # 5. 提升可用端口范围,避免端口耗尽(反向代理场景必配) # 说明:Nginx反向代理时,每个后端连接会占用一个本地端口,端口范围过窄会导致端口耗尽 # 默认端口范围是32768-61000,修改为1024-65535,扩大可用端口数量 net.ipv4.ip_local_port_range = 1024 65535 # 6. 优化TCP缓冲区,提升数据传输效率(大文件传输、高带宽场景必配) # net.core.wmem_default:TCP发送缓冲区默认大小(8MB) # net.core.wmem_max:TCP发送缓冲区最大大小(16MB) # net.core.rmem_default:TCP接收缓冲区默认大小(8MB) # net.core.rmem_max:TCP接收缓冲区最大大小(16MB) # 说明:缓冲区设置过大,会占用过多内存;设置过小,会导致数据传输频繁,降低效率 # 推荐值:8MB-16MB,根据服务器内存调整(16G内存可设置为16MB-32MB) net.core.wmem_default = 8388608 net.core.wmem_max = 16777216 net.core.rmem_default = 8388608 net.core.rmem_max = 16777216 # 7. 补充优化:提升TCP连接发送和接收队列大小 net.core.netdev_max_backlog = 65535 # 网络设备接收队列大小,避免数据包丢失 net.ipv4.tcp_max_tw_buckets = 5000 # TIME_WAIT连接最大数量,超过后自动清理 net.ipv4.tcp_synack_retries = 2 # SYN-ACK重试次数,默认5次,减少重试开销 |
生效命令:修改/etc/sysctl.conf后,执行以下命令让参数立即生效,无需重启服务器:
同时,需提升用户级文件描述符限制(解决Nginx进程级文件描述符不足问题),修改/etc/security/limits.conf(修改后需重启服务器或重新登录生效):
bash # /etc/security/limits.conf(用户级资源限制,针对所有用户) # * 表示所有用户,soft 表示软限制(警告阈值),hard 表示硬限制(强制阈值) # nofile 表示文件描述符限制,数值需与fs.file-max和worker_rlimit_nofile匹配 * soft nofile 655350 * hard nofile 655350 # 补充:针对Nginx进程所属用户(如nginx用户),可单独设置,更精准 # nginx soft nofile 655350 # nginx hard nofile 655350 |
验证方法:修改生效后,可通过以下命令验证配置是否生效:
查看系统级文件描述符限制:cat /proc/sys/fs/file-max,输出应为655350。
查看用户级文件描述符限制:ulimit -n,输出应为655350。
查看Nginx进程文件描述符限制:cat /proc/$(pidof nginx)/limits | grep "Max open files",输出应为655350。
四、缓存与压缩优化(降低IO,节省带宽,提升响应速度)
缓存可以减少磁盘IO(避免每次请求都读取磁盘文件),压缩可以减少网络传输量(缩小文件体积,节省带宽),两者结合能显著降低响应延迟——尤其适合静态资源(图片、CSS、JS、视频、静态HTML)较多的站点,优化后静态资源响应时间可从100ms降至10ms以内,带宽占用可减少50%-70%。本模块分为静态资源缓存、压缩优化、静态文件传输优化三个部分,层层递进,覆盖所有静态资源场景。
1. 静态资源缓存(降低磁盘IO)
Nginx可以直接缓存静态资源到内存或磁盘,缓存优先级:内存 > 磁盘,当用户请求静态资源时,Nginx先从内存中查找缓存,内存中没有再从磁盘查找,磁盘中没有再读取源文件,有效减少磁盘IO操作(磁盘IO是影响响应速度的主要瓶颈之一)。缓存配置需区分“浏览器缓存”和“Nginx本地缓存”,两者结合才能达到最佳效果。
(http块+server块结合,完整可直接套用):
nginx http { # 定义Nginx本地缓存(内存+磁盘),http块中配置,全局生效 # 路径:/data/nginx/cache(需手动创建,权限设置为nginx用户可读写) # levels:缓存目录层级,1:2表示一级目录1个字符,二级目录2个字符(推荐配置,避免单目录文件过多) # keys_zone:缓存共享内存区,名称为static_cache,大小100m(内存缓存大小) # 说明:内存缓存速度快,用于存储频繁访问的缓存键和小文件,100m可存储约10万条缓存键 # inactive:缓存文件24小时未访问则自动清理(避免缓存文件堆积,占用磁盘空间) # max_size:缓存磁盘最大容量,5g(超过后自动淘汰不常用的缓存文件,采用LRU算法) # use_temp_path:关闭临时文件路径,避免缓存文件写入临时目录后再移动(减少磁盘IO) proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=static_cache:100m inactive=24h max_size=5g use_temp_path=off; server { listen 80; server_name example.com; # 替换为自己的域名 # 静态资源缓存配置(匹配CSS、JS、图片、图标等常见静态资源) # 正则说明:~* 表示不区分大小写,\.(css|js|jpg|png|gif|ico)$ 匹配指定后缀的文件 # 可根据需求补充后缀,如:webp|svg|woff|woff2|ttf(字体文件)、mp4|mp3(视频音频文件) location ~* \.(css|js|jpg|png|gif|ico|webp|svg|woff|woff2|ttf)$ { root /usr/share/nginx/html; # 静态资源根目录,替换为自己的资源路径 expires 30d; # 浏览器缓存时间,30天(静态资源不常更新,建议设置15-30天) # 补充浏览器缓存头,增强缓存效果,与expires配合使用 add_header Cache-Control "public, max-age=2592000, immutable"; # public:允许浏览器和中间代理(如CDN)缓存 # max-age=2592000:缓存有效时间(30天,单位秒) # immutable:告知浏览器,缓存文件不会变化,无需再次验证(减少304请求) # 启用Nginx本地缓存,关联上面定义的static_cache proxy_cache static_cache; # 缓存生效的状态码:200(正常响应)、304(缓存命中),缓存时间10分钟 # 说明:200状态码缓存10分钟,期间相同请求直接返回缓存,无需读取磁盘 proxy_cache_valid 200 304 10m; # 缓存键:由域名+请求URI组成,确保不同域名、不同请求的缓存不冲突 proxy_cache_key "$host$request_uri$args"; # 补充:$args 用于匹配带参数的请求(如xxx.jpg?v=1.0),避免相同文件不同参数缓存冲突 # 响应头添加缓存状态,方便排查缓存是否生效(HIT=命中,MISS=未命中,EXPIRED=已过期) add_header X-Proxy-Cache "$upstream_cache_status"; # 可选:缓存未命中时,不将后端响应(磁盘读取结果)存入缓存(适合高频更新的静态资源) # proxy_cache_min_uses 3; # 至少请求3次才存入缓存 } # 大文件缓存单独配置(如视频、压缩包,避免占用过多内存) location ~* \.(mp4|mp3|zip|rar|iso)$ { root /usr/share/nginx/html; expires 7d; # 大文件更新频率低,缓存7天即可 add_header Cache-Control "public, max-age=604800"; proxy_cache static_cache; proxy_cache_valid 200 304 1h; # 大文件缓存时间缩短为1小时,减少磁盘占用 proxy_cache_key "$host$request_uri$args"; add_header X-Proxy-Cache "$upstream_cache_status"; # 启用大文件分段传输,提升下载速度 proxy_buffering on; proxy_buffer_size 128k; proxy_buffers 4 256k; } } } |
细节与排查方法:
缓存目录创建:手动创建/data/nginx/cache,并设置权限:mkdir -p /data/nginx/cache && chown -R nginx:nginx /data/nginx/cache,否则Nginx无法写入缓存文件。
缓存生效排查:使用curl -I 静态资源URL,查看响应头: - 存在Cache-Control: public, max-age=2592000, immutable,说明浏览器缓存生效; - 存在X-Proxy-Cache: HIT,说明Nginx本地缓存命中; - 若为X-Proxy-Cache: MISS,说明未命中,可检查缓存配置或请求是否符合正则匹配。
缓存清理:如需手动清理缓存,直接删除缓存目录下的文件即可:rm -rf /data/nginx/cache/*,删除后Nginx会重新生成缓存。
2. Gzip/Brotli压缩(节省带宽,提升加载速度)
启用压缩后,文本类资源(HTML、CSS、JS、JSON、XML)体积可缩小50%-70%,图片类资源(PNG、JPG)可缩小10%-30%,大幅减少网络传输时间,尤其适合带宽有限的场景(如云服务器按带宽计费)。推荐同时启用Gzip和Brotli(Brotli压缩效果优于Gzip,压缩比更高,但需额外安装模块),Nginx会自动根据客户端支持情况选择合适的压缩方式。
nginx http { # Gzip压缩配置(Nginx默认自带,无需额外安装) gzip on; # 开启Gzip压缩(默认关闭) gzip_min_length 512; # 文件大于512字节才压缩,避免小文件压缩浪费CPU # 说明:小文件(如几十字节的图标)压缩后体积可能反而变大,因此设置最小压缩阈值 gzip_comp_level 3; # 压缩等级(1-9),3为平衡CPU和压缩效果的最优值 # 说明:等级越高,压缩比越高,但CPU占用越多,1-3级适合高并发场景,4-9级适合低并发、带宽紧张场景 gzip_types text/plain text/css application/json application/javascript text/xml image/svg+xml application/xml application/xhtml+xml; # 需压缩的文件类型 # 补充:可添加application/font-woff2(字体文件)、text/markdown(markdown文件)等,根据业务需求调整 gzip_vary on; # 向客户端发送Vary: Accept-Encoding响应头,告知客户端支持压缩 gzip_disable "MSIE [1-6]\."; # 禁止旧版IE浏览器(IE1-6)使用Gzip压缩(旧版不支持) gzip_buffers 4 16k; # 压缩缓冲区大小,4个16k缓冲区,提升压缩效率 # Brotli压缩配置(需安装ngx_brotli模块,压缩效果优于Gzip) # 安装方法(CentOS为例): # 1. 下载ngx_brotli模块源码:git clone https://github.com/google/ngx_brotli.git # 2. 重新编译Nginx,添加模块:--add-module=/path/to/ngx_brotli # 3. 重启Nginx生效 brotli on; # 开启Brotli压缩 brotli_min_length 512; # 与Gzip一致,大于512字节才压缩 brotli_comp_level 4; # 压缩等级(1-11),4为最优平衡值(比Gzip 3级压缩比高,CPU占用相当) brotli_types text/plain text/css application/json application/javascript text/xml image/svg+xml application/xml application/xhtml+xml; # 与Gzip压缩类型一致 brotli_vary on; # 与Gzip一致,发送Vary响应头 } |
压缩效果对比与排查:
压缩效果:相同文本文件,Gzip压缩比约50%-60%,Brotli压缩比约60%-70%,例如100KB的JS文件,Gzip压缩后约40KB,Brotli压缩后约30KB。
生效排查:使用curl -I -H "Accept-Encoding: gzip, br" 资源URL,查看响应头: - 若存在Content-Encoding: br,说明Brotli压缩生效; - 若存在Content-Encoding: gzip,说明Gzip压缩生效; - 若不存在该响应头,说明压缩未生效,需检查压缩配置或文件类型是否匹配。
规避:不要对已经压缩的文件(如压缩包、已压缩的图片)再次压缩,会浪费CPU且无法进一步缩小体积,可在gzip_types、brotli_types中排除此类文件(如zip、rar、mp4)。
3. 静态文件传输优化(减少IO开销,提升传输效率)
启用sendfile、tcp_nopush和aio等参数,可减少磁盘IO和CPU开销,提升静态文件传输效率——尤其是大文件(如视频、压缩包)传输场景,优化后可减少30%以上的传输延迟,降低CPU和磁盘IO使用率。
nginx http { # 启用零拷贝技术(核心优化) # 说明:默认关闭,启用后,Nginx直接将文件从磁盘发送到网络,跳过内核缓冲区和用户缓冲区 # 减少数据拷贝次数(从磁盘→内核缓冲区→用户缓冲区→网络,变为磁盘→网络),大幅降低CPU和IO开销 sendfile on; # 配合sendfile,批量发送数据,减少TCP数据包数量 # 说明:启用后,Nginx会等待数据积累到一定量后再发送,减少TCP握手和数据包传输次数,提升传输效率 tcp_nopush on; # 启用异步IO(大文件传输场景必配) # 说明:默认关闭,启用后,Nginx读取磁盘文件时采用异步方式,不会阻塞请求处理 # 适合大文件(如100MB以上)传输,避免单个大文件读取阻塞其他请求 aio on; # 补充:大文件传输时,设置文件读取缓冲区大小,提升读取效率 directio 1024k; # 大于1024k的文件,采用直接IO方式读取,跳过内核缓冲区 } |
适配场景:
sendfile和tcp_nopush:适合所有静态资源场景,尤其是小文件(CSS、JS、图片),启用后可明显提升传输速度。
aio和directio:适合大文件传输场景(视频、压缩包、安装包),小文件场景启用效果不明显,甚至可能增加开销,可根据业务场景选择是否启用。
注意:aio参数仅在Linux系统支持,Windows系统不支持;directio参数需文件系统支持(如ext4、xfs)。
五、负载均衡与健康检查(提升可用性,分担后端压力)
当后端服务为集群(如多个Tomcat、Node.js、PHP-FPM节点)时,Nginx的负载均衡可以将请求分发到不同节点,避免单节点过载,同时通过健康检查,自动摘除故障节点、恢复正常节点,确保服务稳定可用。本模块分为负载均衡算法选择、健康检查配置、后端容错优化三个部分,覆盖反向代理集群的全场景优化。
1. 负载均衡算法选择(按业务场景适配,避免盲目使用默认算法)
Nginx内置4种常用负载均衡算法,还有第三方扩展算法(如fair、url_hash),不同算法适用于不同场景,需根据后端节点性能、业务需求(如会话保持)选择,核心是“让请求合理分配,避免单节点过载”。
nginx http { # 定义后端集群,名称为backend_cluster(可自定义),配置负载均衡算法 upstream backend_cluster { # 1. 轮询(默认算法):请求依次分发到每个节点,适合后端节点性能一致的场景 # 特点:简单易用,无额外配置,但无法适配节点性能不均的场景 # 适用场景:后端所有节点配置相同(如相同CPU、内存、带宽),业务无会话保持需求 # server 192.168.1.101:8080; # server 192.168.1.102:8080; # 2. 权重(weight):性能好的节点分配更高权重,适合节点性能不均场景(最常用) # 特点:权重值越高,分配到的请求越多,可根据节点性能灵活调整 # 适用场景:后端节点配置不同(如部分节点8核16G,部分节点4核8G) server 192.168.1.101:8080 weight=3; # 30%的请求分发到该节点(性能较好) server 192.168.1.102:8080 weight=2; # 20%的请求分发到该节点(性能中等) server 192.168.1.103:8080 weight=5; # 50%的请求分发到该节点(性能最好) # 补充:权重总和建议为10或100,方便计算分配比例,避免权重值过大或过小 # 3. ip_hash:根据客户端IP哈希分配,确保同一客户端始终访问同一节点(会话保持) # 特点:客户端IP不变,请求始终分发到同一个后端节点,适合需要会话保持的场景 # 适用场景:用户登录会话、购物车等需要保持会话的业务 # 注意:后端节点扩容或缩容时,会导致部分用户会话丢失(IP哈希结果变化) # ip_hash; # 4. least_conn:将请求分发到连接数最少的节点,适合后端节点负载波动大的场景 # 特点:实时监测后端节点的连接数,优先分配请求到连接数少的节点,避免单节点过载 # 适用场景:后端节点负载波动大(如部分节点突然处理大量长连接)、请求处理时间差异大的场景 # least_conn; # 补充:第三方算法(需安装对应模块) # fair:根据后端节点响应时间分配请求,响应时间越短,分配请求越多(适合对响应速度要求高的场景) # url_hash:根据请求URL哈希分配,相同URL请求始终分发到同一节点(适合静态资源缓存、API接口缓存) # 健康检查(需安装ngx_http_healthcheck_module模块,核心配置) # 说明:定期检查后端节点状态,自动摘除故障节点,恢复正常节点,避免请求发送到故障节点导致502错误 health_check interval=3s fall=2 rise=2; # 每3秒检查一次,连续2次失败则摘除,连续2次成功则恢复 # interval:检查间隔时间(3s,可根据业务调整,建议3-5s) # fall:连续失败次数,达到该次数则判定节点故障,摘除节点 # rise:连续成功次数,达到该次数则判定节点恢复,重新加入集群 # 补充:指定健康检查路径(默认检查根路径/,可自定义) health_check_uri /health; # 后端节点需提供/health接口,返回200状态码表示正常 health_check_timeout 1s; # 健康检查超时时间,1s内未响应则判定失败 } server { listen 80; server_name example.com; location / { proxy_pass http://backend_cluster; # 反向代理到后端集群 # 传递客户端真实IP和域名,方便后端服务日志排查 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 传递客户端请求的协议(http/https),方便后端服务识别 proxy_set_header X-Forwarded-Proto $scheme; } } } |
选择建议:
通用场景:优先选择权重(weight)算法,灵活适配节点性能差异,是生产环境中最常用的算法。
会话保持场景:选择ip_hash算法,或结合Redis会话共享(推荐后者,避免ip_hash的扩容问题)。
负载波动大场景:选择least_conn算法,确保节点负载均衡。
静态资源/API缓存场景:选择url_hash算法,提升缓存命中率。
2. 后端容错优化(避免后端故障导致请求失败,提升服务可用性)
即便配置了负载均衡和健康检查,后端节点仍可能出现临时故障(如网络波动、服务重启),因此需要添加后端连接超时、重试机制,避免单个节点故障导致请求失败,同时减少请求等待时间,提升用户体验。
nginx location / { proxy_pass http://backend_cluster; # 与后端建立连接的超时时间(5s,建议3-5s) # 说明:超过该时间未与后端建立连接,则判定连接失败,触发重试 proxy_connect_timeout 5s; # 读取后端响应的超时时间(10s,根据后端服务响应时间调整) # 说明:后端接收请求后,超过该时间未返回响应,则判定响应超时,触发重试 proxy_read_timeout 10s; # 向后端发送请求的超时时间(10s,建议与proxy_read_timeout一致) proxy_send_timeout 10s; # 后端节点故障时,自动切换到下一个节点(核心容错配置) # 说明:当后端节点返回error、timeout、502、503状态码时,自动将请求转发到下一个节点 proxy_next_upstream error timeout http_502 http_503; # 重试超时限制(0表示无限制,推荐0) # 说明:设置为0,只要有可用节点,就一直重试,直到请求成功或所有节点都故障 proxy_next_upstream_timeout 0; # 每个请求最多重试次数(3次,建议2-3次) # 说明:重试次数过多会增加响应时间,过少则可能错过后端节点恢复的机会 proxy_next_upstream_tries 3; # 补充:限制重试的状态码,避免无效重试 proxy_next_upstream_tries 3; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; # 可选:后端节点故障时,返回自定义错误页面,提升用户体验 error_page 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } |
注意事项:
超时时间设置:proxy_connect_timeout、proxy_read_timeout不要设置过长(如超过30s),否则会导致请求长时间等待,影响用户体验;也不要设置过短(如小于1s),否则会误判正常后端节点为故障节点。
重试次数:建议设置为2-3次,重试次数过多会导致后端服务压力增加,尤其在高并发场景下,可能引发雪崩效应。
自定义错误页面:建议配置502、503、504等错误页面,避免向用户返回默认的Nginx错误页面,提升用户体验。