你如何在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消息传递选项将是
- 部署与TorqueBox(与HornetQ捆绑在一起), http://torquebox.org/news/2011/08/15/websockets-stomp-and-torquebox/ ,令人印象深刻和企业化,但不是很优雅,除非你来自一个Java背景
- 较新版本的Faye应该与JRuby, Faye在jruby on rails上合作
- 注意未来,密切关注赛璐珞社区,一些有趣的分布式解决方案来自那里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
)。