总结 Nginx 与 PM2 部署架构中的常见故障模式、系统化的排查顺序、关键证据保留方法以及长期治理策略,帮助团队在故障发生时快速定位根因并减少重复性问题。

软件定制开发团队
"真正有价值的技术内容,应该能帮助客户更快判断方向、预算和落地路径。"
在 Nginx 与 PM2 配合使用的架构中,故障通常表现为以下三类:**请求无法到达应用**、**应用响应异常**、**服务间歇性不可用**。每类故障的根因可能落在网络层、代理层、进程管理层或应用代码层。排查前,建议先明确故障的影响范围:是单机故障还是集群故障?是首次部署还是变更后出现?是持续还是偶发?这些信息直接决定了排查的起点和工具选择。
一个常见的误区是,当用户反馈“502 Bad Gateway”时,运维人员直接重启 Nginx 或 PM2。这种做法可能临时恢复服务,但无法阻止问题复发。真正有效的排查,需要先收集故障时刻的系统快照,而非急于操作。
故障发生后的前 5 分钟是证据保留的关键窗口。如果条件允许,应立刻执行以下命令并保存输出:
这些数据在故障被修复后往往不再重现,但却是事后分析的根本依据。对于偶发性故障,建议在 cron 或 systemd timer 中每 5 分钟轮询一次关键指标并写入环形缓冲区,避免日志覆盖导致证据丢失。
在 SystemDo 的项目中,我们曾遇到一个案例:PM2 进程未被 OOM Killer 杀掉,但 Nginx 持续返回 502。事后分析发现是 PM2 的 `max_memory_restart` 设置过高,导致 Node.js 进程频繁进入 GC 暂停状态,而 Nginx 的超时配置又太短。如果没有保留当时的 `dmesg` 和 PM2 日志,这个根因几乎无法定位。
推荐采用“从外到内”的排查顺序,即先检查网络可达性,再检查 Nginx 配置,然后检查 PM2 进程状态,最后检查应用代码。这样做的好处是,每步都能快速排除一大类可能性。
如果本机正常但公网异常,问题大概率出在防火墙规则、安全组配置或 CDN 回源设置上。
一个容易忽略的细节是,Nginx 的 `proxy_read_timeout` 默认是 60 秒。如果 PM2 管理的应用在处理长请求时超过这个时间,Nginx 会返回 504。此时需要根据业务场景调整超时,或者优化应用响应速度。
如果进程状态频繁在 `online` 和 `errored` 之间切换,说明应用存在未捕获的异常或内存泄漏。PM2 的 `--max-memory-restart` 设置可以自动重启,但这只是治标,必须定位根本原因。
应用层的问题往往是排查的终点。例如,数据库连接池耗尽会导致请求排队,最终在 Nginx 侧表现为 502。此时 PM2 和 Nginx 均无异常,根因在应用与数据库之间的交互。
最常见的原因是 PM2 管理的应用进程崩溃或端口未监听。排查步骤:
1. 确认 PM2 进程是否存活:`pm2 list`。
2. 确认应用端口是否监听:`ss -tlnp | grep <port>`。
3. 检查 Nginx `error.log` 中是否有 `connect() failed (111: Connection refused)`。
4. 如果端口监听正常,可能是应用在处理请求时发生未捕获异常,导致进程退出。查看 PM2 日志确认。
另一个可能的原因是 Nginx 的 `proxy_pass` 指向了错误的 IP 或端口,例如在配置中写了 `127.0.0.1:3000` 但 PM2 运行在 `0.0.0.0:3001`。
说明 Nginx 成功连接了应用,但应用在超时时间内未返回响应。根因通常包括:
解决思路:先调大 `proxy_read_timeout` 确认问题是否缓解,再优化应用逻辑。如果调大后依然超时,需要分析应用内部耗时。
频繁重启会形成“崩溃-重启-崩溃”的死循环,此时 PM2 的 `max_restarts` 设置会限制重启次数,最终导致进程永久停止。建议在应用入口处添加启动依赖检查,只有在依赖服务就绪后才开始监听端口。
当请求量超过 Nginx 或 PM2 的处理能力时,会出现连接被拒绝或响应缓慢。排查方法:
长期治理方案包括:调大 `worker_connections`、启用 Nginx 的 keepalive 连接池、使用 PM2 的 cluster 模式充分利用多核 CPU。
一次故障排查完成后,应将根因转化为监控指标和配置变更。以下是推荐的长期治理措施:
Nginx 和 PM2 的配置文件应纳入 Git 管理,变更前执行 `nginx -t` 或 `pm2 restart` 的 dry-run 验证。每次部署或配置变更后,建议观察 10 分钟的日志和指标,确认无异常后再结束变更窗口。
每季度或每次重大版本发布前,使用 `wrk` 或 `ab` 对系统进行压力测试,验证 Nginx 和 PM2 在高并发下的表现。重点关注连接数、内存增长趋势和错误率。如果压力测试中出现了 502 或 504,说明现有配置或资源不足以支撑预期流量,需要提前扩容或优化。
定期组织故障演练,模拟 Nginx 配置错误、PM2 进程崩溃、磁盘满等场景,检验团队的排查能力和恢复速度。每次真实故障后,应撰写故障报告,内容包括:故障时间、影响范围、根因、恢复步骤、改进措施。这些文档是团队经验积累的核心资产。
一次常规故障排查(从报警到根因确认)的时间,取决于故障的复杂度和证据的完整度。如果证据保留充分,且团队熟悉工具,通常在 30 分钟到 2 小时内可以定位。如果故障是偶发性的,且没有日志留存,排查时间可能延长到半天甚至更长。
在人力成本方面,建议每个项目至少指定一名运维或开发人员负责故障响应,并为其准备标准化的排查清单。初期投入 1-2 天搭建监控和日志系统,后续每月约 4-8 小时用于告警调优和文档更新。对于核心业务系统,这笔投入远低于故障造成的业务损失。
在排查过程中,不要直接在 Nginx 或 PM2 的配置文件中做修改。如果需要调整参数,应先在测试环境验证,再通过 CI/CD 管道部署到生产。紧急情况下,可以使用 `nginx -s reload` 或 `pm2 reload` 实现热更新,但事后必须回填配置变更记录。
PM2 默认不会自动轮转日志,长时间运行后日志文件可能占用数十 GB 磁盘空间,导致磁盘满故障。建议配置 PM2 的日志轮转插件 `pm2-logrotate`,或使用系统级的 logrotate 工具。设置日志保留周期为 7-14 天,同时确保关键故障日志被归档到远程存储。
PM2 的 cluster 模式在 Node.js 中通过 `cluster` 模块实现,可以充分利用多核 CPU。但在某些场景下,如使用 Socket.IO 或 Server-Sent Events 时,需要额外配置 sticky session,否则请求可能被分配到错误的进程。如果应用涉及 WebSocket 或长连接,建议使用单进程模式配合 Nginx 的 `ip_hash` 负载均衡策略。
故障排查不是终点,而是系统优化的起点。每次故障都应推动监控完善、配置固化或代码改进。Nginx 与 PM2 的组合虽然成熟,但并非无懈可击,只有将排查经验转化为制度和工具,才能真正减少故障发生频率和影响范围。
对于团队而言,维护一份清晰的故障排查清单,并定期进行演练,比依赖某个“资深工程师”更可靠。因为人的记忆会衰减,而清单和监控系统可以持续运行。这也是 SystemDo 在多个项目中帮助客户建立运维体系的核心思路:让知识沉淀在流程中,而非个人头脑中。
继续了解企业数字化、SEO / GEO、AI 自动化和软件定制开发中的常见问题。