你如何在Rails应用程序中“生成”一个EventMachine?

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

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

我已经看到这个回到Sinatra的例子来做一个EventMachine GET请求,但这并不是我想要的。

任何帮助表示赞赏。

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

我的一些同事在ruby代码中根据需要组合了一些启动EM反应器的例子,以便在EventMachine中运行他们的测试。 我试着用它作为一个可能的例子; 使用eventmachine进行耙和测试

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

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

如果您在瘦服务器(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进程应用程序。

不知道这是不是你想要的。 但是如果你想提供某种套接字消息系统。

看看Faye 。 它为Node.js和Rack提供消息服务器。 Ryan Bates还为此设计了一个轨道 ,可以简化实施。

希望有所帮助。

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

UPDATE

我们把这个配置拉到了一个名为Momentarily的gem中。 来源在这里https://github.com/eatenbyagrue/momentarily

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

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

你可能不应该再使用EM了,如果你可以帮助它,它似乎不再被维护 – 如果你遇到一个bug – 你就是你自己。

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

 Thread.new{ EM.run } 

EM::Synchrony和互联网上发现的各种答案(例如EventMachine和Ruby Threads – 这里真正发生了什么? )在JRuby eventmachine实现中被破坏了(光纤是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/WebSockets,https://github.com/celluloid/dcell

我有同样的问题,找到了解决方案。 首先,将代码放在lib目录中(例如/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 

之后我用了dante gem。 创建/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 )。