为什么使用赛璐珞会出现随机错误?

Why do I get random errors by using celluloid?

我需要对网络服务进行 API 次调用才能检索日期。 为此,我创建了一个样本以熟悉赛璐珞。 在这里,我将使用 openweather API 用于 "training" 目的。 最终目标是 运行 并发多个请求。

我的预订class (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.

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

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。在 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,这非常适合具有并发出站收集调用的 actor。