我使用 gem Curb
(也尝试过httparty
)来执行大量 http 请求,并且效果很好。但是在我的 ( rake
) 任务之一(我执行 20k+ 请求)中,我遇到了内存问题(Rails “吃掉”了超过 2GB 的 RAM,直到没有可用内存为止)。
似乎Rails“不等待”响应并在循环中的另一个线程中继续,问题是这样会创建很多没有被垃圾收集器收集的对象(我认为)并且是内存泄漏的原因。
有一种方法可以让 rails 等到响应到来?(我试过sleep
但不是一个稳定的解决方案)。
我有一个这样的伪代码:
def the_start
while start_date <= end_date do # ~ 140 loop
a_method_that_do_sub_specifics_call
end
end
def a_method_that_do_sub_specifics_call
some_data.each do |r| # ~ 180 loop
do_a_call
#do something with models (update/create entries,...)
end
end
def do_a_call # called ~ 25k times
# with the gem Curb version
req = Curl::Easy.new do |curl|
curl.ssl_verify_peer = false
curl.url = url
curl.headers['Content-type'] = 'application/json'
end
req.perform
# actual version, with httparty gem
req = HTTParty.get("#{url}",
:headers => {'Content-type' => 'application/json'})
end
似乎 Rails 并没有等到req.perform
.
编辑:
也尝试只实例化一次Curl::Easy
对象,在调用之后使用Curl::Easy.perform()
and req.close
(应该隐式调用 GC),但没有成功使用大量内存。(我认为)唯一可行的解决方案是在响应到来之前“阻塞”导轨,但是如何?
编辑 2
在另一个任务中,我只调用a_method_that_do_sub_specifics_call
没有问题的。
编辑 3
在一些性能模块(放置find_each(:batch_size => ...)
、GC.start
...)之后,任务工作得更好了。现在第一个 ~100 循环(do_a_call
)工作得很好,之后内存使用量再次从 100Mb 跃升至 2Gb+。