【问题标题】:Is it possible to access Ruby EventMachine Channels from Thin/Rack/Sinatra?是否可以从 Thin/Rack/Sinatra 访问 Ruby EventMachine 通道?
【发布时间】:2011-08-11 00:38:34
【问题描述】:

我希望为利用 Sinatra 的内部项目构建一个简单的 RESTful 通知系统。我过去使用 EventMachine 频道订阅/发布事件,但在我之前的所有案例中,我都直接使用 EventMachine。

有谁知道是否可以从 Sinatra 应用程序或什至从某些 Rack 中间件创建、订阅和发布到 EventMachine 通道(在 Thin 中运行)?

【问题讨论】:

    标签: ruby sinatra rack eventmachine thin


    【解决方案1】:

    看看async_sinatra

    基本上,要在 Thin 中运行时使用 EventMachine,您需要让它知道您想要异步处理请求。 Rack 协议在设计上是同步的,Thin 期望在处理程序返回时完成请求。有一些方法可以让 Thin 意识到您想要异步处理请求(请参阅 think_async 了解如何处理的示例),而 async_sinatra 让这变得非常容易。

    【讨论】:

    • 嗯...所以我不需要异步处理请求,因为我只需要一种利用 EventMachine 的 Channel 对象的方法。但是,您的回答让我很清楚,在 Thin 中运行的 EventMachine 可用于 Rack 应用程序,只需像往常一样引用 EM。因此,您已经回答了我的问题。谢谢西奥!
    • 我假设您想使用 Channels 在您的应用程序中进行通信。例如,在处理要发布到通道的请求时,等待另一个通道上的回复,或者您可能想退出队列。这些是异步操作,您必须异步处理您的请求以处理它们。例如,如果您运行queue.pop { |msg| ... },则您的请求在调用回调/阻止时已经发送。
    • 是的,我没必要很好地解释我想要完成的工作。本质上,我想提供一个 RESTful 接口来创建、推送和注册通道,以支持我的应用程序之外的其他 Web 服务器的通知。最后,我希望一个客户端能够将通知推送到通道,并通过 queue.pop 块中定义的单独 HTTP 请求通知向该通道注册的所有 Web 服务器。
    【解决方案2】:

    布莱恩, 您可以使用 em-http-request 库 (https://github.com/igrigorik/em-http-request),这将允许您引用在 A.同一服务器上运行的特定 EventMachine 应用程序,B.a不同的服务器,或 C. 真正想要的任何地方。

    require 'eventmachine'
    require 'em-http-request'
    require 'sinatra/base'
    require 'thin'
    
    class ServerClass < EventMachine::Connection
      def initialize(*args)
        # ruby singleton - store channel data in global hash
        ($channels ||= [])
      end
    
      def post_init
        puts "initialized"
        $cb.call("initialized");
      end
    
      def receive_data(data)
        # got information from client connection
      end
    
      def channel_send(msg,channel)
        $channels[channel].send_data(msg)
      end
    
      def channels_send(msg)
        $channels.each{|channel| channel.send_data(msg)}
      end
    
      def unbind
        # puts user left
      end
    
    end
    
    EventMachine.run do
      $cb = EM.callback {|msg| puts msg #do something creative}
      $ems = EventMachine::start_server('0.0.0.0',ServerClass,args)
    
      class App < Sinatra::Base
        set :public, File.dirname(__FILE__) + '/public'
    
        get '/' do
          erb :index          
        end
    
      end
    
      App.run!({:port => 3000})
    
    end
    

    上面是一个基本的线框。根据您希望如何发送数据,您可以使用 WebSockets (em-websocket) 并在登录时绑定每个用户(必须添加登录系统),或者您可以将其用于任何用途。只要您拥有对 Eventmachine 对象(连接、websocket、通道)的全局引用,您就可以从应用程序中传递消息。

    顺便说一句 - 添加 EventMachine.run do;....end 循环是可选的,因为 Thin 无论如何都会这样做。它有助于了解它是如何工作的。

    祝你好运

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-12
      • 2011-10-20
      • 1970-01-01
      • 2020-10-14
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多