3

我们有一个服务器正在运行

  • Sidekiq 4.2.9
  • 导轨 4.2.8
  • 核磁共振 2.1.9

该服务器定期从外部 API 生成一些导入,对它们执行一些计算并将这些值保存到数据库中。

大约 3 周前,服务器开始挂起,正如我从 NewRelic 看到的(以及当 ssh'ed 到它时) - 随着时间的推移,它消耗越来越多的内存,最终占用所有可用的 RAM,然后服务器挂起。

我已经阅读了一些关于 ruby​​ GC 如何工作的文章,但仍然无法理解,为什么在 ~5:30 AM 堆大小从 ~2.3M 跳到 3M 时,仍然有 1M 可用的可用堆槽(GC 设置是默认值)

在此处输入图像描述

类似的行为,下午 3:35: 在此处输入图像描述

所以,问题是:

  1. 如何让 Ruby 填充空闲堆槽而不是从操作系统请求新槽?
  2. 如何让它向系统释放空闲的堆槽?
4

1 回答 1

3

如何让 Ruby 填充空闲堆槽而不是从操作系统请求新槽?

您的图表没有“完全”保真度。很多假设 GC.stat 是由 Newrelic 或其他什么不是在正确的时间调用的。

很有可能你的槽用完了,堆增长了,而且由于 Ruby 中的堆没有缩小,你会被一个有点膨胀的堆卡住。

为了减轻一些痛苦,您可以将RUBY_GC_HEAP_GROWTH_MAX_SLOTS限制为一个合理的数字,例如 100,000 就可以了,我正在尝试游说在核心中设置默认值。

  • 创建运行的作业及其运行时间(持续时间等)的持久日志,在作业运行之前和之后收集 GC.stat

  • 按队列拆分作业,在一台服务器上运行 1 个队列,在另一台服务器上运行另一个队列,查看哪个队列和哪个作业导致问题

  • 使用火焰图或其他分析工具分析您拥有的各种工作

  • 减少您作为实验运行的并发作业数量,或在某些作业类型之间放置互斥锁。一次 1 个“job a”可能是 OKish,而一次 20 个并发的“job a”会导致内存膨胀。

于 2017-06-05T14:05:50.333 回答