红宝石和赛璐珞

时间:2012-09-05 16:14:44

标签: ruby concurrency celluloid

由于某些限制,我想将当前项目从EventMachine / EM-Synchrony切换到Celluloid,但是我很难与它联系。我正在编写的项目是一个网络收集器,它应该尽可能快地抓取大量页面。

为了对Celluloid的基本了解,我在本地网络服务器上生成了10.000个虚拟页面,并希望通过这个简单的Celluloid片段抓取它们:

#!/usr/bin/env jruby --1.9

require 'celluloid'
require 'open-uri'

IDS = 1..9999
BASE_URL = "http://192.168.0.20/files"

class Crawler
  include Celluloid
  def read(id)
    url = "#{BASE_URL}/#{id}"
    puts "URL: " + url
    open(url) { |x| x.read }
  end
end

pool = Crawler.pool(size: 100)

IDS.to_a.map do |id|
   pool.future(:read, id)
end

据我了解赛璐珞,期货是获取被激活请求响应的方式(与EventMachine中的回调相当),对吧?另一件事是,每个actor都在自己的线程中运行,所以我需要对请求进行某种批处理,因为10.000线程会导致我的OSX开发机器出错。

所以创建一个游泳池是可行的,对吧?但是:上面的代码迭代了9999个URL,但只有1300个HTTP请求被发送到Web服务器。因此限制请求和迭代所有URL都会出错。

1 个答案:

答案 0 :(得分:7)

一旦你的所有期货都被创建,你的程序就可能会退出。使用赛璐珞,未来将开始执行,但是在你对未来对象调用#value之前,你无法确定它是否完成。这也适用于池中的期货。你可能需要做的就是改变它:

  crawlers = IDS.to_a.map do |id|
    begin
      pool.future(:read, id)
    rescue DeadActorError, MailboxError
    end
  end

  crawlers.compact.each { |crawler| crawler.value rescue nil }