【发布时间】:2016-01-21 14:27:46
【问题描述】:
我想实现一个使用 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 tutorial,这是低效的。所以我有两个问题:
- 是否可以避免为每个 Rails 请求创建队列?
- 这种方法(使用线程和互斥锁)将如何干扰我的整个 Rails 环境?在 Rails 中以这种方式实现是否安全?我使用 Puma 作为我的网络服务器,如果它是相关的。
【问题讨论】:
-
您可以尝试使用用于数据库连接的
RuntimeRegistry模拟活动记录的方法github.com/rails/rails/blob/master/activerecord/lib/…
标签: ruby-on-rails ruby multithreading rabbitmq rpc