RabbitMQ 的请求/响应模式 已翻译 100%

oschina 投递于 2013/11/03 08:46 (共 6 段, 翻译完成于 11-03)
阅读 8992
收藏 57
2
加载中

如果你正在进行web服务编程,那么最常用的模式是请求-响应模式。这种模式总是由客户端发起,然后等待服务器端的响应。如果客户端想发送一些信息给服务器,或者客户端按照某些标准请求一些信息,那么这种模式非常适合。如果服务器想自己发送信息给客户端,那么这种模式就非常不适合。这时我们就必须依赖像长轮询或者web挂钩这样的对HTTP进行某种程度扩展的技巧了。

而对消息系统来说,最常用的模式是发送-接收模式。生产者节点发布一条信息,接下来这条信息会被传送给消费节点。这儿没有纯粹的客户端或者服务器的概念;节点可以是生产者,也可以是消费者,或者二者兼有。当一个节点想发送一些信息给另一个节点或者相反,这种模式都运行的非常好,不过,如果一个节点想按照某些标准向另一个节点请求信息,那么这种模式就不是很适合。

几点人
几点人
翻译于 2013/11/03 09:48
2

然而,这一切并不是完全做不到。我们可以模仿请求-应答模式:让客户端创建一个应答队列,这个队列存储客户端发送给服务器的查询消息的应答。客户端可以设置请求消息的reply_to属性字段为应答队列名。服务器检查reply_to子段,然后通过默认的整理中心把应答消息发布给应答队列,接着这个消息就由客户端接收。

request-response

请求端的实现很简单;它看起来就像标准的发送-接收模式。而对于应答端,我们可以有多个选择。如果你通过谷歌搜寻"RabbitMQ RPC"或者"RabbitMQ request response",你就发现有关应答队列的性质方面有几个不同的意见:

  • 每个请求是不是应该对应一个应答队列,或者客户端对多个请求是不是应该只维护一个应答队列?
  • 应答队列是不是应该是独享的,即只可用于一个通道,或者应该不是独享的?注意:当通道关闭的时候,独享队列应该删除,无论是有意,还是网络中断或者转发网关失效,都能引起连接丢失。

让我们看看这些意见的优点和缺点。

几点人
几点人
翻译于 2013/11/03 10:28
3

每个请求独享一个应答队列

这种情况下,每个请求创建一个应答队列。好处是实现起来简单。把响应与请求关联起来也没有问题,因为每个请求都有它自己对应的响应消费者。如果客户端与代理之间的连接在响应接收之前就断开了,那么代理就会清除掉剩余的应答队列,这时就会丢失响应的消息。

实现这个的主要问题是:倘若由于服务器问题引起服务器无法发布响应,那么我们必须清除所有的应答队列。

这种方式有很大的性能开销,因为它对每个请求都要创建一个新的队列和消费者。

几点人
几点人
翻译于 2013/11/03 11:16
2

每个客户端独享一个应答队列

这种情况下,每个客户端连接维护着由许多请求共享的应答队列。这减少了对每个请求都要创建队列和消费者所造成的性能开销,不过它增加了客户端需要跟踪应答队列并且把应答与各自对应的请求匹配方面的开销。处理这个的标准办法是使用关联id,服务器可以从响应所对应的请求里拷贝这个id。

再次说明一下,在客户端断开的时候,删除应答队列没有任何问题,因为转发网关会自动删除队列的。然而,这确实意味着断开的那个时刻的仍在传输的任何响应都将丢失。

几点人
几点人
翻译于 2013/11/03 11:18
2

永久应答队列

上面两种情形都存在这样的问题:如果客户端和转发网关之间的连接断开,并且响应还处在运行状态,那么这些响应就会丢失。这是因为它们使用的是独享型的队列,也就是说,当拥有这个队列的连接关闭的时候,转发网关必须删除这个队列。

针对这个问题的常见的解决办法就是使用非独享型的应答队列。不过这会引起一些管理开销。你需要采用某种方式命名应答队列,并把它与特定的客户端关联起来。问题是:客户端很难知道一个应答队列是属于自己的,还是属于另一个客户端的。不过随意地创建一个可把响应发送给不对应的客户端这样的环境却非常容易。你可能最终要手工创建和命名响应队列,这么做就没有了第一种情况下可根据消息选择代理的好处了。

几点人
几点人
翻译于 2013/11/03 11:21
2

EasyNetQ

对一个像EasyNetQ这样高级的可重用的库来说,不可能实现永久应答队列。因为没有明确的方法知道EasyNetQ库的具体实例是属于客户端应用的哪一种逻辑实例。这儿的“逻辑实例”我指的是可能停止的和可能已经启动的单个逻辑实例,与此对应的是同一个客户端具有两个独立的实例。

因此,我们必须使用独享型队列,并且要接受响应消息的偶尔丢失。实现超时机制是非常重要的,这样如果出现响应丢失,那么就向客户端应用抛出一个异常。理想情况下,客户端将捕捉这个异常,然后在适当的情况下重新发送这条消息。

目前EasyNetQ实现了"每个请求独享一个应答队列“这种模式,而且我们正在有计划地修改这种模式为”每个客户端独享一个应答队列“模式。要求把响应与请求匹配起来的开销不能太多,还要求既要高效又要易于管理。

我非常有兴趣听取其他人在用RabbitMQ实现请求-发送模式的经验。

几点人
几点人
翻译于 2013/11/03 11:48
2
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(13)

qwfys
qwfys
^_^
a
autocoder

引用来自“几点人”的评论

引用来自“摩云飞”的评论

引用来自“几点人”的评论

引用来自“摩云飞”的评论

翻译的水平不行啊,很多地方翻译出来的都不是原文的意思了,特定名字的翻译也不准确,容易让刚开始了解RabbitMQ的人对基本概念产生困惑,看来译者不是真正研究过RabbitMQ的人。

感谢你对这篇翻译文章的评论,请指出具体词不达意的地方,以便我们讨论后订正。谢谢

exchange和broker的翻译感觉不够到位,尤其将broker翻译成“代理”感觉没有表达出原义。“处在运行状态的任何响应”这句容易让人产生疑惑,“响应”为何会有“运行状态”?原文 in flight 所表达出的含义用中文似乎不好简单的描述出来,索性白话一点也许更易理解 -- “处于传输过程中的任何响应”。

至于exchange翻译的时候我遇到了问题,Request Exchange 和Default Exchange是位于两个队列之前,译成交换点或者交换中心似乎都难以理解。经过多次斟酌后,我建议修改为整理点,或者整理中心,这样便于大家理解。如何?

译者的态度 比文章本身更有意义。赞一个。
摩云飞
摩云飞

引用来自“几点人”的评论

引用来自“摩云飞”的评论

引用来自“几点人”的评论

引用来自“摩云飞”的评论

翻译的水平不行啊,很多地方翻译出来的都不是原文的意思了,特定名字的翻译也不准确,容易让刚开始了解RabbitMQ的人对基本概念产生困惑,看来译者不是真正研究过RabbitMQ的人。

感谢你对这篇翻译文章的评论,请指出具体词不达意的地方,以便我们讨论后订正。谢谢

exchange和broker的翻译感觉不够到位,尤其将broker翻译成“代理”感觉没有表达出原义。“处在运行状态的任何响应”这句容易让人产生疑惑,“响应”为何会有“运行状态”?原文 in flight 所表达出的含义用中文似乎不好简单的描述出来,索性白话一点也许更易理解 -- “处于传输过程中的任何响应”。

至于exchange翻译的时候我遇到了问题,Request Exchange 和Default Exchange是位于两个队列之前,译成交换点或者交换中心似乎都难以理解。经过多次斟酌后,我建议修改为整理点,或者整理中心,这样便于大家理解。如何?

其实我也觉得不好翻译,无法给出一个准确的表达。唉,其实我觉得不翻译最好……
开源中国首席鉴定大湿
开源中国首席鉴定大湿
我建议Exchange就不要翻译。我们在讨论的时候,一般都是直接说Exchange的,这个确实很难翻译
几点人
几点人

引用来自“摩云飞”的评论

引用来自“几点人”的评论

引用来自“摩云飞”的评论

翻译的水平不行啊,很多地方翻译出来的都不是原文的意思了,特定名字的翻译也不准确,容易让刚开始了解RabbitMQ的人对基本概念产生困惑,看来译者不是真正研究过RabbitMQ的人。

感谢你对这篇翻译文章的评论,请指出具体词不达意的地方,以便我们讨论后订正。谢谢

exchange和broker的翻译感觉不够到位,尤其将broker翻译成“代理”感觉没有表达出原义。“处在运行状态的任何响应”这句容易让人产生疑惑,“响应”为何会有“运行状态”?原文 in flight 所表达出的含义用中文似乎不好简单的描述出来,索性白话一点也许更易理解 -- “处于传输过程中的任何响应”。

至于exchange翻译的时候我遇到了问题,Request Exchange 和Default Exchange是位于两个队列之前,译成交换点或者交换中心似乎都难以理解。经过多次斟酌后,我建议修改为整理点,或者整理中心,这样便于大家理解。如何?
几点人
几点人

引用来自“摩云飞”的评论

引用来自“几点人”的评论

引用来自“摩云飞”的评论

翻译的水平不行啊,很多地方翻译出来的都不是原文的意思了,特定名字的翻译也不准确,容易让刚开始了解RabbitMQ的人对基本概念产生困惑,看来译者不是真正研究过RabbitMQ的人。

感谢你对这篇翻译文章的评论,请指出具体词不达意的地方,以便我们讨论后订正。谢谢

exchange和broker的翻译感觉不够到位,尤其将broker翻译成“代理”感觉没有表达出原义。“处在运行状态的任何响应”这句容易让人产生疑惑,“响应”为何会有“运行状态”?原文 in flight 所表达出的含义用中文似乎不好简单的描述出来,索性白话一点也许更易理解 -- “处于传输过程中的任何响应”。

broker,一般译作:代理,中间人、中介,中间协调者。在这儿译作代理确实存在难以理解的问题,因此译为:转发网关,这样易于理解,直接用英文,我建议是尽量不这么做,我们的目标是翻译给大家,便于大家看得懂。in-flight由于是修饰的响应,所以我修改为正在传输的响应,如何?
摩云飞
摩云飞

引用来自“几点人”的评论

引用来自“摩云飞”的评论

翻译的水平不行啊,很多地方翻译出来的都不是原文的意思了,特定名字的翻译也不准确,容易让刚开始了解RabbitMQ的人对基本概念产生困惑,看来译者不是真正研究过RabbitMQ的人。

感谢你对这篇翻译文章的评论,请指出具体词不达意的地方,以便我们讨论后订正。谢谢

exchange和broker的翻译感觉不够到位,尤其将broker翻译成“代理”感觉没有表达出原义。“处在运行状态的任何响应”这句容易让人产生疑惑,“响应”为何会有“运行状态”?原文 in flight 所表达出的含义用中文似乎不好简单的描述出来,索性白话一点也许更易理解 -- “处于传输过程中的任何响应”。
几点人
几点人

引用来自“摩云飞”的评论

翻译的水平不行啊,很多地方翻译出来的都不是原文的意思了,特定名字的翻译也不准确,容易让刚开始了解RabbitMQ的人对基本概念产生困惑,看来译者不是真正研究过RabbitMQ的人。

感谢你对这篇翻译文章的评论,请指出具体词不达意的地方,以便我们讨论后订正。谢谢
junsun
junsun
各位觉得呢?
junsun
junsun
以前公司用 rabbitmq 来实现内部的远程调用(同步的),设计有问题,效率低下,我觉得这种消息中间件就适合做异步消息发送,接收,而通过它来实现类似RMI这种同步调用真的是效率低的
返回顶部
顶部