简体   繁体   English

如何在Rails中用RabbitMQ实现RPC?

[英]How to implement RPC with RabbitMQ in Rails?

I want to implement an action that calls remote service with RabbitMQ and presents returned data. 我想实现一个使用RabbitMQ调用远程服务并显示返回数据的操作。 I implemented this (more as a proof of concept so far) in similar way to example taken from here: https://github.com/baowen/RailsRabbit and it looks like this: 我以类似于此处的示例的方式实现了这一点(到目前为止,作为概念证明): https : //github.com/baowen/RailsRabbit ,它看起来像这样:

controller: 控制器:

def rpc
  text = params[:text]
  c = RpcClient.new('RPC server route key')
  response = c.call text
  render text: response
end

RabbitMQ RPC client: RabbitMQ RPC客户端:

class RpcClient < MQ
  attr_reader :reply_queue
  attr_accessor :response, :call_id
  attr_reader :lock, :condition

  def initialize()
    # initialize exchange:

    conn = Bunny.new(:automatically_recover => false)
    conn.start
    ch = conn.create_channel

    @x = ch.default_exchange
    @reply_queue = ch.queue("", :exclusive => true)
    @server_queue = 'rpc_queue'

    @lock = Mutex.new
    @condition = ConditionVariable.new
    that = self

    @reply_queue.subscribe do |_delivery_info, properties, payload|
      if properties[:correlation_id] == that.call_id
        that.response = payload.to_s
        that.lock.synchronize { that.condition.signal }
      end
    end
  end

  def call(message)
    self.call_id = generate_uuid
    @x.publish(message.to_s,
               routing_key: @server_queue,
               correlation_id: call_id,
               reply_to: @reply_queue.name)

    lock.synchronize { condition.wait(lock) }
    response
  end

  private

  def generate_uuid
    # very naive but good enough for code
    # examples
    "#{rand}#{rand}#{rand}"
  end
end

A few tests indicate that this approach works. 一些测试表明此方法有效。 On the other hand, this approach assumes creating a client (and subscribing to the queue) for every request on this action, which is inefficient according to the RabbitMQ tutorial . 另一方面,此方法假定为此操作上的每个请求都创建一个客户端(并订阅队列),根据RabbitMQ教程 ,这效率很低。 So I've got two questions: 所以我有两个问题:

  1. Is it possible to avoid creating a queue for every Rails request? 是否可以避免为每个Rails请求创建队列?
  2. How will this approach (with threads and mutex) interfere with my whole Rails environment? 这种方法(带有线程和互斥锁)将如何干扰我的整个Rails环境? Is it safe to implement things this way in Rails? 在Rails中以这种方式实现事情安全吗? I'm using Puma as my web server, if it's relevant. 如果相关,我正在将Puma用作Web服务器。

Is it possible to avoid creating a queue for every Rails request? 是否可以避免为每个Rails请求创建队列?

Yes - there is no need for every single request to have it's own reply queue. 是的-不需要每个单独的请求都有自己的回复队列。

You can use the built-in direct-reply queue. 您可以使用内置的直接答复队列。 See the documentation here . 请参阅此处的文档

If you don't want to use the direct-reply feature, you can create a single reply queue per rails instance. 如果您不想使用直接回复功能,则可以为每个rails实例创建一个回复队列。 You can use a single reply queue, and have the correlation id help you figure out where the reply needs to go within that rails instance. 您可以使用单个答复队列,并具有相关性ID来帮助您确定答复需要在该Rails实例中到达的位置。

How will this approach (with threads and mutex) interfere with my whole Rails environment? 这种方法(带有线程和互斥锁)将如何干扰我的整个Rails环境? Is it safe to implement things this way in Rails? 在Rails中以这种方式实现事情安全吗?

what's the purpose of the lock / mutex in this code? 这段代码中锁/互斥的目的是什么? doesn't seem necessary to me, but i'm probably missing something since i haven't done ruby in about 5 years :) 对我来说似乎没有必要,但是由于我大约5年没有做过红宝石,所以我可能缺少了一些东西:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM