为什么你的 EC2 服务器会突然停止响应 —— 以及如何为 Laravel 与 Node 应用加固
Source: Dev.to
实际发生了什么?
根据内部调查,问题是由于服务器无法加载构建并导致系统卡死。当有人在 EC2 实例内部直接运行 npm run build 或 yarn build——尤其是内存只有 1–2 GB 的实例时,Node 会消耗大量内存来编译和优化前端资源。随着内存使用量的增加,服务器会出现以下情况:
- 频繁换页(Swap)
- 杀死进程
- 冻结 PHP‑FPM
- 卡住 Nginx 工作进程
- SSH 访问失效
- 所有 HTTP 请求不再响应
因为所有 Laravel 应用、Node 应用、队列工作者和套接字服务都运行在同一个操作系统上,整个系统会变得不可用。
为什么 Node 构建会冻结小型 EC2 实例
Vite、Webpack、Next.js 等 Node.js 构建工具需要大量内存来:
- 压缩大型 JS 包
- 优化图片
- 处理 TypeScript
- 执行 tree‑shaking
- 构建多个目标
在内存不足的服务器上,这会触发连锁反应:
1. CPU 占用 100 %
Node 编译器全速运行。
2. RAM 用尽
一次构建可能需要 512 MB – 2 GB 的内存,这对小型 EC2 实例来说太重。
3. OOM(内存不足)杀进程
内核会自动先杀掉其他进程(如 PHP‑FPM 或 MySQL),而不是 Node。
4. Nginx 停止响应
当 PHP‑FPM 死掉后,Nginx 会返回 502/504 错误或彻底卡死。
5. SSH 变慢
如果换页也被占满,操作系统将停止调度任务,导致 服务器上所有域名 均不可用。
如何在未来防止此类问题
1. 永远不要在生产或测试服务器上构建前端代码
- 在本地或 CI/CD 中构建。
- 只上传最终的
dist/或build/文件夹。 - 部署已编译的资源。
仅此一步就能避免大多数此类事故。
2. 添加 Swap 文件
对小型 EC2 实例(如 t2.micro、t3.small),创建一个 2 GB 的 swap 文件:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab
Swap 能帮助操作系统在内存耗尽时避免崩溃。
3. 限制 Node.js 内存使用(PM2 保护)
如果应用在 PM2 下运行,使用内存保护:
pm2 restart --max-memory-restart=300M
或对所有进程生效:
pm2 restart all --max-memory-restart=300M
这可以防止单个 Node 应用耗尽全部内存。
4. 高负载时重启 PHP‑FPM 与 Nginx
当服务器变慢或卡死时:
sudo systemctl restart php8.1-fpm
sudo systemctl restart nginx
通常可以立刻恢复服务。
5. 使用 htop 实时监控资源使用情况
安装并运行:
sudo apt install htop
htop
htop 能帮助你快速定位哪个进程占用了 CPU、哪个服务占用了 RAM,以及是否有卡住或僵尸进程。
6. 使用 PM2 Startup 确保 Node 应用在重启后自动启动
pm2 startup
pm2 save
这样在服务器重启后 Node 应用会自动恢复。
7. 使用部署流水线
采用 CI/CD 方案(GitHub Actions、GitLab CI、Bitbucket Pipelines、Jenkins 等),在 部署前 完成资源构建,绝不在目标服务器上进行构建。
结论
当多个应用共享同一台 EC2 实例时,像 Node 构建这样的大任务会导致系统资源超负荷,进而使整台机器卡死,所有域名和服务同时宕机。为防止此类情况,团队应当:
- 避免在服务器上直接运行构建
- 添加 swap 内存
- 限制 Node 内存使用
- 监控资源消耗
- 使用 CI/CD 流水线
通过这些措施可以保证性能的稳定,避免在开发、测试或生产环境中出现突发的停机。