应用进程与 Nginx 协同
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read390 words

应用进程与 Nginx 协同

生产环境最稳的模式通常是:Nginx 对公网,应用只对本机开放。

协同模型

graph LR A["公网 443/80"] --> B[Nginx 反向代理] B --> C["127.0.0.1:3000 应用"] C --> D[systemd 托管进程] B --> E["/var/log/nginx/ 访问日志"] D --> F["journald 应用日志"]

完整 Nginx proxy_pass 配置块

# /etc/nginx/sites-available/myapp.conf
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
# 上传文件大小限制(默认 1M,常见原因是 413 错误)
client_max_body_size 20M;
location / {
proxy_pass         http://127.0.0.1:3000;
proxy_http_version 1.1;
# 传递真实客户端信息(应用日志/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;
# WebSocket 支持(普通 HTTP 应用可省略)
proxy_set_header Upgrade    $http_upgrade;
proxy_set_header Connection "upgrade";
# 超时设置
proxy_connect_timeout 10s;  # 连接后端超时
proxy_read_timeout    60s;  # 等待后端响应超时
proxy_send_timeout    60s;  # 向后端发送数据超时
}
# 静态文件直接由 Nginx 提供(绕过应用,性能更好)
location /static/ {
alias /opt/myapp/current/public/;
expires 7d;
add_header Cache-Control "public, immutable";
}
# 健康检查端点(不记录访问日志,减少噪音)
location /health {
proxy_pass http://127.0.0.1:3000;
access_log off;
}
}

分层排查流程(502/504 场景)

graph TD A[用户报告 502/504] --> B[curl -I https://app.example.com] B --> C{Nginx 有响应?} C -->|无响应| D[检查 Nginx 是否运行: systemctl status nginx] C -->|502/504| E[确认应用进程状态] E --> F[systemctl status myapp] F --> G{myapp 运行中?} G -->|否| H[journalctl -u myapp -n 50 查崩溃原因] G -->|是| I[确认端口监听] I --> J[ss -tulpn | grep 3000] J --> K{端口监听?} K -->|否| L[应用没有绑定正确端口,查启动日志] K -->|是| M[curl -sf http://127.0.0.1:3000/health] M --> N{本机直连通?} N -->|否| O[应用逻辑错误,查应用日志] N -->|是| P[Nginx 配置问题,nginx -t 检查语法]

快速诊断命令(60 秒版):

# 1. Nginx 状态
systemctl status nginx
# 2. 应用状态
systemctl status myapp
# 3. 应用端口监听
ss -tulpn | grep 3000
# 4. 本机直连应用
curl -sf http://127.0.0.1:3000/health && echo OK || echo FAIL
# 5. 通过 Nginx 访问
curl -sf https://app.example.com/health && echo OK || echo FAIL
# 6. 查看 Nginx 错误日志(最近 20 行)
sudo tail -20 /var/log/nginx/error.log
# 7. 查看应用日志
journalctl -u myapp -n 30 --no-pager

常见错误速查表

错误 含义 最先排查
502 Bad Gateway Nginx 连接不到后端 systemctl status myapp,应用是否崩溃
504 Gateway Timeout 后端连接超时(proxy_read_timeout 应用响应慢,查数据库/计算瓶颈
413 Request Entity Too Large 上传文件超过 client_max_body_size 增大该值或在应用层拒绝大文件
upstream connect() failed 后端端口未监听 ss -tulpn | grep 3000
connection refused 应用未启动或绑定了错误地址 curl http://127.0.0.1:3000 本机直连测试
no live upstreams 所有 upstream 节点均不健康 upstream 健康检查配置问题

应用只监听本机(安全最佳实践)

# ✅ 正确:只绑定 localhost,外部无法直接访问应用端口
# Node.js
app.listen(3000, '127.0.0.1')
# Python (Gunicorn)
gunicorn --bind 127.0.0.1:3000 app:application
# 验证:应用端口不应对外暴露
ss -tulpn | grep 3000
# 应该看到:127.0.0.1:3000(而非 0.0.0.0:3000)
# 确认防火墙不放行应用端口(3000 不需要对外)
sudo ufw status
# 应该只有 22, 80, 443 对外开放

常见误区

误区 正确做法
改完应用没验证本机端口,直接查 Nginx curl http://127.0.0.1:3000/health 确认本机直连通
应用绑定 0.0.0.0:3000,防火墙没挡 应用只绑定 127.0.0.1,由 Nginx 对外提供服务
proxy_read_timeout 用默认值 60s 长任务(报表、导出)需要调大,否则出现 504
没有传 X-Real-IP header 应用看到的 IP 始终是 127.0.0.1,IP 限流和日志失效

本节执行清单

下一章应用部署实战——正式把代码发布上去。