5

我正在构建一个服务,它基本上允许用户与机器人聊天,然后机器人对用户发送的聊天进行一些奇怪的处理,并最终回复一些有意义的数据。基本上类似于 Aardvark 使用 (?) 工作的方式。

我的机器人正在工作,现在正在收听,我有一个单独的 Rails 应用程序,它将完成所有其他繁重的工作。这两个部分单独工作都很好,现在我被困在两者的接口上。我的想法是通过 Resque 将机器人(基本上是一个小的 ruby​​ 脚本)与 rails 应用程序接口 - 任何进入的东西都会进入队列,被拾取,然后将结果再次推回队列,然后脚本会回复结果。

这个接口怎么建立我不是很清楚:

  1. 我是否需要编写一个 rake 任务来启动/停止/重新加载机器人
  2. 如果我在没有 rake 的情况下运行它(假设是一个由 Monit 监控的独立进程),那么我如何与 Resque 交互或访问我的 rails 模型?

我知道这些可能是非常微不足道的问题,但我很难理解哪个效果更好,以及如何进行设置。

4

3 回答 3

4

在 Rails 应用程序和这个 bot 守护程序之间可以通过三种方式进行通信:

  1. 通过将 Rails 应用程序作为 HTTP 请求调用(从 Rails 应用程序推送/拉取数据)
  2. 通过直接与 Rails 应用程序使用的数据库交互(可能是 Mysql/Postgres)
  3. 通过与 Redis 数据库支持的 Resque 工作队列系统交互

当您将 Resque 作业排入队列并将其从各种作业队列中拉出时,您只是通过 API 读取/写入共享的 Redis 数据库。机器人和 Rails 应用程序都通过网络与 Redis DB 通信。

我建议直接将机器人作为 ruby​​ 进程或由 monit 管理的 rake 任务运行。听起来您已经知道如何做到这一点。

于 2013-01-28T16:46:09.507 回答
2

我认为这里的主要问题是您需要另一种消息传递解决方案(类似 IPC,而不是 IM),而不是试图弯曲“只是”一个队列的 Resque。其中一些选项是amqp gem(AMQP 协议)或zmq gem(ZeroMQ 协议),但您也可以通过 Ruby 标准库 Socket 类(很好的示例)使用普通的旧 UNIX 套接字。它们都有不同的优点和缺点,所以这取决于你和你的需求。

交互可能如下所示:

  1. 机器人启动。
  2. Bot 开始侦听 IPC 消息。
  3. Bot 接收来自发件人的查询(通过 XMPP)。
  4. Bot 通过 Resque 对作业进行排队。
  5. Job 通过 HTTP 调用 Rails 应用程序。
  6. Rails 应用程序完成了它的工作。
  7. 某人或某事解决了任何查询并通过 Rails 应用程序输入结果。
  8. Rails 应用程序使用某种 IPC 方法将结果发送到机器人。
  9. Bot 将结果发送给原始发件人(通过 XMPP)。

可以像往常一样进行一些更改。例如,我认为您根本不需要 Resque。机器人可以简单地将请求立即传递给 Rails 应用程序。但是,这取决于负载、您想要实现的响应时间、您当前的架构等。也许 Resque 作业可以等待 Rails 应用程序返回结果,然后该作业(而不是 Rails 应用程序)将使用 IPC。还有其他变体……</p>

我是否需要编写一个 rake 任务来启动/停止/重新加载机器人

不,你没有。如何以及何时运行它取决于您。毕竟,Rake 可以被视为将多个 Ruby 脚本放在一起并在它们之间创建依赖关系的便捷方式。如果您认为除了运行机器人之外还有其他任务(一些清理、部署等),那么为了方便起见,使用 Rake 会很好。如果您还没有,请将机器人的逻辑重构为类并使用 Rake 任务对其进行初始化。但是,如果您离开它也可以,只需按原样运行您的脚本(使用 monit、您的自定义 init.d 脚本、ad-hoc 等)。

如果我在没有 rake 的情况下运行它(假设是一个由 Monit 监控的独立进程),那么我如何与 Resque 交互或访问我的 rails 模型?

Rake 对此没有任何影响。从操作系统的角度来看,如果您通过 Rake 运行 Resque 并通过 Rake 运行您的机器人或作为独立脚本运行,这并不重要。无论如何,它们将是不同的过程。另外,请记住,Resque 需要 Redis 在某个地方运行。

我知道这些可能是非常琐碎的问题

一点也不。我认为需要一些时间才能将诸如此类的问题视为微不足道的问题。

于 2013-02-03T04:36:41.913 回答
0

你可以把你的代码放在一个初始化器上运行,并且可以完全访问你所有的 Rails 模型或库。

这样,您就不需要在您的机器人和您的 Rails 应用程序之间“通信”,因为您的机器人在您的 Rails 应用程序中。

样板代码如下:

配置/初始化程序/background_app_tasks.rb

class BackgroundWorker

      #-------------------------------
      def initialize(operation='normal')
        @exit = false
        @lock = Mutex.new  # For thread safety
        @thread = nil
        say "Starting in '#{operation}' mode..."
        case operation
          when 'normal'
            @thread = Thread.new() {    loopme     }
          when 'cleanup'
            @thread = Thread.new() {    cleanup     }
          when 'nothing'
            #startup without threads
        end
        @thread.run if @thread
      end

      #-------------------------------
      def exit!
        begin
            return if @exit # #stop?
            say   "Exiting #{}, waiting for mutex..."
            @lock.synchronize {
                say "exiting thread #{@thread.to_s || '<sem nome>' }..."
                @exit = true # #stop
            }
        rescue Exception => e
            exceptme(e)
        end
      end

      #-------------------------------
      def loopme

        at_exit { exit! }
        i=0;  ok=false;

        nap = 30

        while true do
          begin
              break if @exit
              i+=1

              #lock mutex for processing...
              @lock.synchronize {

                  #.... do some work ....

              }
          rescue StandardError => e

              #....

          end

          sleep(nap)
        end 
      end

end #class

# ------ M A I N --------

Thread.abort_on_exception=false
e = BackgroundWorker.new(OPERATION)
于 2015-12-17T11:02:54.467 回答