为什么我使用赛璐珞会得到随机错误?

我需要对Web服务进行API调用才能检索日期。 为此我创建了一个样本以熟悉赛璐珞。 在这里,我将使用openweather API进行“培训”。 最终目标是同时运行多个请求。

我的预订类(booking.rb)获取数据

require 'celluloid' require 'open-uri' require 'json' class Booking include Celluloid def initialize end def parse(url) p "back again" begin buffer = open(url).read p JSON.parse(buffer)['cod'] rescue => e "fuck" end end end 

这就是我运行它的方式:

 require 'celluloid' Celluloid.shutdown_timeout = 10 begin pool = Booking.pool %W( http://api.openweathermap.org/data/2.5/weather?q=London,uk http://api.openweathermap.org/data/2.5/weather?q=Berlin,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de ).each_with_index do |weather, i| pi #Booking.new.async.parse(weather) pool.future.parse(weather) end rescue => e p "ex #{e}" end p "start" 

现在,当我多次运行它时,我会得到不同的错误消息:

 ruby run_booking.rb 0 1 2 3 4 5 6 7 8 9 "start" D, [2015-06-11T21:20:06.351274 #33316] DEBUG -- : Terminating 9 actors... E, [2015-06-11T21:20:16.356649 #33316] ERROR -- : Couldn't cleanly terminate all actors in 10 seconds! ➜ booking ruby run_booking.rb 0 1 2 3 4 5 6 7 8 9 "start" D, [2015-06-11T21:22:19.172770 #33344] DEBUG -- : Terminating 9 actors... W, [2015-06-11T21:22:19.173145 #33344] WARN -- : Terminating task: type=:finalizer, meta={:method_name=>:__shutdown__}, status=:receiving Celluloid::TaskFiber backtrace unavailable. Please try `Celluloid.task_class = Celluloid::TaskThread` if you need backtraces here. 

所以我想知道这里发生了什么? 感谢帮助。 提前致谢

你的程序在Celluloid完成其工作之前完成。

您需要使用#2中显示的方法来避免这种情况。 您需要join每个Future以确保检索和解析所有信息…否则您只是触发了大量不block的异步调用…这意味着什么都不会block程序退出。

如果有疑问,只需在程序结束时添加sleep ,直到找到想要优雅完成的方式。 到目前为止,您展示的代码不完整。


1.像这样使用新版Celluloid

在你的Gemfile中:

 gem 'celluloid', github: 'celluloid/celluloid', branch: '0.17.0-prerelease', submodules: true 

然后,当您require Celluloid库时,请使用:

 require 'celluloid/current' 

2.只需使用期货。 你根本不需要游泳池,它会减慢你的速度:

 results = [] booking = Booking.new %W( http://api.openweathermap.org/data/2.5/weather?q=London,uk http://api.openweathermap.org/data/2.5/weather?q=Berlin,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de http://api.openweathermap.org/data/2.5/weather?q=Munich,de ).each_with_index do |weather, i| pi results << booking.future.parse(weather) end #de Turn the futures into actual results by calling `.value` on each future: results = results.map(&:value) 

3.使用带有Celluloid支持的http.rb

Celluloid::IO添加到您的Gemfile如下所示:

 gem 'celluloid-io', github: 'celluloid/celluloid-io', branch: '0.17.0-dependent', submodules: true 

然后使用HTTP代替,并传入Celluloid::IO套接字类型。 以下是http.rb本身的示例:

 require "celluloid/io" require "http" class HttpFetcher include Celluloid::IO def fetch(url) HTTP.get(url, socket_class: Celluloid::IO::TCPSocket) end end 

那个电话就在那里使用了公平的TCP,这对你的演员来说非常好,后者有并发的出站收集电话。