Puma Docker容器内存使用后无法释放问题求助
Rails Puma集群模式内存持续增长导致容器重启
我们的Rails应用采用Puma集群模式,配置为3个worker、5个线程。容器启动后,Puma worker的内存占用率快速上升,一段时间后增速放缓但仍逐步增长;当内存占用达到100%时,容器会停止并重启。
内存使用率图表:
排查与解决方案
1. 定位内存泄漏根源
- 用
derailed_benchmarks快速检测:
安装gem:gem 'derailed_benchmarks', group: :development
运行命令:bundle exec derailed exec perf:mem,它会追踪对象分配情况,找出持续增长的对象类型,精准定位泄漏点。 - 结合
memory_profiler做请求级分析:在特定请求中插入内存追踪代码,查看哪些对象未被回收。
2. 优化Puma配置,主动释放内存
- 启用worker定期重启:在
config/puma.rb中添加以下配置,让Puma自动重启worker避免内存累积:worker_timeout 3600 # 每小时重启一次worker preload_app! on_worker_boot do # 重启worker时重建必要连接 ActiveRecord::Base.establish_connection Rails.cache.reset if defined?(Rails.cache) end - 调整worker/线程配比:如果单worker内存增长过快,可尝试减少worker数量(如2个)或降低线程数(如3个),避免线程竞争导致的资源未释放问题。
3. 排查常见泄漏场景
- 资源未释放:用
lsof -p <worker_pid>检查是否有未关闭的数据库连接、Redis连接或文件句柄。 - 全局/类变量滥用:避免用
@@开头的类变量存储动态数据,这类数据会在worker生命周期内持续累积。 - 第三方gem问题:排查近期新增的gem,尤其是处理文件、网络请求的依赖,移除后观察内存变化验证是否为gem泄漏。
- 缓存无过期:检查Rails缓存配置,确保缓存数据设置了合理的过期时间,防止缓存溢出。
4. 容器层面的兜底策略
- 使用
puma_worker_killer实现内存阈值触发重启:
安装gem:gem 'puma_worker_killer'
配置config/puma.rb:require 'puma_worker_killer' # 每小时滚动重启worker,避免服务中断 PumaWorkerKiller.enable_rolling_restart(3600) # 内存占用达90%时自动重启worker PumaWorkerKiller.config do |config| config.ram = 1024 # 容器可用内存(单位:MB,根据实际调整) config.percent_usage = 0.9 config.frequency = 5 # 每5秒检查一次内存 end
内容的提问来源于stack exchange,提问作者Appso
相关产品推荐
相关产品推荐

