09. 运维和故障排查
1. 排障原则
遇到“网站打不开”时,从外到内逐层验证:
DNS
→ 云安全组与 UFW
→ Nginx 80/443
→ TLS 证书和虚拟主机
→ Nginx 静态文件或反向代理
→ PM2 / Express 3000
→ MySQL 3306
→ 具体 SQL 和业务代码
每一层都用一个最小命令验证。不要一开始同时重启 Nginx、PM2 和 MySQL,否则会丢失故障现场。
2. DNS 检查
dig +short airport.cxhair.cn A
若 IP 错误:检查 DNS 控制台记录和 TTL。若本地与公共 DNS 结果不同,可以分别查询:
dig @1.1.1.1 airport.cxhair.cn A
dig @8.8.8.8 airport.cxhair.cn A
DNS 正确不代表服务器端口可访问。
3. 网络和监听端口
sudo ss -lntp | grep -E ':80|:443|:3000|:3306'
sudo ufw status verbose
同时检查京东云安全组。理想状态:
- 80、443 由 Nginx 监听公网地址;
- 3000 由 Node.js 监听
127.0.0.1; - 3306 由 MySQL 监听本机或私网地址。
从本地电脑测试端口比在服务器内部更能证明公网链路。
4. Nginx 检查
sudo nginx -t
systemctl status nginx --no-pager
sudo journalctl -u nginx -n 100 --no-pager
sudo tail -n 100 /var/log/nginx/airport.error.log
sudo tail -n 100 /var/log/nginx/airport.access.log
输出完整生效配置:
sudo nginx -T
nginx -T 可能很长,可定位:
sudo nginx -T 2>&1 | grep -n "airport.cxhair.cn\|proxy_pass\|ssl_certificate"
5. TLS 检查
sudo certbot certificates
sudo certbot renew --dry-run
检查线上证书:
openssl s_client \
-connect airport.cxhair.cn:443 \
-servername airport.cxhair.cn </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
常见问题:
- SAN 没有子域名;
- Nginx 命中了另一个 server block;
- DNS 指向旧服务器;
- 证书续期成功但 Nginx 未 reload;
- 服务器时间严重错误。
6. PM2 和 Express 检查
pm2 status
pm2 describe airport-api
pm2 logs airport-api --lines 200 --nostream
curl -i http://127.0.0.1:3000/health
如果本机 3000 正常而公网 /health 失败,问题多半在 Nginx 或外层网络。如果本机 3000 失败,先查 PM2 日志和环境变量。
检查进程使用的 Node.js:
node --version
which node
pm2 report
7. MySQL 检查
systemctl status mysql --no-pager
sudo journalctl -u mysql -n 200 --no-pager
mysql -h 127.0.0.1 -u airport_app -p airportdb_training \
-e "SELECT 1 AS database_ok;"
管理员查看连接:
sudo mysql -e "SHOW FULL PROCESSLIST;"
sudo mysql -e "SHOW GLOBAL STATUS LIKE 'Threads_connected';"
不要看到慢请求就立即重启 MySQL。记录 SQL、绑定参数、数据范围和执行计划,再判断是缺少索引、范围过大、锁等待还是连接池问题。
8. 常见 HTTP 状态
404
- Nginx 404:静态路径或 SPA
try_files有问题; - Express JSON 404:请求已到后端,但路由不存在;
/api前缀丢失:检查proxy_pass尾部斜杠。
502 Bad Gateway
Nginx 无法连接 Express。检查:
pm2 status
curl -i http://127.0.0.1:3000/health
sudo ss -lntp | grep ':3000'
503 Service Unavailable
本项目 /health 在进程可用但数据库 down 时主动返回 503。读取 JSON body,区分 Nginx 自己生成的 503 和 Express 健康检查。
504 Gateway Timeout
Nginx 已连接后端,但在 proxy_read_timeout 内没有得到响应。根据 request ID 查 PM2 日志和慢 SQL。不要先把超时改成无限大。
413 Request Entity Too Large
请求体超过 Nginx 或 Express 限制。本项目是只读查询应用,通常不应上传大文件。先确认业务是否合理,再调整限制。
9. request ID 关联日志
Nginx 将 $request_id 通过 X-Request-ID 传给 Express。API 响应也返回 request_id。发生错误时:
- 从浏览器响应获取 request ID;
- 在 PM2 日志搜索该 ID;
- 在 Nginx access log 定位同一次请求;
- 查看路径、状态码、耗时和对应 SQL 日志。
可将 Nginx日志格式扩展为包含 $request_id,例如在 http 块定义:
log_format airport_main
'$remote_addr - $host [$time_local] "$request" $status $body_bytes_sent '
'request_id=$request_id request_time=$request_time '
'upstream_time=$upstream_response_time';
站点使用:
access_log /var/log/nginx/airport.access.log airport_main;
修改 /etc/nginx/nginx.conf 前备份,执行 nginx -t 后再 reload。
10. 容量检查
df -h
df -i
free -h
du -sh ~/.pm2/logs
sudo du -sh /var/log/nginx /var/lib/mysql
磁盘满会导致 MySQL、日志和部署同时失败。需要同时监控磁盘空间和 inode。
11. 定期维护
每周或每月根据项目活跃度执行:
- 检查
certbot renew --dry-run和 timer; - 检查 PM2、Nginx、MySQL 状态;
- 检查磁盘和日志轮转;
- 安装经过评估的系统安全更新;
- 在本地评估 npm 依赖更新和生产依赖审计;
- 检查只读账号授权;
- 备份数据库与配置;
- 实际演练一次恢复,不只确认备份文件存在。
依赖审计结果需要判断可利用路径和升级兼容性,不要在生产服务器直接运行破坏性 npm audit fix --force。
12. 数据库备份边界
AirportDB 可以从官方 dump 重新导入,但索引实验、性能记录和额外应用数据需要单独保存。至少备份:
- 官方 ZIP 的来源和校验值;
- 可复现导入步骤;
- 新增索引的 SQL 和回滚 SQL;
- Nginx、PM2 和环境变量清单;
- 如果未来创建
airport_appschema,则备份其中不可重建的数据。
备份中包含凭据时应加密并限制权限。
下一章:配置模板与检查清单