今天不讲那些空洞的理论,拿出我项目里的真实配置,从最基本的到稍微复杂的,每个都附上踩坑记录。你跟着敲一遍,基本就能应付90%的场景了。
*图:Nginx配置结构示意图,展示http、server、location三层架构*
先看:最基础的静态资源托管
很多新手连这步都搞不定,原因是一上来就照着官网抄,结果路径搞不对。
“nginx
server {
listen 80;
server_name example.com;
# 为什么用root而不是alias?因为root会自动拼接URI路径
root /var/www/html;
# 默认首页配置
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html;
}
}
`
踩坑记录:第一次我写成了root /var/www/html/(多了个斜杠),结果所有静态资源请求都返回404。Nginx处理路径很敏感,最好不要在结尾加斜杠。
另一个坑:try_files这行的顺序很重要。$uri先检查精确文件,$uri/再检查目录,最后回退到/index.html。如果你的SPA应用刷新报404,八成是这行没配。
核心配置:反向代理与负载均衡
这是Nginx最常用的功能,也是坑最多的地方。
`nginx
upstream backend_server {
# 为什么要用least_conn?因为默认的轮询可能导致请求倾斜
least_conn;
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 backup;
# 健康检查,这个默认不开启,需要手动配
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
location /api/ {
proxy_pass http://backend_server;
<
p> # 这些header是必须的,少一个都可能出问题
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;
# 超时设置,默认60秒太长了
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
proxy_send_timeout 10s;
}
}
`
踩坑记录:有次我把proxy_set_header Host写成了$proxy_host,结果后端拿到的Host全是内网IP,认证直接崩了。官方文档这段文档不够清晰,实际调试发现$host才是浏览器的原始Host。
还有个细节:keepalive这个参数很多人不配,结果每次请求都新建TCP连接,性能直接从3.2秒掉到0.8秒。记住,负载均衡一定要配合keepalive使用。
*图:反向代理请求流程图,展示客户端请求经Nginx转发到后端服务器的完整路径*
进阶玩法:HTTPS配置
现在没HTTPS都不好意思出门,但配置起来坑更多。
`nginx
server {
listen 443 ssl http2;
server_name secure.example.com;
# 证书文件,注意路径别写错
ssl_certificate /etc/nginx/ssl/example.com.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# 这些安全配置是必选项
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
# HSTS配置,强制浏览器使用HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 这个设计真的反人类:SSL session缓存要手动开启
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location / {
proxy_pass http://backend;
}
}
HTTP自动跳转HTTPS
server {
listen 80;
server_name secure.example.com;
return 301 https://$server_name$request_uri;
}
`
踩坑记录:ssl_session_cache这行我漏配了半年,导致每次HTTPS握手都重新协商,延迟从50ms飙到200ms。这个缓存就像数据库连接池,绝对是性能关键点。
还有个坑:有些老设备不支持TLSv1.3,如果你只配了TLSv1.3,iPhone 6用户就打不开了。建议保留TLSv1.2。
性能调优:静态资源缓存
这个配置能让你的网站速度翻倍。
`nginx
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
# 为什么加这个?防止代理服务器缓存过期后还返回旧资源
add_header ETag $uri;
# 对字体文件特殊处理
location ~* \.(woff|woff2|ttf|svg)$ {
add_header Access-Control-Allow-Origin "*";
expires 1y;
}
}
对HTML不做缓存,保证内容实时性
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
`
踩坑记录:最开始我用了expires max,结果用户更新了JS文件,浏览器还加载老的,排查了好久才发现是缓存策略太激进。现在改成30天,配合文件名哈希,完美解决。
WebSocket代理
这个我调了整整一天。
`nginx
location /ws/ {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
# WebSocket必须的升级头
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 这个不加,连接60秒就断开
proxy_read_timeout 86400s;
# 限制WebSocket连接数
limit_conn addr 10;
}
`
踩坑记录:proxy_read_timeout默认60秒,WebSocket长连接直接断开。我一开始用proxy_read_timeout 0(无限),结果连接数暴涨,服务器内存爆了。后来改成86400秒(24小时),配合limit_conn控制并发,问题解决。
安全防护:防爬虫和限流
`nginx
限制同一IP的访问频率
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
封禁恶意爬虫
if ($http_user_agent ~* (python|curl|scrapy|wget|Java)) {
return 403;
}
server {
location / {
limit_req zone=mylimit burst=20 nodelay;
# IP黑名单
deny 10.0.0.0/8;
deny 192.168.0.0/16;
allow all;
}
# 防止文件遍历攻击
location ~* \.(php|asp|aspx|jsp)$ {
deny all;
}
}
`
踩坑记录:limit_req的burst参数容易被忽略。如果设置为0,超过10r/s就直接返回503。设置20的突发队列,在高峰期可以缓冲一下,用户体验好很多。
日志优化:排错必备
`nginx
自定义日志格式,包含更多调试信息
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$upstream_addr $upstream_status $upstream_response_time';
access_log /var/log/nginx/access.log detailed;
error_log /var/log/nginx/error.log warn;
对敏感API单独记录日志
location /api/payment/ {
access_log /var/log/nginx/payment.log detailed;
proxy_pass http://payment_backend;
}
`
踩坑记录:有次排查慢请求,默认日志格式没有$upstream_response_time,根本不知道是Nginx慢还是后端慢。加了这个字段后,从日志里一眼就看到了后端响应时间从100ms涨到2s,直接定位到数据库慢查询。
*图:Nginx日志分析示例,展示如何通过upstream_response_time定位性能瓶颈*
总结一下,你可以立刻用的三个点:
引入。这样出了问题,5分钟就能定位。、ssl_session_cache、expires,这三个配好了,性能翻倍。,99%的慢请求问题都能从日志里找到根因。最后提醒一句:每次修改配置后,一定要执行nginx -t检查语法,然后systemctl reload nginx`平滑重启。别问我为什么强调这个,生产环境崩过一次就知道了。