我尝试将现有的爬虫从EngEnter切换到赛璐珞。为了与赛璐珞取得联系,我在linux上生成了一堆静态文件,每个文件有150kb,通过nginx提供。
底部的代码应该做它的工作,但是代码中有一个问题,我不明白:代码应该产生最大50个线程,因为线程池大小为50,但是它产生了180个线程。如果我将池大小增加到100,将生成330个线程。怎么了?
此代码的简单复制和粘贴应该适用于每个框,因此欢迎提供任何提示:)

#!/usr/bin/env jruby

require 'celluloid'
require 'open-uri'

URLS = *(1..1000)

@@requests = 0
@@responses = 0
@@total_size = 0

class Crawler
  include Celluloid

  def fetch(id)
    uri = URI("http://data.asconix.com/#{id}")
    puts "Request ##{@@requests += 1} -> #{uri}"
    begin
      req = open(uri).read
    rescue Exception => e
      puts e
    end
  end
end

URLS.each_slice(50).map do |idset|
  pool = Crawler.pool(size: 50)
  crawlers = idset.to_a.map do |id|
    begin
      pool.future(:fetch, id)
    rescue Celluloid::DeadActorError, Celluloid::MailboxError
    end
  end
  crawlers.compact.each do |resp|
    $stdout.print "Response ##{@@responses += 1} ->  "
    if resp.value.size == 150000
      $stdout.print "OK\n"
      @@total_size += resp.value.size
    else
      $stdout.print "ERROR\n"
    end
  end
  pool.terminate
  puts "Actors left: #{Celluloid::Actor.all.to_set.length} -- Alive: #{Celluloid::Actor.all.to_set.select(&:alive?).length}"
end

$stdout.print "Requests total: #{@@requests}\n"
$stdout.print "Responses total: #{@@responses}\n"
$stdout.print "Size total: #{@@total_size} bytes\n"

顺便说一下,当我在每个切片循环之外定义池时,也会出现同样的问题:
....
@pool = Crawler.pool(size: 50)

URLS.each_slice(50).map do |idset|
  crawlers = idset.to_a.map do |id|
    begin
      @pool.future(:fetch, id)
    rescue Celluloid::DeadActorError, Celluloid::MailboxError
    end
  end
  crawlers.compact.each do |resp|
    $stdout.print "Response ##{@@responses += 1} ->  "
    if resp.value.size == 150000
      $stdout.print "OK\n"
      @@total_size += resp.value.size
    else
      $stdout.print "ERROR\n"
    end
  end
  puts "Actors left: #{Celluloid::Actor.all.to_set.length} -- Alive: #{Celluloid::Actor.all.to_set.select(&:alive?).length}"
end

最佳答案

你在用什么红宝石?jRubyRubinius等?那是什么版本的呢?
我问的原因是,每个ruby对线程的处理方式不同。您似乎正在描述的是添加的线程,这些线程用于主管和任务。看看你发帖的日期,很可能是纤维实际上正在变成本机线程,这会使它看起来像是在使用jRuby可能。此外,使用Futures经常调用内部线程池,这与池无关。
有了这两个原因和其他类似的原因,您可以寻找,这就解释了为什么您有一个比您的池调用更高的线程计数。这是一个有点老,所以也许你可以跟进你是否仍然有这个问题,并后输出。

08-04 22:01