簡體   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