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

时间:2015-06-11 19:29:15

标签: ruby concurrency celluloid

我需要对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|
    p i
    #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.

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

1 个答案:

答案 0 :(得分:2)

0。您的计划在Celluloid完成工作之前完成。

您需要使用#2中显示的方法来避免这种情况。您需要join每个Future以确保检索和解析所有信息...否则您只是发起了大量不是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|
  p i
  results << booking.future.parse(weather)
end

#de Turn the futures into actual results by calling `.value` on each future:
results = results.map(&:value)

3。将http.rbCelluloid支持一起使用:

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,这对你的演员来说非常好,后者有并发的出站聚会电话。