繁体   English   中英

如何在Rails中用RabbitMQ实现RPC?

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

我想实现一个使用RabbitMQ调用远程服务并显示返回数据的操作。 我以类似于此处的示例的方式实现了这一点(到目前为止,作为概念证明): https : //github.com/baowen/RailsRabbit ,它看起来像这样:

控制器:

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

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

一些测试表明此方法有效。 另一方面,此方法假定为此操作上的每个请求都创建一个客户端(并订阅队列),根据RabbitMQ教程 ,这效率很低。 所以我有两个问题:

  1. 是否可以避免为每个Rails请求创建队列?
  2. 这种方法(带有线程和互斥锁)将如何干扰我的整个Rails环境? 在Rails中以这种方式实现事情安全吗? 如果相关,我正在将Puma用作Web服务器。

是否可以避免为每个Rails请求创建队列?

是的-不需要每个单独的请求都有自己的回复队列。

您可以使用内置的直接答复队列。 请参阅此处的文档

如果您不想使用直接回复功能,则可以为每个rails实例创建一个回复队列。 您可以使用单个答复队列,并具有相关性ID来帮助您确定答复需要在该Rails实例中到达的位置。

这种方法(带有线程和互斥锁)将如何干扰我的整个Rails环境? 在Rails中以这种方式实现事情安全吗?

这段代码中锁/互斥的目的是什么? 对我来说似乎没有必要,但是由于我大约5年没有做过红宝石,所以我可能缺少了一些东西:)

暂无
暂无

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

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