You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sidekiq Worker+Nokogiri爬取网站内存持续增长问题咨询

问题分析与解决方案

先给你理清核心差异:Sidekiq和rails runner的进程生命周期完全不同,这是内存表现差异的根本原因,再结合代码里的细节,就能找到问题所在。

1. 进程模型的本质区别

  • Sidekiq的Worker进程是长期驻留的:启动后会一直运行,反复处理队列里的任务。Ruby的垃圾回收(GC)是惰性触发的,只有当内存占用达到阈值时才会主动回收。而且如果任务处理后有一些对象被隐式引用(比如日志上下文、Sidekiq的内部钩子),GC可能不会立即清理这些对象,导致内存看起来“没释放”。
  • rails runner是一次性进程:任务启动时创建进程,任务结束后进程直接销毁,操作系统会回收这个进程占用的所有内存,所以看起来内存完全释放了。

2. 你的代码里可能的内存残留点

看你提供的简化代码,有两个需要注意的地方:

  • Net::HTTP::Persistent的使用:这个库是用来复用HTTP长连接的,但你的任务是每隔几分钟运行一次,长连接复用的优势几乎为零,反而可能在连接池里残留一些未彻底清理的对象。虽然你调用了http.shutdown,但某些场景下可能还有残留的连接或上下文对象。
  • 实例变量@parsed_response:用实例变量持有Nokogiri解析后的节点集,会让这个对象的生命周期和Worker实例绑定。虽然任务结束后Worker实例理论上会被GC,但如果有隐式引用(比如Sidekiq的监控数据、日志输出),可能延迟回收。换成局部变量会更利于GC及时清理。

3. 这类任务适合用Sidekiq吗?

不是不适合,而是需要做针对性优化。如果你的任务是周期性、低频率的,优化后Sidekiq完全可以稳定运行。但如果任务每次内存占用极高,或者内存泄漏难以排查,那可以考虑更轻量化的方案。

4. 具体解决方案

方案一:优化Sidekiq任务代码,解决内存泄漏

  • 替换Net::HTTP::Persistent为普通的Net::HTTP请求,因为你的任务间隔长,不需要长连接复用:
    def get_request(url, headers="")
      uri = URI.parse(url)
      Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
        request = Net::HTTP::Get.new(uri)
        # 这里可以添加headers
        headers.each { |k, v| request[k] = v } if headers.is_a?(Hash)
        http.request(request)
      end
    end
    
  • 把@parsed_response改成局部变量,让对象在任务结束后立即脱离作用域:
    def perform
      response = get_request("https://website.com")
      parsed_response = Nokogiri::HTML(response.body).xpath("//tbody/tr")
      # 后续处理用parsed_response而不是实例变量
    end
    
  • 可选:在任务末尾手动触发GC(不推荐频繁使用,但可以用来验证是否是GC延迟问题):GC.start

方案二:调整Sidekiq配置,自动重启Worker进程

在Sidekiq的配置文件(比如config/sidekiq.yml)中添加max_jobs参数,让Worker处理一定数量的任务后自动重启,强制释放内存:

:max_jobs: 50  # 每个Worker处理50个任务后重启

方案三:改用Cron + rails runner/独立脚本

这就是你想到的方案,完全规避长期进程的内存问题:

  • 编写独立的Ruby脚本(或用rails runner调用任务逻辑),然后用Linux Cron定时执行。比如Cron表达式可以设为*/5 * * * *(每隔5分钟运行一次)。
  • 这种方案的优势是任务结束后内存完全释放,适合内存敏感、低频率的周期性任务。

内容的提问来源于stack exchange,提问作者LewlSauce

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:40:05