超过 67% 的全球网站使用 Nginx 作为 Web 服务器或反向代理(W3Techs 2026 年数据),但大多数开发者对 Nginx 的理解停留在「能跑就行」的水平——复制一段网上的配置、改改端口号、祈祷不要出问题。当你遇到 WebSocket 连接莫名断开、HTTPS 证书配置不生效、或者大文件上传超时这类问题时,才意识到对 Nginx 的理解有多浅。本文将从零构建一套生产级 Nginx 配置,用真实场景和代码帮你彻底搞懂这个「Web 基础设施之王」。
🔧 一、Nginx 核心架构与反向代理
1.1 为什么需要 Nginx?
很多 Node.js 开发者会问:「我的 Express/Fastify 应用已经能监听端口了,为什么还要在前面加一层 Nginx?」答案很简单:Nginx 做的事情,你的应用框架做不好也做不到。
| 能力 | Node.js 原生 | Nginx | 推荐方案 |
|---|---|---|---|
| 静态文件服务 | ⚠️ 能做但慢 | ✅ 极快(零拷贝) | Nginx |
| HTTPS 终止 | ⚠️ 需要代码配置 | ✅ 原生支持 | Nginx |
| 负载均衡 | ❌ 不支持 | ✅ 多种策略 | Nginx |
| 请求限流 | ⚠️ 需要额外库 | ✅ 内置模块 | Nginx |
| WebSocket 代理 | ❌ 不适用 | ✅ 原生支持 | Nginx |
| 连接管理 | ⚠️ 单进程 | ✅ 事件驱动 | Nginx |
📌 记住: Nginx 的事件驱动架构让它可以用极少的内存(通常 < 50MB)处理数万并发连接,而每个 Node.js 进程的内存开销通常在 100-500MB。Nginx 是你应用的第一道防线,也是性能的第一层保障。
1.2 反向代理基础配置
反向代理(Reverse Proxy)是 Nginx 最核心的功能——它接收客户端请求,转发给后端应用服务器,再把响应返回给客户端。客户端完全不知道后端服务器的存在。
# /etc/nginx/conf.d/app.conf — 基础反向代理配置
server {
listen 80;
server_name jsjson.com www.jsjson.com;
# 请求体大小限制(大文件上传场景需要调大)
client_max_body_size 50m;
# 代理超时设置(防止长请求被断开)
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
location / {
# 转发请求到后端 Node.js 应用
proxy_pass http://127.0.0.1:3000;
# ⚠️ 必须设置的代理头——否则后端拿不到真实 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;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
⚠️ 警告:
proxy_set_header X-Real-IP $remote_addr是最容易遗漏的配置。没有它,你的 Node.js 应用通过req.ip获取到的永远是127.0.0.1,导致 IP 限流、地理定位和日志审计全部失效。
1.3 静态资源分离
Nginx 处理静态文件的性能是 Node.js 的 10-50 倍。正确的做法是让 Nginx 直接服务静态资源,只把动态请求转发给后端:
# 静态资源由 Nginx 直接服务(绕过 Node.js)
location /static/ {
alias /var/www/jsjson/public/;
# 缓存 30 天(配合文件名哈希实现长期缓存)
expires 30d;
add_header Cache-Control "public, immutable";
# 启用 Gzip 压缩
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_min_length 1024;
}
# 图片资源单独配置更长的缓存
location ~* \.(png|jpg|jpeg|gif|ico|webp|avif)$ {
root /var/www/jsjson/public;
expires 365d;
add_header Cache-Control "public, immutable";
# 禁止访问隐藏文件
access_log off;
}
🚀 二、HTTPS、负载均衡与 WebSocket
2.1 HTTPS 配置(Let’s Encrypt 自动续期)
2026 年,HTTPS 不是可选项,而是基本要求。Google Chrome 会直接标记 HTTP 站点为「不安全」,而 Let’s Encrypt 提供免费的 SSL 证书。以下是生产级的 HTTPS 配置:
# /etc/nginx/conf.d/ssl.conf — 完整 HTTPS 配置
server {
listen 443 ssl http2;
server_name jsjson.com www.jsjson.com;
# SSL 证书路径(Certbot 自动生成)
ssl_certificate /etc/letsencrypt/live/jsjson.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/jsjson.com/privkey.pem;
# SSL 安全配置(2026 年推荐值)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS — 告诉浏览器只用 HTTPS 访问(慎用,开启后难以回退)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
# OCSP Stapling — 加速 SSL 握手
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
# SSL Session 缓存 — 减少握手开销
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
# HTTP → HTTPS 强制跳转
server {
listen 80;
server_name jsjson.com www.jsjson.com;
return 301 https://$host$request_uri;
}
💡 提示: Let’s Encrypt 证书有效期只有 90 天,但 Certbot 会自动设置续期定时任务。安装后用
sudo certbot renew --dry-run测试自动续期是否正常工作。
Let’s Encrypt 一键安装命令:
# Ubuntu/Debian 一键安装 Certbot 并申请证书
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d jsjson.com -d www.jsjson.com
# 测试自动续期
sudo certbot renew --dry-run
2.2 负载均衡配置
当单台服务器无法承载所有流量时,Nginx 可以将请求分发到多个后端实例。以下是三种常见策略的对比:
| 策略 | 配置方式 | 适用场景 | 特点 |
|---|---|---|---|
| 轮询(Round Robin) | 默认策略 | 服务器配置相同 | 简单均匀分配 |
| 加权轮询 | weight=N |
服务器配置不同 | 按权重分配 |
| IP Hash | ip_hash |
需要会话保持 | 同一 IP 始终访问同一后端 |
| 最少连接 | least_conn |
请求处理时间差异大 | 分配给连接数最少的服务器 |
# /etc/nginx/conf.d/upstream.conf — 负载均衡配置
upstream app_backend {
# 最少连接策略(推荐大多数场景)
least_conn;
# 后端服务器列表(weight 表示权重)
server 127.0.0.1:3000 weight=3; # 高配服务器,权重 3
server 127.0.0.1:3001 weight=2; # 中配服务器,权重 2
server 127.0.0.1:3002 weight=1; # 低配服务器,权重 1
# 备用服务器(只在其他服务器全挂时启用)
server 127.0.0.1:3003 backup;
# Keep-Alive 连接池(减少 TCP 握手开销)
keepalive 32;
}
server {
listen 443 ssl http2;
server_name jsjson.com;
# SSL 配置省略(同上)
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # 启用 keepalive 的关键配置
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_next_upstream error timeout http_502 http_503;
proxy_next_upstream_tries 2; # 最多重试 2 次
}
}
⚠️ 警告:
proxy_set_header Connection ""是启用 upstream keepalive 的必须配置。没有它,Nginx 会把客户端的Connection: close头透传给后端,导致 keepalive 失效。这是 Nginx 配置中最容易遗漏的「隐形杀手」。
2.3 WebSocket 代理配置
WebSocket 连接需要 HTTP 升级(Upgrade),默认的 Nginx 配置会缓冲响应导致连接失败或消息延迟:
# WebSocket 代理配置
location /ws/ {
proxy_pass http://127.0.0.1:3000;
# WebSocket 必须的三行配置
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# WebSocket 超时设置(默认 60s 太短)
proxy_read_timeout 3600s; # 1 小时
proxy_send_timeout 3600s;
# 客户端真实 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 API 和 WebSocket 在同一个域名下,可以用
map指令根据请求头自动选择连接类型,而不是写两个location块:
# 根据 Upgrade 头自动切换连接类型
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
💡 三、安全加固与性能优化
3.1 安全头配置
HTTP 安全头是防御 XSS、点击劫持、MIME 嗅探等攻击的第一道防线。以下是经过生产验证的完整安全头配置:
# /etc/nginx/snippets/security-headers.conf
# 可以在 server 块中用 include 引入
# 防止 MIME 类型嗅探
add_header X-Content-Type-Options "nosniff" always;
# 防止点击劫持
add_header X-Frame-Options "SAMEORIGIN" always;
# XSS 过滤器(现代浏览器已内置,但仍建议开启)
add_header X-XSS-Protection "1; mode=block" always;
# Referrer 策略 — 防止 URL 中的敏感信息泄露
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 权限策略 — 禁用不需要的浏览器 API
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# 内容安全策略(CSP)— 根据实际资源域名调整
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.jsjson.com;" always;
# 隐藏 Nginx 版本号(减少攻击面)
server_tokens off;
⚠️ 警告: CSP(Content Security Policy)是最强大但也最容易「翻车」的安全头。错误的 CSP 配置会导致页面样式丢失、脚本不执行、字体加载失败。建议先用
Content-Security-Policy-Report-Only模式观察一周,确认没有误伤后再切换为强制模式。
3.2 限流配置
Nginx 内置的 limit_req 模块可以有效防御 DDoS 和暴力破解攻击,而且零额外依赖:
# 定义限流区域(放在 http 块中)
# zone=api:10m 表示共享内存区域名为 api,大小 10MB
# rate=10r/s 表示每秒允许 10 个请求
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
# API 限流
location /api/ {
# burst=20 允许突发 20 个请求
# nodelay 不延迟处理突发请求(直接处理,超出则拒绝)
limit_req zone=api burst=20 nodelay;
# 自定义限流错误页面
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 登录接口严格限流(防暴力破解)
location /api/auth/login {
limit_req zone=login burst=3 nodelay;
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
💡 提示:
$binary_remote_addr比$remote_addr更节省内存——它将 IP 地址存储为固定 16 字节(IPv4)或 32 字节(IPv6),而$remote_addr存储为字符串,空间开销大 3-5 倍。10MB 的共享内存可以存储约 16 万个 IPv4 地址。
3.3 Gzip 与 Brotli 压缩
压缩是提升页面加载速度最简单有效的手段。Nginx 原生支持 Gzip,Brotli 需要额外模块但压缩率更高:
# Gzip 压缩(Nginx 原生支持)
gzip on;
gzip_vary on; # 添加 Vary: Accept-Encoding 头
gzip_proxied any;
gzip_comp_level 6; # 压缩级别 1-9,6 是性价比最高点
gzip_min_length 1024; # 小于 1KB 的文件不压缩
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml
font/woff2;
# Brotli 压缩(需要 ngx_brotli 模块)
# 安装:sudo apt install libnginx-mod-brotli
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/javascript application/json image/svg+xml;
| 压缩算法 | 压缩率 | 压缩速度 | 解压速度 | 浏览器支持 |
|---|---|---|---|---|
| Gzip (level 6) | 基准 | 快 | 快 | 100% |
| Brotli (level 6) | 比 Gzip 小 15-20% | 较慢 | 快 | 96% |
| Brotli (level 11) | 比 Gzip 小 25-30% | 很慢 | 快 | 96% |
⚡ 关键结论: 生产环境推荐 Gzip 作为兜底 + Brotli 作为首选。Brotli 的压缩时间比 Gzip 慢 3-5 倍,但传输体积小 15-20%。对于静态资源,建议在构建阶段用 Brotli 最高级别预压缩,运行时用 Gzip 处理动态内容。
3.4 完整的生产配置模板
将以上所有配置组合在一起,就是一个可以直接使用的生产级 Nginx 配置:
# /etc/nginx/nginx.conf — 主配置文件
user www-data;
worker_processes auto; # 自动匹配 CPU 核心数
worker_rlimit_nofile 65535; # 最大文件描述符
events {
worker_connections 4096;
multi_accept on;
use epoll; # Linux 高性能事件模型
}
http {
# 基础设置
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# MIME 类型
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式(包含请求耗时,便于性能分析)
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
# 限流区域定义
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# 引入站点配置
include /etc/nginx/conf.d/*.conf;
}
✅ 总结与最佳实践
Nginx 的配置看似简单,但每一个指令背后都有性能和安全的考量。核心要点回顾:
- ✅ 永远在 Node.js 前面加 Nginx — 静态文件、HTTPS、限流、负载均衡,这些都不是应用框架该做的事
- ✅ 必须设置代理头 —
X-Real-IP、X-Forwarded-For、X-Forwarded-Proto三个头缺一不可 - ✅ WebSocket 需要特殊配置 —
Upgrade、Connection、proxy_read_timeout三件套 - ✅ 安全头不能少 — CSP、HSTS、X-Frame-Options 是最低要求
- ✅ 用
nginx -t测试配置 — 每次修改后先测试,再nginx -s reload热重载 - ❌ 不要在 Nginx 里写业务逻辑 — Nginx 是基础设施层,不是应用层
- ⚠️ CSP 先用 Report-Only 模式 — 直接开启强制模式大概率翻车
⚡ 关键结论: Nginx 配置的 80% 可以标准化——把上面的模板复制到你的项目中,替换域名和端口号,就能覆盖绝大多数场景。剩下 20% 的定制化(如复杂的 rewrite 规则、自定义日志格式)才需要深入学习 Nginx 的模块化语法。
相关工具推荐
| 工具 | 用途 | 链接 |
|---|---|---|
| Certbot | Let’s Encrypt 证书自动化 | certbot.eff.org |
| Nginx Config Test | 在线 Nginx 配置检查 | nginxconfig.io |
| Mozilla SSL Config | SSL 配置生成器 | ssl-config.mozilla.org |
| Nginx Amplify | Nginx 监控与分析 | amplify.nginx.com |
| wrk / hey | HTTP 压力测试工具 | github.com/wg/wrk |