主要观点:使用 Sidekiq 运行 Ruby 应用的后台任务久了会遇到内存问题,虽有很多内容专注于帮助查找和修复内存问题,但有时后台任务确实需要大量内存。本文主要探讨减轻内存消耗大的后台任务的危害,包括用 APM 工具查找内存问题、常见的内存优化方法(如扇出大任务)、根据内存需求将任务拆分到不同队列以及自动缩放专用 Sidekiq 队列等。
关键信息:
- APM 工具可监测应用和 Sidekiq 进程的内存问题,如 Scout、New Relic 和 AppSignal 可提供内存使用见解。
- 常见的内存优化方法是“扇出”大任务,将其拆分成可更快执行甚至并行的小任务,如将发送提醒的任务拆分成
RemindersJob
和NotifyUserJob
。 - 可根据内存需求将内存消耗大的任务放入单独的 Sidekiq 队列,如
ImportJob
,并为其分配单独的进程,还可设置单线程运行,甚至将其分配到不同机器,垂直扩展机器内存。 - 分配内存消耗大的 Sidekiq 队列到单独进程后可进行水平缩放,如使用 Judoscale 根据队列时间自动缩放 Sidekiq 工作进程,以更好地处理峰值工作负载而不浪费资源。
重要细节: RemindersJob
通过where
和pluck
方法获取需要通知的Event
记录的 ID,然后使用NotifyUserJob.perform_bulk
方法将通知任务入队。- 可通过修改类定义将
ImportJob
放入memory_hungry
队列,如class ImportJob include Sidekiq::Job sidekiq_options queue: 'memory_hungry' end
。 - 可通过
bundle exec sidekiq -q default -q memory_hungry
启动包含两个队列的 Sidekiq 进程,还可在Procfile
中设置不同队列的工作进程,如worker_memory_hungry: RAILS_MAX_THREADS=1 bundle exec sidekiq -q memory_hungry
。 - Judoscale 可根据队列时间自动缩放 Sidekiq 工作进程,处理内存消耗大的任务时可先拆分任务,再根据内存需求拆分到队列,灵活调整配置和添加资源。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。