0

我有一个使用 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 队列中。

4

2 回答 2

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
于 2013-06-14T20:36:51.083 回答
0

我不确定你需要什么。您可以使用该max_concurrency选项设置并行请求的上限。

于 2013-06-19T08:23:24.710 回答