1

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

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

4

1 回答 1

2

0. 你的程序在完成Celluloid它的工作之前就完成了。

您需要使用#2 中显示的方法来避免这种情况。你需要确保所有的信息都被检索和解析......否则你只是触发了大量的异步调用,这些调用没有join......这意味着没有什么能阻止程序退出。Futureblock

如有疑问,只需添加sleep到程序的末尾,直到您弄清楚您希望如何优雅地完成。到目前为止,您显示的代码不完整。


1. 像这样使用新版本Celluloid

在您的 Gemfile 中:

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

然后当你图书馆,使用这个requireCelluloid

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.rb使用Celluloid

像这样添加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,它非常适合你的参与者,它有并发的出站收集调用。

于 2015-06-13T08:53:47.607 回答