我有一个使用hydra来请求页面的程序。我想限制下载队列中的项目数。 hydra.queue
调用是非阻塞的,因此我需要以某种方式在旧的完成处理时触发新的下载。当前的解决方案使用递归。
def perform
@hydra = Typhoeus::Hydra.new(:max_concurrency => 100)
@target_concurrency.times {process_next_product}
end
def process_next_product
if id = $redis.lpop(REDIS_UNSCRAPED_PRODUCTS_KEY)
product = Product.find(id).url
req = Typhoeus::Request.new(product.url, {:follow_location => true})
req.on_complete do |resp|
process_product_response(product, resp.body)
end
@hydra.queue(req)
end
end
def process_product_response(product, response)
# process product
process_next_product
end
随着调用堆栈的增长,此解决方案正在占用内存。我想要一个解决方案,允许我在不使用递归的情况下将 x 项保留在hydra队列中。
答案 0 :(得分:0)
我采用的解决方案是使用信号触发处理下一个条目:
def perform
@hydra = Typhoeus::Hydra.new(:max_concurrency => 100)
set_trap
@target_concurrency.times { Process.kill("USR1", Process.pid) }
end
def set_trap
Signal.trap('USR1') do
if id = $redis.lpop(REDIS_UNSCRAPED_PRODUCTS_KEY)
product = Product.find(id).url
req = Typhoeus::Request.new(product.url, {:follow_location => true})
req.on_complete do |resp|
process_product_response(product, resp.body)
end
@hydra.queue(req)
end
end
end
def process_product_response(product, response)
# process product
Process.kill("USR1", Process.pid)
end
答案 1 :(得分:0)
我不确定你需要什么。您可以使用max_concurrency
选项设置并行请求的上限。