为什么你的 EC2 服务器会突然停止响应 —— 以及如何为 Laravel 与 Node 应用加固

发布: (2025年12月10日 GMT+8 00:50)
5 min read
原文: Dev.to

Source: Dev.to

实际发生了什么?

根据内部调查,问题是由于服务器无法加载构建并导致系统卡死。当有人在 EC2 实例内部直接运行 npm run buildyarn 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 流水线

通过这些措施可以保证性能的稳定,避免在开发、测试或生产环境中出现突发的停机。

Back to Blog

相关文章

阅读更多 »