既存のクローラーを 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