端口冲突引发的服务无限重启#
今天在服务器上部署智慧教育项目后端服务时,发现CPU占用异常飙升,初步检查发现3001端口有服务陷入无限重启循环。经过排查,发现是旧服务进程没有完全清理干净,导致新部署的服务无法绑定端口,PM2不断尝试重启形成了死循环。本文将详细记录这次问题的发现、排查和解决过程。
一.问题现象#
- 服务器宕机 :在部署项目后端服务时,前端页面原本能打开过一会突然又挂了
- CPU占用异常:CPU占用率飙升到95%并且居高不下
二.发现问题#
- 使用
top命令查看系统资源时,发现一个Node.js进程占用95%的CPU - 检查3001端口(后端服务端口)时发现异常
- 查看PM2服务状态显示重启次数高达6991次
- 服务日志中不断重复出现端口被占用的错误
三.问题根源分析#
问题的根本原因是端口冲突:
- 旧进程残留:之前的
smart-education-backend服务被删除后,其进程(PID 23372)没有完全终止 - 端口占用:旧进程仍然占用着3001端口
- PM2无限重启:新部署的服务通过PM2管理,尝试绑定3001端口失败
- 死循环形成:PM2检测到服务启动失败,自动重启,但每次重启都因端口冲突失败,形成无限重启循环
四.详细排查步骤#
1.检查端口占用情况#
netstat -tulpn | grep :3001bash输出结果:
tcp6 0 0 :::3001 :::\* LISTEN 23372/nodemarkdown发现3001端口被PID 23372的Node进程占用。
2.查看CPU占用最高的进程#
ps aux --sort=-%cpu | head -20bash关键发现:
- PID 23372:占用0.1% CPU(旧进程)
- PID 115121:占用95.0% CPU(PM2不断重启的新进程)
3.查看进程详细信息#
lsof -i :3001bash输出:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
MainThrea 23372 root 21u IPv6 142407 0t0 TCP \*:3001 (LISTEN)markdown确认PID 23372确实在监听3001端口。
4.检查PM2服务状态#
pm2 list
pm2 show smart-education-backendbash关键信息:
- 服务名称:
smart-education-backend - 重启次数:6991次
- 运行时间:1秒(刚启动就崩溃)
- 状态:online(但实际上无法正常工作)
5.查看服务日志#
pm2 logs smart-education-backend --lines 50bash错误日志关键内容:
Error: listen EADDRINUSE: address already in use :::3001
at Server.setupListenHandle [as _listen2] (node:net:1948:16)
at listenInCluster (node:net:2005:12)
at Server.listen (node:net:2110:7)plaintext日志明确显示端口3001已被占用。
五.问题原因总结#
| 问题环节 | 具体原因 | 影响 |
|---|---|---|
| 旧服务清理不彻底 | 删除服务时只停止了PM2管理,没有终止实际进程 | 端口被占用 |
| 部署流程不规范 | 新部署前没有检查端口占用情况 | 直接冲突 |
| PM2配置问题 | 重启策略过于激进,没有设置合理的重启间隔 | 无限循环 |
六.解决方案#
- 第一步:终止占用端口的旧进程
kill -9 23372bash- 第二步:验证端口已释放
netstat -tulpn | grep :3001
# 没有输出,表示端口已释放bash- 第三步:重启PM2服务
pm2 restart smart-education-backendbash- 第四步:验证服务正常运行
pm2 list
# 查看重启次数是否重置,状态是否稳定
netstat -tulpn | grep :3001
# 确认新进程正常监听端口
ps aux --sort=-%cpu | head -10
# 查看CPU占用是否恢复正常bash七.经验教训#
-
服务清理要彻底
- 停止服务后要检查进程是否真正终止
- 使用
ps aux | grep <服务名>确认没有残留进程
-
部署前做好检查
- 检查目标端口是否被占用
- 检查相关进程是否完全停止
-
合理配置进程管理工具
- PM2的重启策略要设置合理限制
- 添加重启延迟避免无限循环
- 设置最大重启次数限制
-
加强监控和告警
- 监控服务的重启次数
- 设置CPU占用率告警
- 定期检查服务日志
八.常用命令速查#
| 操作 | 命令 | 说明 |
|---|---|---|
| 检查端口占用 | netstat -tulpn | grep :<端口> | 查看指定端口被哪个进程占用 |
| 查看进程信息 | lsof -i :<端口> | 查看占用端口的进程详细信息 |
| 终止进程 | kill -9 <PID> | 强制终止指定进程 |
| 查看CPU占用 | ps aux --sort=-%cpu | head -20 | 查看CPU占用最高的20个进程 |
| PM2服务列表 | pm2 list | 查看PM2管理的所有服务 |
| PM2服务详情 | pm2 show <app-name> | 查看指定服务的详细信息 |
| PM2服务日志 | pm2 logs <app-name> --lines 50 | 查看服务最近50行日志 |
| 重启PM2服务 | pm2 restart <app-name> | 重启指定服务 |
| 检查服务健康 | curl http://localhost:3001/health | 检查服务是否正常响应 |
| 清理占用端口 | lsof -ti :<端口> | xargs kill -9 | 一键清理占用指定端口的所有进程 |