Next.js Docker容器运行约4小时后崩溃:SSR页面API超时
问题分析与解决方案
1. 4小时规律性故障的可能根源
几个常见触发因素:
- 内存泄漏:Next.js SSR页面中未清理的全局变量、React Query无限膨胀的缓存、未释放的API连接(如fetch/axios未正确回收请求)会导致内存持续占用,达到容器或Node.js内存阈值后引发服务无响应。
- 连接池耗尽:后端API调用未复用连接,或默认连接数上限过低,4小时的请求堆积后无法新建连接,导致SSR阶段API调用超时。
- 定时任务触发:若应用存在每4小时执行的定时任务(如缓存刷新、数据同步),任务执行时占用大量CPU/内存资源,导致服务阻塞。
- Docker资源限制触发:未设置容器内存上限时,内存占用达到宿主机阈值后,Docker会强制限制容器资源,引发服务崩溃。
2. 正确监控Next.js容器内存使用
Docker层面监控
- 实时查看容器资源:执行
docker stats <container-id>,可获取内存、CPU、网络等指标的实时数据。 - 记录历史数据:定时执行
docker stats --no-stream --format "{{.Name}},{{.MemUsage}}" >> mem-log.txt,留存内存使用趋势,便于排查泄漏问题。
应用层面监控
- 在Next.js中添加内存日志:在
server.js或自定义middleware.ts中加入定时监控代码:
setInterval(() => { const { rss, heapUsed } = process.memoryUsage(); console.log(`[${new Date().toISOString()}] Memory: RSS=${Math.round(rss/1024/1024)}MB, HeapUsed=${Math.round(heapUsed/1024/1024)}MB`); }, 60000); // 每分钟记录一次
- 使用Node.js调试工具:启动容器时添加
--inspect参数,通过Chrome DevTools的Memory面板分析内存快照,定位泄漏点:
docker run -p 9229:9229 -p 7700:7700 your-image node --inspect=0.0.0.0 server.js
3. Next.js SSR连接/资源耗尽的已知问题
- React Query缓存膨胀:默认缓存策略可能导致内存占用持续增长,需手动设置
cacheTime和staleTime限制缓存生命周期。 - 未处理的资源:在
getServerSideProps或getInitialProps中若存在未捕获的Promise、未关闭的数据库连接/API请求,会导致资源泄漏。 - Standalone模式资源回收:Next.js 14的standalone构建可能存在部分静态资源或模块未被正确回收的情况,可尝试升级到最新小版本修复。
- Node.js 18 HTTP连接池:Node.js 18默认的HTTP/2连接池上限可能不足以支撑高并发场景,需手动调整
maxSockets参数。
4. Docker配置优化建议
1. 添加健康检查
在Dockerfile的runner阶段末尾添加健康检查,让Docker自动重启不健康容器:
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT}/api/health || exit 1
需先在应用中实现
/api/health接口,返回200状态码表示服务正常。
2. 限制容器资源
启动容器时设置内存和CPU上限,防止资源耗尽影响宿主机:
docker run -d -p 7700:7700 --memory=2g --cpus=1 --restart=always your-image
--memory=2g:限制容器最大内存为2GB--restart=always:容器故障时自动重启
3. 优化Docker镜像
- 移除
runner阶段不必要的pnpm安装:standalone构建已包含所有依赖,无需在生产镜像中保留pnpm,删除RUN npm install -g pnpm。 - 添加Alpine依赖兼容包:安装
libc6-compat解决musl libc与部分Node.js包的兼容性问题:
FROM node:18-alpine AS runner RUN apk add --no-cache libc6-compat # 后续步骤不变
4. 调整Node.js内存参数
启动时设置Node.js老年代内存上限,避免内存溢出:
CMD ["node", "--max-old-space-size=1536", "server.js"]
1536表示1.5GB,可根据容器内存限制调整。
额外排查步骤
- 检查React Query配置:在
QueryClient中设置合理的缓存过期时间:
const queryClient = new QueryClient({ defaultOptions: { queries: { cacheTime: 3600000, // 1小时 staleTime: 900000, // 15分钟 }, }, });
- 优化API调用代码:确保所有fetch/axios请求正确处理错误,复用HTTP Agent限制连接数:
import https from 'https'; const agent = new https.Agent({ keepAlive: true, maxSockets: 10 }); // 在fetch中使用agent fetch('https://your-api.com/data', { agent });
内容的提问来源于stack exchange,提问作者Esamani77
相关产品推荐
相关产品推荐

