Nginx 高级配置
大约 11 分钟约 3306 字
Nginx 高级配置
简介
Nginx 是当前最流行的 Web 服务器和反向代理之一,除了基本的静态文件服务和反向代理功能外,它还提供了丰富的性能优化、负载均衡策略、Lua 脚本扩展和安全加固能力。本文将深入探讨 Nginx 在生产环境中的高级配置技巧,包括性能调优参数、多种负载均衡策略、OpenResty/Lua 动态扩展以及反向代理的高级配置,帮助运维工程师构建高性能、高可用的 Web 服务架构。
特点
性能优化配置
Nginx 的性能优化涉及工作进程、连接处理、缓冲区和缓存等多个方面。
# nginx.conf - 主配置文件性能优化
# 工作进程配置
worker_processes auto; # 自动匹配 CPU 核心数
worker_cpu_affinity auto; # 自动绑定 CPU 亲和性
worker_rlimit_nofile 65535; # 提高文件描述符限制
# 事件模块优化
events {
worker_connections 4096; # 单个 worker 最大连接数
multi_accept on; # 一次性接受所有新连接
accept_mutex off; # 关闭互斥锁(高并发下提升性能)
use epoll; # Linux 使用 epoll 事件模型
}
http {
include mime.types;
default_type application/octet-stream;
# 基础优化
sendfile on; # 零拷贝发送文件
tcp_nopush on; # 优化数据包发送
tcp_nodelay on; # 禁用 Nagle 算法
keepalive_timeout 65; # 长连接超时
keepalive_requests 10000; # 单个长连接最大请求数
reset_timedout_connection on; # 超时后立即重置连接
# 压缩配置
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 4; # 压缩级别(1-9)
gzip_min_length 1024; # 最小压缩阈值
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/vnd.ms-fontobject
font/opentype
image/svg+xml;
# 缓冲区配置
client_body_buffer_size 128k;
client_max_body_size 50m;
client_header_buffer_size 4k;
large_client_header_buffers 4 16k;
output_buffers 1 32k;
postpone_output 1460;
# 代理缓冲配置
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 64k;
} # FastCGI 缓存配置(适用于 PHP 等动态应用)
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=FASTCGI_CACHE:100m
max_size=10g
inactive=60m
use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_valid 200 301 302 60m;
fastcgi_cache_valid 404 1m;
fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
fastcgi_cache_lock on;
fastcgi_cache_lock_timeout 5s;
# 代理缓存配置(适用于反向代理场景)
proxy_cache_path /var/cache/nginx/proxy
levels=1:2
keys_zone=PROXY_CACHE:200m
max_size=20g
inactive=60m
use_temp_path=off;
proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args";
proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
# 开启文件缓存(减少磁盘 I/O)
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# 隐藏版本号
server_tokens off;
# 包含其他配置文件
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/upstreams/*.conf;负载均衡策略
Nginx 支持多种负载均衡算法,可根据业务场景灵活选择。
# upstream 配置 - 多种负载均衡策略
# 1. 加权轮询(默认策略)
upstream backend_pool {
server 10.0.1.10:8080 weight=5; # 权重 5,接收更多请求
server 10.0.1.11:8080 weight=3; # 权重 3
server 10.0.1.12:8080 weight=2; # 权重 2
server 10.0.1.13:8080 backup; # 备用服务器,其他都不可用时启用
keepalive 32; # 保持 32 个空闲长连接
}
# 2. 最少连接策略
upstream api_pool {
least_conn; # 将请求分配给连接数最少的服务器
server 10.0.2.10:8080 weight=3 max_fails=3 fail_timeout=30s;
server 10.0.2.11:8080 weight=3 max_fails=3 fail_timeout=30s;
server 10.0.2.12:8080 weight=2 max_fails=3 fail_timeout=30s;
keepalive 64;
}
# 3. IP 哈希策略(会话保持)
upstream websocket_pool {
ip_hash; # 同一 IP 始终路由到同一后端
server 10.0.3.10:8080;
server 10.0.3.11:8080;
server 10.0.3.12:8080;
}
# 4. 一致性哈希策略(需要第三方模块)
upstream cache_pool {
hash $request_uri consistent; # 基于 URI 的一致性哈希
server 10.0.4.10:8080;
server 10.0.4.11:8080;
server 10.0.4.12:8080;
}
# 5. 带健康检查的负载均衡(nginx-plus 或 tengine)
upstream health_checked_pool {
# 健康检查配置
check interval=3000 rise=2 fall=3 timeout=1000 type=http;
check_http_send "HEAD /healthz HTTP/1.0\r\nHost: backend\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
server 10.0.5.10:8080;
server 10.0.5.11:8080;
}# 负载均衡 server 配置
server {
listen 80;
server_name api.example.com;
location /api/ {
proxy_pass http://api_pool;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 连接超时配置
proxy_connect_timeout 5s;
proxy_send_timeout 30s;
proxy_read_timeout 60s;
# 自定义错误响应
error_page 502 503 504 /50x.html;
}
# WebSocket 代理
location /ws/ {
proxy_pass http://websocket_pool;
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;
proxy_send_timeout 3600s;
}
}Lua 扩展(OpenResty)
通过 OpenResty 和 Lua 脚本,可以在 Nginx 中实现动态路由、访问控制等高级功能。
# OpenResty Lua 扩展配置
# 在 http 块中配置 Lua 模块路径
lua_package_path "/etc/nginx/lua/?.lua;;";
lua_shared_dict rate_limit 10m;
lua_shared_dict config_cache 5m;
# 初始化阶段:加载配置
init_worker_by_lua_block {
local config = require "config_loader"
config.init()
-- 定时刷新后端服务器列表
local function refresh_backends(premature)
if premature then return end
local http = require "resty.http"
local httpc = http.new()
local res, err = httpc:request_uri("http://config-service:8080/backends", {
method = "GET",
timeout = 5000,
})
if res and res.status == 200 then
local cjson = require "cjson.safe"
local backends = cjson.decode(res.body)
if backends then
local dict = ngx.shared.config_cache
dict:set("backends", res.body, 60)
end
end
-- 每 30 秒刷新一次
ngx.timer.at(30, refresh_backends)
end
ngx.timer.at(0, refresh_backends)
}# 动态路由和访问控制
server {
listen 80;
server_name app.example.com;
# 基于请求头的动态路由
location /api/ {
access_by_lua_block {
local cjson = require "cjson.safe"
local dict = ngx.shared.config_cache
-- 1. JWT Token 验证
local auth_header = ngx.var.http_authorization
if not auth_header then
ngx.status = 401
ngx.say('{"error":"Missing authorization header"}')
ngx.exit(401)
end
local jwt = require "resty.jwt"
local jwt_obj = jwt:verify("my-secret-key", auth_header)
if not jwt_obj.verified then
ngx.status = 403
ngx.say('{"error":"Invalid token"}')
ngx.exit(403)
end
-- 将用户信息传递给后端
ngx.req.set_header("X-User-Id", jwt_obj.payload.sub)
ngx.req.set_header("X-User-Role", jwt_obj.payload.role)
-- 2. 简易速率限制
local limit = require "resty.limit.req"
local lim, err = limit.new("rate_limit", 100, 50) -- 100r/s, burst 50
local key = ngx.var.remote_addr
local delay, err = lim:incoming(key, true)
if not delay then
if err == "rejected" then
ngx.status = 429
ngx.say('{"error":"Too many requests"}')
ngx.exit(429)
end
end
}
proxy_pass http://api_pool;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}反向代理高级配置
# 反向代理安全加固
server {
listen 443 ssl http2;
server_name secure.example.com;
# SSL/TLS 配置
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# 安全响应头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline';" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 速率限制
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;
# API 代理
location /api/ {
limit_req zone=api_limit burst=200 nodelay;
proxy_pass http://api_pool;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
# CORS 配置
add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
add_header Access-Control-Max-Age 3600 always;
if ($request_method = OPTIONS) {
return 204;
}
}
# 登录接口额外限流
location /api/auth/login {
limit_req zone=login_limit burst=3 nodelay;
proxy_pass http://api_pool;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 静态资源(带缓存)
location /static/ {
alias /var/www/static/;
expires 30d;
add_header Cache-Control "public, immutable";
# 开启 Brotli 压缩(需要模块)
# brotli on;
# brotli_comp_level 6;
}
# 健康检查端点
location /healthz {
access_log off;
return 200 "OK";
add_header Content-Type text/plain;
}
}优点
缺点
总结
Nginx 凭借其事件驱动的异步架构和丰富的功能模块,在 Web 服务器和反向代理领域占据着不可替代的地位。通过合理配置 worker 进程、连接参数和缓冲区,可以充分发挥 Nginx 的性能优势;多种负载均衡策略满足不同的业务需求;OpenResty/Lua 扩展机制更是将 Nginx 的能力从静态代理提升到可编程的流量管理平台。掌握这些高级配置技巧,对于构建高性能、高可用的 Web 服务架构至关重要。
关键知识点
- DevOps 主题的核心是让交付更快、更稳、更可审计。
- 自动化不是把命令脚本化,而是把失败、回滚、权限和观测一起设计进去。
- 生产链路必须明确制品、环境、凭据、配置和责任边界。
项目落地视角
- 把流水线拆成构建、测试、制品、部署、验证和回滚几个阶段。
- 为关键步骤补齐日志、指标、通知和人工兜底点。
- 定期演练扩容、回滚、故障注入和灾备切换。
常见误区
- 只关注部署成功,不关注失败恢复和审计追踪。
- 把环境差异藏在临时脚本或人工操作里。
- 上线频率高了以后,没有标准化制品和配置管理。
进阶路线
- 继续补齐 GitOps、可观测性、平台工程和成本治理。
- 把主题和应用架构、安全、权限、备份恢复联动起来理解。
- 形成团队级平台能力,而不是每个项目重复造轮子。
适用场景
- 当你准备把《Nginx 高级配置》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合构建自动化交付、基础设施治理、监控告警和生产发布体系。
- 当团队规模扩大、发布频率提升或环境变多时,这类主题会显著影响交付效率。
落地建议
- 所有自动化流程尽量做到幂等、可审计、可回滚。
- 把制品、变量、凭据和执行权限分层管理。
- 定期演练扩容、回滚、密钥轮换和灾备恢复。
排错清单
- 先定位失败发生在代码、构建、制品、环境还是权限层。
- 检查流水线变量、凭据、镜像标签和目标环境配置是否一致。
- 如果问题偶发,重点看并发发布、资源争抢和外部依赖抖动。
复盘问题
- 如果把《Nginx 高级配置》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《Nginx 高级配置》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《Nginx 高级配置》最大的收益和代价分别是什么?
日志与调试配置
Nginx 日志是排查问题的关键。合理的日志配置可以既不遗漏关键信息,又不浪费磁盘空间。
# 日志格式定义
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct=$upstream_connect_time '
'uht=$upstream_header_time urt=$upstream_response_time';
log_format json_combined escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request_method":"$request_method",'
'"request_uri":"$request_uri",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"upstream_response_time":"$upstream_response_time",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"x_forwarded_for":"$http_x_forwarded_for"'
'}';
# 按域名分开日志
access_log /var/log/nginx/access.log json_combined buffer=32k flush=5m;
error_log /var/log/nginx/error.log warn;
# 特定 location 关闭日志(如健康检查)
location /healthz {
access_log off;
return 200 "OK";
}安全加固进阶
除了基本的 SSL 和安全头配置外,还需要考虑更多安全防护措施。
# 防止恶意请求
server {
listen 80;
server_name _;
# 拒绝非标准域名访问
return 444;
# 限制 HTTP 方法
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$ ) {
return 405;
}
# 防止 SQL 注入和 XSS 的简单规则
# 注意:Nginx 不适合做完整的 WAF,复杂场景用 ModSecurity
if ($args ~* "union.*select.*from") {
return 403;
}
if ($args ~* "concat.*\(") {
return 403;
}
if ($args ~* "<script>") {
return 403;
}
}
# 基于地理位置的访问控制(需要 GeoIP 模块)
# geoip_country /usr/share/GeoIP/GeoIP.dat;
#
# map $geoip_country_code $allowed_country {
# default yes;
# CN yes;
# US no;
# }
#
# if ($allowed_country = no) {
# return 403;
# }Nginx 性能调优检查清单
性能调优核心参数清单:
1. worker_processes auto
- 匹配 CPU 核心数,充分利用多核
2. worker_rlimit_nofile 65535
- 提高单进程文件描述符限制
- 必须小于系统 ulimit -n 值
3. worker_connections 4096
- 单个 worker 最大并发连接
- 理论最大并发 = worker_processes * worker_connections
4. sendfile on
- 零拷贝传输静态文件,减少内核态/用户态切换
5. tcp_nopush on + tcp_nodelay on
- tcp_nopush: 优化大文件发送(等数据包满再发)
- tcp_nodelay: 优化小数据实时性(立即发送)
- 两者可以同时开启
6. keepalive_timeout 65 + keepalive_requests 10000
- 复用连接减少握手开销
- 值过大会占用连接资源
7. gzip on + gzip_min_length 1024
- 压缩减少传输体积
- 太小的文件不值得压缩(压缩后可能更大)
8. open_file_cache
- 缓存频繁访问的静态文件元数据
- 减少磁盘 stat() 系统调用
9. proxy_buffering on
- 代理场景下缓冲后端响应
- 避免慢客户端拖垮后端
10. 避免在 location 中使用 if 指令
- if 会产生意外的行为("if is evil")
- 优先使用 map、try_files 或 location 匹配常用排错命令
# 检查配置语法
nginx -t
# 重新加载配置(不中断服务)
nginx -s reload
# 查看连接状态
ss -tnp | grep nginx | wc -l
# 查看实时日志
tail -f /var/log/nginx/error.log
# 分析访问日志中最频繁的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# 分析状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# 分析响应时间最慢的请求
awk '{print $NF, $7}' /var/log/nginx/access.log | sort -rn | head -20
# 查看当前连接详情(需要 stub_status 模块)
# 在 server 中配置:
# location /nginx_status {
# stub_status;
# access_log off;
# allow 127.0.0.1;
# deny all;
# }
# 然后访问 curl http://127.0.0.1/nginx_status