在项目中引入RabbitMQ通常会考虑它会带来的好处:解耦应用程序,实现不同编程语言之间的互通,解除对特定通信协议的依赖,解除应用程序在时序上执行的依赖(异步).落实到代码层面就是两种常用应用模式:"发后即忘"(fire-and-forget)和RPC.
fire-and-forget
RPC
这里有两件事情要保证:1.要为队列创建随机Name 2.即使Name随机还是有可能冲突,还需要保证消息通信的独占性,看看RabbitMQ是怎么满足这两点的:
[1] 之前提到过,如果创建的队列不指定queue name,RabbitMQ就会创建一个随机的Name.
[2] 独占只需要exclusive参数即可
总而言之,需要做的就是Client创建一个temporary,exclusive,anonymou的queue,并把queue name设置在RPC 消息的reply_to字段即可.注意这里RPC Server已经知道要投递到哪个Queue,所以不需要指定Exchange(后面我们会提到在实现层面Queue和Exchange的不同,简单讲queue会有对应的Erlang进程,而exchang只是执行一些模式匹配的检查并没有进程实体对应).看下图:
略有不同
传统的RPC调用Client和Server紧密依赖,客户端连接上服务器,发送一个请求然后阻塞等待服务器响应.这样的做的特点是客户端和服务器端是知道对方的.如果RPC Server崩溃掉,客户端需要重连,如果Server彻底崩掉就要重新找一个提供同样服务的Server,然后客户端重连过去.
用RabbitMQ来实现RPC,依然保持Client Server信息隐藏的特点,Client依赖的不是特定的Server而是特定的消息,在有多个等效Server的情况下,一个Server的状态是否正常不会影响到客户端的状态.
总结一下,使用RabbitMQ是先RPC,客观上还实现了下面的效果:
- 容错 一个Server崩溃不影响 Client
- 解耦了对特定通信协议和接口的依赖,统一走AMQP消息.
- 在多个RPC Server之间的负载均衡由RabbitMQ完成
RabbitMQ 入门文档中专门提到了RPC的场景,Python和Java版本的代码都有,很容易写一个.net版本这里不再堆叠,请移步这里:
http://www.rabbitmq.com/tutorials/tutorial-six-python.html