你如何生成一个事件机器"inside"一个Rails应用程序?



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

我想知道是否有一种方法可以将EventMachine反应器"集成"到Rails中?初始化代码放在哪里?这是实现这一目标的正确方法吗?

我看到了这个例子,它依靠Sinatra来执行EventMachine GET请求,但这并不是我想要的。

感谢您的帮助。

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

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

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

举例:

带有以下代码的初始化器库:

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

非阻塞rails进程应用程序。

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

看看王菲。它为Node.js和Rack提供消息服务器。Ryan Bates对此也提出了一个建议,这应该会简化实现。

希望能有所帮助。

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

更新

我们把这个配置变成了一个名为Momentally的宝石。来源在这里https://github.com/eatenbyagrue/momentarily

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

我的一些同事在ruby代码中列出了一些按需启动EM反应器的示例,以便在EventMachine中运行测试。我会尝试用它作为一个可能的例子;使用事件机进行清理和测试

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

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

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

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

Thread.new{ EM.run }

EM::Synchrony使用的方法和在互联网上找到的各种答案(如EventMachine和Ruby Threads-这里到底发生了什么?(在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/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

之后我用了丹特宝石。创建/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(。

相关内容

  • 没有找到相关文章

最新更新