21

我有一个 Rails 应用程序,并希望为其添加某种 WebSocket 支持。从各种谷歌搜索来看,基于 Ruby 的最佳 WebSocket 解决方案似乎是在 EventMachine 上运行的em-websocket 。

我想知道是否有办法将 EventMachine 反应器“集成”到 Rails 中?我在哪里放置初始化代码?这是完成此任务的正确方法吗?

我见过这个例子,它依靠 Sinatra 来执行 EventMachineGET请求,但这并不是我想要的。

任何帮助表示赞赏。

4

8 回答 8

9

你不能在 Rails 内部运行 Eventmachine 引擎,因为它是一个持久的运行循环,会永久阻塞你的 Rails 进程之一。通常所做的是有一个使用 Eventmachine 的辅助进程,Rails 通过套接字与其通信以发送通知。

Juggernaut就是这种事情的一个例子,它实现了一个 Websocket 客户端和一个 Rails 钩子来向它发送通知。该项目已经弃用了 Ruby 版本,转而支持 JavaScript Node.js 版本,但这仍然是一个非常详尽的例子,说明了如何使用 Eventmachine。

于 2011-04-27T04:53:07.073 回答
6

如果您在瘦服务器(bundle exec thin start)中运行 rails 应用程序,则瘦服务器会为您运行 EventMachine,然后您的 rails 应用程序可以在您需要的任何地方执行 EM 代码。

举例:

具有该代码的库 o 初始化程序:

EM.next_tick do
  EM.add_periodic_timer(20) do
    puts 'from Event Machine in rails code'
  end
end

不阻止 rails 进程应用程序。

于 2011-12-02T12:55:14.897 回答
5

不知道这是否是你所追求的。但是,如果您想提供某种套接字消息传递系统。

看看法伊。它为 Node.js 和 Rack 提供消息服务器。Ryan Bates 也为此铸造了一个轨道,它应该可以简化实施。

希望有帮助。

于 2011-04-27T05:52:35.253 回答
4

我花了相当多的时间来研究这个。EventMachine 需要在您的 rails 安装中作为线程运行(除非您使用的是 Thin),并且对于 Passenger 有一些特殊的注意事项。我在这里写了我们的实现:http ://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html

更新

我们将此配置提取到一个名为 Momentarily 的 gem 中。来源在这里https://github.com/eatenbyagrue/momentarily

于 2011-11-04T18:58:34.443 回答
2

我会尝试使用em-synchrony在光纤中启动反应器。在 Rails 应用程序中,您可能可以在初始化程序中启动它,因为听起来您只想让反应器运行以响应 websocket 请求。正如其他答案所建议的那样,我认为您想要设置与反应堆的套接字通信,或者使用异步客户端之一到数据存储,您的反应堆和 Rails 代码都可以读取和写入以交换数据。

我的一些同事整理了一些在 ruby​​ 代码中按需启动 EM 反应器的示例,以在 EventMachine 中运行他们的测试。我会尝试使用它作为一个可能的例子;使用 eventmachine 进行搜索和测试

于 2011-04-27T06:07:52.377 回答
2

我会考虑调查抽筋。它是一个建立在 EventMachine 之上的异步框架,它支持瘦服务器:

机架中间件支持 + 彩虹!和瘦 Web 服务器

于 2012-03-23T05:36:50.460 回答
0

如果你能提供帮助,你可能不应该再使用 EM,它似乎不再被维护——如果你遇到错误——你只能靠自己了。

由于https://github.com/eventmachine/eventmachine/issues/479,上述大多数答案在 JRuby 中不起作用- 即模式:

Thread.new{ EM.run }

在互联网上找到的EM::Synchrony各种答案(例如EventMachine 和 Ruby 线程 - 这里到底发生了什么?)在 JRuby 事件机器实现下被破坏(纤维是 jruby 中的线程,目前没有关于何时改变的路线图)。

JRuby 消息传递选项将是

  1. 使用 TorqueBox(与 HornetQ 捆绑在一起)进行部署,http ://torquebox.org/news/2011/08/15/websockets-stomp-and-torquebox/ ,令人印象深刻且富有企业精神,但不是很优雅,除非你来自Java背景
  2. 较新版本的 Faye 应该与 JRuby 一起工作,Faye 在 jruby on rails
  3. 注意未来,关注赛璐珞社区,一些有趣的分布式解决方案来自那里https://github.com/celluloid/reel/wiki/WebSocketshttps://github.com/celluloid/dcell
  4. ?
于 2013-12-24T06:42:10.323 回答
0

我有同样的问题并找到了解决方案。首先,将您的代码放在libdir 中(例如/lib/listener/init.rb)并创建一个运行 EM 的类方法,例如Listener.run.

#!/usr/bin/env ruby

require File.expand_path('../../config/environment', File.dirname(__FILE__))

class Listener
  def self.run
  # your code here
  # you can access your models too
  end
end

之后我使用了但丁宝石。创建/init/listener文件。代码可能是这样的:

#!/usr/bin/env ruby

require File.expand_path('../../lib/listener/init.rb', __FILE__)

log_file = File.expand_path('../../log/listener.stdout.log', __FILE__)
pid_file = File.expand_path('../../tmp/listener.pid', __FILE__)

listener = Dante::Runner.new('listener')

if ARGV[0] === 'start'
  listener.execute(daemonize: true,
                   pid_path: pid_file,
                   log_path: log_file) { Listener.run }
elsif ARGV[0] === 'restart'
  listener.execute(daemonize: true,
                   restart: true,
                   pid_path: pid_file,
                   log_path: log_file) { Listener.run }
elsif ARGV[0] === 'stop'
  listener.execute(kill: true, pid_path: pid_file)
end

现在你可以像这样运行你的代码:./bin/listener start, ./bin/listener restart,./bin/listener stop

你可以使用god来监控你的监听器正在运行。但请确保您使用的是相同的 pid 文件 ( /tmp/listener.pid)。

于 2016-12-13T01:47:15.023 回答