Nginx 核心架构包含三个主要部分:
Master 进程
管理 Worker 进程读取配置文件信号控制(启动、停止、重载)Worker 进程
处理实际客户端请求事件驱动模型(epoll / kqueue / select)模块化设计
通过模块扩展功能,如 HTTP、Stream、Mail 模块等| 模块类型 | 功能 |
|---|---|
| http | 提供 HTTP/HTTPS 服务,可作为静态服务器、反向代理、负载均衡等 |
| stream | 提供 TCP/UDP 转发和负载均衡 |
| 提供 SMTP/POP3/IMAP 邮件代理服务 | |
| event | 事件处理模块,管理连接的异步事件 |
# 启动 Nginx
sudo nginx
# 停止 Nginx
sudo nginx -s stop
# 平滑重载配置(不中断服务)
sudo nginx -s reload
# 查看 Nginx 是否运行
ps -ef | grep nginx
/etc/nginx/nginx.conf 或
/usr/local/nginx/conf/nginx.conf主要块结构:
user nginx;
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
}
}
关键点:
events:处理连接相关配置
http:处理 HTTP 请求配置
server:虚拟主机配置
location:请求路径处理规则
# CentOS / RHEL
sudo yum install nginx -y
# Ubuntu / Debian
sudo apt update
sudo apt install nginx -y
# Docker
docker run -d -p 80:80 nginx
启动 Nginx 并访问首页
sudo systemctl start nginx # 启动
sudo systemctl enable nginx # 开机自启
firefox http://localhost # 浏览器访问
验证配置文件
sudo nginx -t # 检查配置文件是否正确
server 块与
location 块server 块
定义一个虚拟主机可以配置监听端口、域名等
server {
listen 80;
server_name example.com;
root /var/www/html;
}
location 块
定义路径匹配规则用于处理不同请求路径的具体行为
location /images/ {
root /var/www/static;
}
location /api/ {
proxy_pass http://127.0.0.1:8080;
}
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
alias vs
root| 指令 | 作用 | 注意事项 |
|---|---|---|
| root | 指定请求路径的根目录 | location 中路径会追加到 root 后 |
| alias | 指定请求路径对应的目录 | location 中路径会被替换,不追加 |
# 使用 root
location /static/ {
root /var/www/html;
# /static/img.jpg => /var/www/html/static/img.jpg
}
# 使用 alias
location /static/ {
alias /var/www/html/static-files/;
# /static/img.jpg => /var/www/html/static-files/img.jpg
}
access_log
记录访问日志自定义格式示例:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log
记录错误日志
error_log /var/log/nginx/error.log warn;
sudo nginx -t
输出示例:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html/my_site;
index index.html;
}
}
创建静态目录并放置 HTML 文件:
mkdir -p /usr/share/nginx/html/my_site
echo "<h1>Hello Nginx!</h1>" > /usr/share/nginx/html/my_site/index.html
自定义 access_log 格式
log_format mylog '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
access_log /var/log/nginx/my_access.log mylog;
测试配置并重载
sudo nginx -t # 测试配置
sudo nginx -s reload # 重载配置
location 匹配方式Nginx 的
location 块匹配请求路径时,有几种方式:
=
location = /index.html {
root /var/www/html;
}
只有请求
/index.html 才会命中该 location。
location /images/ {
root /var/www/html;
}
请求
/images/pic.jpg 会匹配。
~ /
~*
~:区分大小写的正则匹配
~*:不区分大小写的正则匹配
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
}
匹配顺序如下:
精确匹配
=前缀匹配
^~(表示匹配到该前缀就停止搜索正则)正则匹配
~ /
~*(按配置顺序匹配)普通前缀匹配(最长前缀优先)
示意表:
| 类型 | 示例 | 优先级 |
|---|---|---|
| 精确匹配 |
= /index.html | 最高 |
| 前缀匹配 |
^~ /images/ | 高 |
| 正则匹配 |
~ .php$ | 中 |
| 普通前缀 |
/ | 最低 |
# 返回 301 重定向
location /old {
return 301 /new;
}
location /blog/ {
rewrite ^/blog/(.*)$ /newblog/$1 permanent;
}
常用标志:
last:内部跳转,继续匹配 location
break:停止 rewrite,直接在当前 location 执行
permanent:301 永久重定向
redirect:302 临时重定向
server {
listen 80;
server_name localhost;
# 跳转 /old -> /new
location /old {
return 301 /new;
}
location /new {
root /usr/share/nginx/html;
index index.html;
}
}
设计 3 个 location 测试优先级
server {
listen 80;
server_name localhost;
# 精确匹配
location = /test.html {
return 200 "Exact match!";
}
# 前缀匹配
location ^~ /static/ {
return 200 "Prefix match!";
}
# 正则匹配
location ~ .php$ {
return 200 "Regex match!";
}
# 普通前缀匹配
location / {
return 200 "Default match!";
}
}
测试方法:
curl http://localhost/test.html # 精确匹配
curl http://localhost/static/file # 前缀匹配
curl http://localhost/index.php # 正则匹配
curl http://localhost/anything # 普通前缀匹配
proxy_pass 的工作原理
proxy_pass 用于将客户端请求转发到后端服务器(HTTP/TCP)工作流程:
客户端发起请求 → Nginx 接收根据 location 规则匹配 → 将请求转发给后端 upstreamNginx 接收后端响应 → 返回给客户端
示例:
location /api/ {
proxy_pass http://127.0.0.1:8080;
}
upstream 基础
upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
server {
listen 80;
location /api/ {
proxy_pass http://backend;
}
}
常用负载均衡策略:
轮询(默认):轮流分配请求least_conn:最少连接数ip_hash:基于客户端 IP 分配,保证同一用户请求固定节点Host:客户端请求的域名,默认转发时保持原 Host
X-Real-IP:记录客户端真实 IP
X-Forwarded-For:记录经过的代理链路 IP
配置示例:
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
upstream backend {
server 127.0.0.1:8080;
keepalive 16; # 最多保持 16 个空闲连接
}
server {
listen 80;
location /api/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
upstream myapp {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
keepalive 16;
}
server & location 配置
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://myapp;
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_http_version 1.1;
proxy_set_header Connection "";
}
}
重载 Nginx
sudo nginx -t # 测试配置
sudo nginx -s reload # 重载生效
验证
curl -i http://localhost/
查看后端日志,确认能收到客户端真实 IP。
upstream backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
upstream backend {
ip_hash;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
upstream backend {
least_conn;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
nginx-upstream-hash
upstream backend {
hash $request_uri consistent;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
upstream myapp {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
server {
listen 80;
location / {
proxy_pass http://myapp;
}
}
测试:
curl http://localhost/ # 多次请求,轮流访问不同节点
IP 哈希(ip_hash)
upstream myapp {
ip_hash;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
测试:
curl http://localhost/ # 相同客户端 IP 总是访问同一节点
最少连接(least_conn)
upstream myapp {
least_conn;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
测试:
# 模拟多个请求,观察分配给连接最少的节点
proxy_cache
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
levels=1:2:缓存目录分层
keys_zone=my_cache:10m:缓存区域名称 + 内存大小
max_size:最大缓存大小
inactive:多久未访问被删除
在 location 中启用缓存:
location /api/ {
proxy_pass http://backend;
proxy_cache my_cache;
proxy_cache_valid 200 302 10m; # 状态码 200/302 缓存 10 分钟
proxy_cache_valid 404 1m; # 404 缓存 1 分钟
}
expires
location /images/ {
root /var/www/html;
expires 30d; # 浏览器缓存 30 天
}
也可以使用
modified:
expires modified 7d; # 文件修改后 7 天缓存
etag /
cache-control
etag on;
Cache-Control:控制浏览器缓存行为
add_header Cache-Control "public, max-age=2592000"; # 30 天
mkdir -p /tmp/nginx_cache
nginx.conf 配置
http {
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=img_cache:10m max_size=500m inactive=30m use_temp_path=off;
server {
listen 80;
server_name localhost;
# 静态图片缓存
location /images/ {
root /usr/share/nginx/html;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
# 动态接口缓存
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_cache img_cache;
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating;
}
}
}
重载配置
sudo nginx -t
sudo nginx -s reload
验证
静态图片请求:
curl -I http://localhost/images/pic.jpg
# 查看 Cache-Control 和 Expires
动态接口请求:
curl -I http://localhost/api/data
# 查看 X-Cache-Status 是否命中缓存
Nginx 代理请求时,可以设置各种超时,防止长时间阻塞。
| 指令 | 作用 | 示例 |
|---|---|---|
proxy_connect_timeout | 与后端建立 TCP 连接的超时时间 |
proxy_connect_timeout 5s; |
proxy_send_timeout | 向后端发送请求的超时时间 |
proxy_send_timeout 10s; |
proxy_read_timeout | 读取后端响应的超时时间 |
proxy_read_timeout 30s; |
max_fails +
fail_timeout 简单健康检查
upstream backend {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
}
Nginx Plus:提供主动健康检查模块,可定期探测节点可用性
proxy_next_upstream 指令,失败时切换到其他节点
location /api/ {
proxy_pass http://backend;
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
}
常用参数:
error:连接错误
timeout:连接超时
invalid_header:响应头无效
http_5xx:后端返回 5xx 错误
upstream backend {
server 127.0.0.1:8080 max_fails=2 fail_timeout=10s;
server 127.0.0.1:8081 max_fails=2 fail_timeout=10s;
}
server 配置
server {
listen 80;
server_name localhost;
location /api/ {
proxy_pass http://backend;
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
重载配置
sudo nginx -t
sudo nginx -s reload
验证
模拟一个后端挂掉:
curl -i http://localhost/api/ # Nginx 会自动切换到可用节点
查看 Nginx 日志:
tail -f /var/log/nginx/error.log
日志会显示尝试切换节点的记录
# Ubuntu / Debian 安装 Certbot
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
# 申请证书
sudo certbot --nginx -d example.com -d www.example.com
Certbot 会自动修改 Nginx 配置,并设置自动续期
证书默认路径:
/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/privkey.pem
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /var/www/html;
index index.html;
}
}
ssl_protocols:指定支持的 TLS 协议版本ssl_ciphers:指定加密算法套件
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
说明:
max-age=31536000:缓存 1 年
includeSubDomains:包含子域名
preload:可加入浏览器 HSTS 预加载列表
# HTTP 跳转到 HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com
检查 Nginx 配置:
sudo nginx -t
重载 Nginx:
sudo nginx -s reload
验证:
curl -I https://example.com
# 应该返回 200,并且使用 HTTPS
可选:手动配置 HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
浏览器访问后,HTTP 请求会自动跳转 HTTPSCertbot 会自动设置定期续期:
sudo systemctl status certbot.timer
WebSocket 需要 HTTP 升级 (Upgrade),使用
proxy_http_version 1.1
Nginx 默认是 HTTP/1.0,需要设置 HTTP/1.1 来支持长连接
关键头部:
Upgrade: websocket
Connection: Upgrade
假设后端 WebSocket 服务地址:
ws://localhost:12333
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name localhost;
location /ws/ {
proxy_pass http://localhost:12333;
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
map 指令确保
Connection 头在 Upgrade 时正确设置
proxy_set_header 保留客户端真实 IP 和 Host
| 错误 | 原因 | 解决方案 |
|---|---|---|
| 400 Bad Request | Upgrade 或 Connection 头未正确设置 | 检查
$http_upgrade、
$connection_upgrade 配置 |
| 502 Bad Gateway | 后端服务未启动或端口错误 | 确认 WebSocket 服务正常运行,端口与 proxy_pass 匹配 |
| 长时间无响应 | proxy_read_timeout 太短 | 增加
proxy_read_timeout,如
60s |
# 假设一个简单 WebSocket 服务运行在 12333 端口
node websocket_server.js
Nginx 配置
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name localhost;
location /ws/ {
proxy_pass http://localhost:12333;
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
重载 Nginx
sudo nginx -t
sudo nginx -s reload
测试
// 浏览器或 Node.js 测试客户端
const ws = new WebSocket('ws://localhost/ws/');
ws.onopen = () => console.log('Connected');
ws.onmessage = (msg) => console.log('Message:', msg.data);
确认客户端能正常连接并收发消息查看 Nginx 日志排查可能的 400 / 502 问题
add_header 详解
add_header name value [always];
always 参数确保即使响应码非 200 也添加头
| 头部 | 作用 | 示例 |
|---|---|---|
X-Frame-Options | 防止页面被 iframe 嵌套点击劫持 |
add_header X-Frame-Options SAMEORIGIN; |
Strict-Transport-Security (HSTS) | 强制浏览器使用 HTTPS |
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; |
X-Content-Type-Options | 阻止 MIME 类型嗅探 |
add_header X-Content-Type-Options nosniff; |
Content-Security-Policy | 内容安全策略 |
add_header Content-Security-Policy "default-src 'self';"; |
location /api/ {
proxy_pass http://backend;
add_header Access-Control-Allow-Origin https://example.com;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, Content-Type, Authorization";
# 处理 preflight 请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Max-Age 1728000;
add_header Content-Type text/plain;
return 204;
}
}
说明:
Access-Control-Allow-Origin:允许访问的域名
Access-Control-Allow-Methods:允许请求方法
Access-Control-Allow-Headers:允许请求头
OPTIONS 请求为浏览器预检请求
upstream backend {
server 127.0.0.1:8080;
}
server 配置
server {
listen 80;
server_name localhost;
location /api/ {
proxy_pass http://backend;
# 保留客户端真实 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;
# CORS 配置
add_header Access-Control-Allow-Origin https://client.example.com;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, Content-Type, Authorization";
if ($request_method = 'OPTIONS') {
add_header Access-Control-Max-Age 1728000;
add_header Content-Type text/plain;
return 204;
}
# 安全头
add_header X-Frame-Options SAMEORIGIN;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff;
}
}
重载 Nginx
sudo nginx -t
sudo nginx -s reload
验证
浏览器端 JS 测试跨域访问:
fetch('http://localhost/api/data')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
确认来自
https://client.example.com 的请求可以访问查看响应头是否包含
Access-Control-Allow-Origin 和安全头
| 指令 | 作用 | 示例 |
|---|---|---|
limit_req_zone | 定义请求限流的 key 和速率 |
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s; |
limit_req | 在 location 中应用请求限流 |
limit_req zone=one burst=5 nodelay; |
limit_conn_zone | 定义连接数限制的 key |
limit_conn_zone $binary_remote_addr zone=addr:10m; |
limit_conn | 在 location/server 中应用连接数限制 |
limit_conn addr 5; |
令牌桶算法(Token Bucket):
每秒生成固定速率令牌请求消耗令牌,令牌用完则拒绝或等待
limit_req 默认使用令牌桶算法
# 定义限流 zone
limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s;
server {
listen 80;
server_name localhost;
location /api/ {
proxy_pass http://backend;
# 应用限流
limit_req zone=one burst=5 nodelay;
# 保留客户端真实 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;
}
}
超过速率 20r/s,直接返回 503 Service Unavailable
limit_req_zone $binary_remote_addr zone=my_limit:10m rate=10r/s;
在 location 中应用
server {
listen 80;
server_name localhost;
location /api/ {
proxy_pass http://backend;
# 限流
limit_req zone=my_limit burst=5 nodelay;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
重载 Nginx
sudo nginx -t
sudo nginx -s reload
验证
使用
ab 或
wrk 等压测工具模拟请求:
ab -n 50 -c 20 http://localhost/api/
观察超过 10r/s 后请求返回 503
auto
worker_processes auto;
每个 worker 独立处理事件,不共享请求
events {
worker_connections 10240;
use epoll; # Linux 推荐 epoll
}
events {
worker_connections 10240;
use epoll;
multi_accept on; # 一次接受多个连接
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
client_max_body_size 50M;
}
# nginx.conf
worker_processes auto;
events {
worker_connections 65536;
use epoll;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
client_max_body_size 50M;
server {
listen 80;
server_name localhost;
location / {
root /var/www/html;
index index.html;
}
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
说明:
worker_processes auto → 利用多核 CPU
worker_connections 65536 → 每 worker 高并发
epoll + multi_accept → 高效事件处理
sendfile + tcp_nopush + tcp_nodelay → 高吞吐与低延迟
理论最大并发 =
worker_processes × worker_connections
验证方法:
ab -n 100000 -c 1000 http://localhost/
wrk -t12 -c1000 -d30s http://localhost/api/
检查是否能支撑高并发请求,CPU 和网络利用率合理
Nginx 日志分为:
access.log:记录客户端请求信息error.log:记录错误、告警、异常信息日志等级:
debug /
info /
notice /
warn /
error /
crit
查看日志:
# 实时查看
tail -f /var/log/nginx/error.log
# 查看最近 100 条
tail -n 100 /var/log/nginx/error.log
日志示例:
[error] 1234#0: *45 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.10, server: localhost, request: "GET /api/ HTTP/1.1", upstream: "http://127.0.0.1:8080/api/", host: "localhost"
分析思路:
日志等级(error、warn)client IPupstream 地址错误原因(Connection refused、timeout 等)| 状态码 | 常见原因 | 排查方法 |
|---|---|---|
| 403 Forbidden | 权限/目录配置不当 | 检查 root/alias,文件权限,SELinux |
| 404 Not Found | URL 或路径不存在 | 检查 location 配置、文件路径、alias/root 使用 |
| 500 Internal Server Error | 后端错误或脚本异常 | 检查后端服务、PHP/CGI 日志 |
| 502 Bad Gateway | 后端服务不可用 | 检查 upstream 是否启动,端口正确,超时 |
| 504 Gateway Timeout | 后端响应超时 | 检查
proxy_read_timeout、后端处理性能 |
connect() failed (111: Connection refused) while connecting to upstream
upstream timed out (110: Connection timed out)
排查步骤:
确认 upstream 节点是否运行检查防火墙 / SELinux检查端口和 IP 配置是否正确查看
proxy_connect_timeout、
proxy_read_timeout 配置检查负载均衡策略,是否某节点压力过大
nginx_error_guide.md
# Nginx 常见错误排查手册
## 1. 403 Forbidden
- 原因:
- 文件/目录权限不足
- alias/root 配置错误
- SELinux 限制
- 解决:
- `chmod 755 /var/www/html`
- 检查 alias 路径是否正确
- `setenforce 0` 测试 SELinux
## 2. 404 Not Found
- 原因:
- location 未匹配
- 文件路径不存在
- 解决:
- 检查 root/alias
- 确认文件存在
- 使用 `nginx -T` 查看最终配置
## 3. 500 Internal Server Error
- 原因:
- 后端应用出错
- 解决:
- 查看后端日志
- 检查脚本权限
## 4. 502 Bad Gateway
- 原因:
- upstream 未启动
- 端口错误
- 解决:
- 启动后端服务
- 检查 proxy_pass 地址
- 检查防火墙/SELinux
## 5. 504 Gateway Timeout
- 原因:
- 后端响应慢
- 解决:
- 增加 `proxy_read_timeout`
- 优化后端处理性能
## 6. upstream 异常
- 查看 error.log,判断节点拒绝或超时
- 检查负载均衡策略
- 使用 `curl` 测试单个节点
保存并随时更新,形成个人 Nginx 排错手册日常遇到新问题,记录原因与解决方案,逐渐完善
目标:搭建一个生产环境级 Nginx,包含 HTTPS、WebSocket、负载均衡、静态资源、限流、日志定制与性能调优。
worker_processes auto;
events {
worker_connections 65536;
use epoll;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
client_max_body_size 50M;
include 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" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# 限流
limit_req_zone $binary_remote_addr zone=my_limit:10m rate=10r/s;
upstream backend {
server 127.0.0.1:8080 max_fails=2 fail_timeout=10s;
server 127.0.0.1:8081 max_fails=2 fail_timeout=10s;
least_conn; # 可选:least_conn 或 ip_hash
}
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 静态资源
location /static/ {
root /var/www/html;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
# API 代理
location /api/ {
proxy_pass http://backend;
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_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
# 限流
limit_req zone=my_limit burst=5 nodelay;
# CORS(可选)
add_header Access-Control-Allow-Origin https://client.example.com;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, Content-Type, Authorization";
if ($request_method = 'OPTIONS') {
add_header Access-Control-Max-Age 1728000;
add_header Content-Type text/plain;
return 204;
}
}
# WebSocket 代理
location /ws/ {
proxy_pass http://localhost:12333;
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# HTTP 跳转到 HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
}
| 功能 | 配置说明 |
|---|---|
| HTTPS | SSL 证书 + HSTS |
| WebSocket |
proxy_http_version 1.1 + Upgrade/Connection |
| 负载均衡 | upstream + least_conn / ip_hash |
| 静态资源 |
/static/ + expires + Cache-Control |
| 限流 |
limit_req_zone +
limit_req |
| 日志定制 | 自定义
log_format + access_log/error_log |
| 性能调优 | worker_processes、worker_connections、epoll、sendfile、tcp_nopush、tcp_nodelay |
sudo nginx -t
重载 Nginx
sudo nginx -s reload
验证
HTTPS:
curl -I https://example.comWebSocket:测试
/ws/ 连接API:请求
/api/,检查限流、负载均衡静态资源:访问
/static/,检查缓存头日志:查看
access.log 与
error.log
这样就构建了一个 生产级 Nginx 案例,可以支撑高并发、支持 HTTPS/WebSocket,同时具备安全、限流、负载均衡和性能优化。
Nginx 是什么?
高性能 HTTP / 反向代理服务器,事件驱动、高并发Nginx 的主要模块有哪些?
http、stream、mail、eventNginx 的事件驱动模型是什么?
单进程异步非阻塞 I/Oworker_processes 和 worker_connections 的作用?
控制并发能力:worker_processes × worker_connectionsNginx 如何实现高并发?
epoll + 异步事件驱动 + 多进程Nginx 的 master 与 worker 关系?
master 管理配置和 worker,worker 处理请求Nginx 配置文件结构有哪些?
nginx.conf、conf.d/.conf、sites-enabled/.conf如何启动、停止、重载 Nginx?
nginx /
nginx -s stop /
nginx -s reload
Nginx 与 Apache 区别?
Apache 进程/线程模式,Nginx 事件驱动;Nginx 更适合高并发Nginx 支持哪些协议?
HTTP、HTTPS、WebSocket、TCP/UDP(stream)server 块和 location 块的区别?
server 控制域名监听,location 控制 URI 路径匹配root 与 alias 区别?
root 拼接 location,alias 直接替换路径location 匹配规则优先级?
精确 =,前缀 ^~,正则 /*,普通前缀rewrite 指令作用?
重写 URL,可 return 或 rewrite如何配置静态文件服务?
root/alias + index + locationaccess_log 格式如何自定义?
log_format 指令如何测试 Nginx 配置?
nginx -t
如何实现 HTTP 跳转 HTTPS?
server listen 80 + return 301如何配置 gzip 压缩?
gzip on; gzip_types text/html text/css application/json;
如何限制客户端请求体大小?
client_max_body_size
proxy_pass 的作用?
将请求代理到后端服务器如何保留客户端真实 IP?
proxy_set_header X-Real-IP $remote_addr;
upstream 配置作用?
定义后端服务器组Nginx 支持哪些负载均衡策略?
round-robin、ip_hash、least_conn、一致性哈希(第三方)proxy_connect_timeout 与 proxy_read_timeout 区别?
连接超时 vs 响应读取超时proxy_next_upstream 有哪些参数?
error、timeout、http_500、http_502、http_503、http_504如何实现失败重试?
proxy_next_upstream +
proxy_next_upstream_tries
upstream max_fails + fail_timeout 作用?
简单健康检查如何实现 WebSocket 代理?
proxy_http_version 1.1 + Upgrade/Connection
如何做请求限流?
limit_req_zone + limit_reqproxy_cache 的作用?
缓存后端响应,提高访问速度expires 与 cache-control 区别?
expires 客户端缓存时间,cache-control 更灵活etag 的作用?
验证资源是否被修改sendfile 的作用?
零拷贝传输文件tcp_nopush 与 tcp_nodelay 区别?
nopush 延迟发送,提高吞吐;nodelay 减少小包延迟keepalive 的作用?
保持长连接,提高性能worker_processes auto 为什么推荐?
自动使用 CPU 核心数multi_accept 指令作用?
一次接受多个连接,提高并发处理效率Nginx 如何实现高并发 QPS ?
worker_processes × worker_connections + epoll + sendfile/tcp优化如何监控 Nginx 性能瓶颈?
stub_status、日志分析、top/htop/netstat如何启用 HTTPS?
ssl_certificate + ssl_certificate_key + listen 443 sslHSTS 的作用?
强制浏览器使用 HTTPSX-Frame-Options 的作用?
防止点击劫持X-Content-Type-Options nosniff 作用?
阻止 MIME 类型嗅探Content-Security-Policy 用途?
限制页面加载资源来源CORS 如何配置?
add_header Access-Control-Allow-Origin + 方法/头如何防止频繁请求攻击?
limit_req + limit_connNginx error.log 中 502 错误排查?
后端未启动、端口错、超时Nginx error.log 中 504 错误排查?
后端响应慢,调整 proxy_read_timeout常用安全加固措施有哪些?
HTTPS、HSTS、X-Frame-Options、CSP、限流、日志监控