2

既存のクローラーを EventMachine から Celluloid に切り替えようとしています。Celluloid と連絡をとるために、Nginx 経由で提供される Linux ボックスで、1 ファイルあたり 150 kB の静的ファイルを多数生成しました。

一番下のコードはその作業を行うはずですが、コードには理解できない問題があります。スレッド プール サイズが 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"

ちなみに、each_slice ループの外側でプールを定義すると、同じ問題が発生します。

....
@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
4

1 に答える 1

0

ルビーは何を使っていますか?jRuby、、Rubiniusなど?そして、それらのどのバージョンですか?

私が尋ねる理由は、スレッドはルビごとに異なる方法で処理されるからです。あなたが説明しているように見えるのは、スーパーバイザーとタスクのために追加されたスレッドです。投稿の日付を見ると、ファイバーが実際にネイティブ スレッドになっている可能性が高く、おそらく使用しているように見えjRubyます。また、使用Futuresすると、プールとは関係のない内部スレッド プールが呼び出されることがよくあります。

これらの理由と同様の他の理由の両方を考えると、プールが要求するよりも多くのスレッド数が必要になる理由は理にかなっています。ただし、これは少し古いので、まだこの問題があるかどうかをフォローアップして、出力を投稿してください。

于 2013-12-06T14:36:48.887 に答える