Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails:如何侦听/从服务或队列中提取?_Ruby On Rails_Rabbitmq_Apache Kafka_Microservices - Fatal编程技术网

Ruby on rails Rails:如何侦听/从服务或队列中提取?

Ruby on rails Rails:如何侦听/从服务或队列中提取?,ruby-on-rails,rabbitmq,apache-kafka,microservices,Ruby On Rails,Rabbitmq,Apache Kafka,Microservices,大多数Rails应用程序的工作方式都是等待来自客户机的请求,然后施展魔法。 但是,如果我想将Rails应用程序作为微服务体系结构的一部分(例如)使用一些异步通信(Serivce a将事件发送到Kafka或RabbitMQ队列,服务B(我的Rails应用程序)应该侦听该队列),如何调整/启动Rails应用程序以立即侦听队列并由队列中的事件触发?(这意味着初始触发器不是来自客户端,而是来自应用程序本身。) 谢谢你的建议 恐怕RabbitMQ至少需要一个客户端。RabbitMQ实现AMQP协议,而不是

大多数Rails应用程序的工作方式都是等待来自客户机的请求,然后施展魔法。 但是,如果我想将Rails应用程序作为微服务体系结构的一部分(例如)使用一些异步通信(Serivce a将事件发送到Kafka或RabbitMQ队列,服务B(我的Rails应用程序)应该侦听该队列),如何调整/启动Rails应用程序以立即侦听队列并由队列中的事件触发?(这意味着初始触发器不是来自客户端,而是来自应用程序本身。)


谢谢你的建议

恐怕RabbitMQ至少需要一个客户端。RabbitMQ实现AMQP协议,而不是web服务器使用的HTTP协议。正如Sergio上面提到的,Rails是一个web框架,因此它没有内置AMQP支持。您必须使用AMQP客户端(如Bunny)才能从Rails应用程序中订阅Rabbit队列。

假设服务a正在向Kafka队列发送一些事件,您可以使用Rails应用程序运行后台进程,该进程将查找Kafka队列并处理这些排队的消息。对于后台进程,您可以使用cron作业或sidekiq之类的东西。

我刚刚在应用程序中设置了RabbitMQ消息传递,并将在第二天左右为解耦(多个、分布式)应用程序实施。我发现这篇文章很有帮助(而且也很有用)。下面的所有代码都是针对RabbitMQ的,并且假设您有一个RabbitMQ服务器,并在本地机器上运行

以下是迄今为止我所拥有的——对我来说很有用:

  #Gemfile
  gem 'bunny'
  gem 'sneakers'
我有一个
发布者
,它向队列发送:

  # app/agents/messaging/publisher.rb
  module Messaging
    class Publisher
      class << self

        def publish(args)
          connection = Bunny.new
          connection.start
          channel = connection.create_channel
          queue_name = "#{args.keys.first.to_s.pluralize}_queue"
          queue = channel.queue(queue_name, durable: true)
          channel.default_exchange.publish(args[args.keys.first].to_json, :routing_key => queue.name)
          puts "in #{self}.#{__method__}, [x] Sent #{args}!"
          connection.close
        end

      end
    end
  end
然后我有了我的“听众”:

  # app/agents/messaging/events_queue_receiver.rb
  require_dependency "#{Rails.root.join('app','agents','messaging','events_agent')}"

  module Messaging
    class EventsQueueReceiver
      include Sneakers::Worker
      from_queue :events_queue, env: nil

      def work(msg)
        logger.info msg
        response = Messaging::EventsAgent.distribute(JSON.parse(msg).with_indifferent_access)
        ack! if response[:success]
      end

    end
  end
“侦听器”将消息发送到
消息传递::EventsAgent.distribute
,如下所示:

  Messaging::Publisher.publish(event: {... event details...})
  # app/agents/messaging/events_agent.rb
 require_dependency  #{Rails.root.join('app','agents','fsm','state_assignment_agent')}"

  module Messaging
    class EventsAgent
      EVENT_HANDLERS = {
        enroll_in_program: ["FSM::StateAssignmentAgent"]
      }
      class << self

        def publish(event)
          Messaging::Publisher.publish(event: event)
        end

        def distribute(event)
          puts "in #{self}.#{__method__}, message"
          if event[:handler]
            puts "in #{self}.#{__method__}, event[:handler: #{event[:handler}"
            event[:handler].constantize.handle_event(event)
          else
            event_name = event[:event_name].to_sym
            EVENT_HANDLERS[event_name].each do |handler|
              event[:handler] = handler
              publish(event)
            end
          end
          return {success: true}
        end

      end
    end
  end
以及:

我打开两个控制台窗口。在第一部分中,我说(让我的听众运行):

第二,我说:

  $ rails s --sandbox
  2.1.2 :001 > Messaging::Publisher.publish({:event=>{:event_name=>"enroll_in_program", :program_system_name=>"aha_chh", :person_id=>1}})
  in Messaging::Publisher.publish, [x] Sent {:event=>{:event_name=>"enroll_in_program", :program_system_name=>"aha_chh", :person_id=>1}}!
  => :closed 
然后,回到我的第一个窗口,我看到:

  2016-03-18T14:17:44Z p-5877 t-19nfxy INFO: {"event_name":"enroll_in_program","program_system_name":"aha_chh","person_id":1}
  in Messaging::EventsAgent.distribute, message
  in Messaging::EventsAgent.distribute, event[:handler]: FSM::StateAssignmentAgent
在我的RabbitMQ服务器中,我看到:

这是一个非常简单的设置,我相信我会在未来几天学到更多


祝你好运

Rails有很多功能。它的一部分处理web请求。其他部分(ActiveRecord)不关心您是web请求还是脚本或其他内容。Rails本身甚至没有一个适合生产的web服务器,您可以使用其他gem(例如,对于普通的旧web浏览器,
thin
,或者对于传入的SOAP请求,
wash_
)。Rails只为您提供了基础架构/中间件来组合所有与服务器相关的部分


除非您的队列能够以某种HTTP方式调用您的应用程序,例如以SOAP请求的形式调用,否则您将需要一些东西来侦听您的排队系统,不管它是什么,并将队列上的新“票证”转换为Rails世界中的控制器操作。

Rails是一个web框架。这就是它所做的,处理web请求。如果您需要监视作业/事件队列(kafka或其他什么),您需要使用其他工具。@Sergio Tulentsev您建议使用什么-只是一个手动Ruby脚本或其他Ruby框架,哪种语言对本例或其他语言有用?Aweasome reply@SergioTulentsev绝对没有增加任何价值。当然-我知道RabbitMQ和Rails之间需要一些软件。但我的理解/希望是,这个客户端可以在Rails应用程序中被称为/can life!?如果是,我将如何“触发”订阅过程?(还有:如何处理事件以便我可以在我的应用程序的rails上下文中处理它们?)RabbitMQ客户端可以在rails应用程序中使用。您可以让Rails运行后台任务,该任务将维护队列订阅并处理传入消息。根据你告诉我的,图书馆对你来说可能比兔子更好。它适用于队列处理在后台进行的情况。
  $ WORKERS=Messaging::EventsQueueReceiver rake sneakers:run
  ... a bunch of start up info
  2016-03-18T14:16:42Z p-5877 t-14d03e INFO: Heartbeat interval used (in seconds): 2
  2016-03-18T14:16:42Z p-5899 t-14d03e INFO: Heartbeat interval used (in seconds): 2
  2016-03-18T14:16:42Z p-5922 t-14d03e INFO: Heartbeat interval used (in seconds): 2
  2016-03-18T14:16:42Z p-5944 t-14d03e INFO: Heartbeat interval used (in seconds): 2
  $ rails s --sandbox
  2.1.2 :001 > Messaging::Publisher.publish({:event=>{:event_name=>"enroll_in_program", :program_system_name=>"aha_chh", :person_id=>1}})
  in Messaging::Publisher.publish, [x] Sent {:event=>{:event_name=>"enroll_in_program", :program_system_name=>"aha_chh", :person_id=>1}}!
  => :closed 
  2016-03-18T14:17:44Z p-5877 t-19nfxy INFO: {"event_name":"enroll_in_program","program_system_name":"aha_chh","person_id":1}
  in Messaging::EventsAgent.distribute, message
  in Messaging::EventsAgent.distribute, event[:handler]: FSM::StateAssignmentAgent