RabbitMQ(六) ——RPC模式

RabbitMQ(六)——RPC模式

(原创内容,转载请注明来源,谢谢)

一、概述

RabbitMQ的RPC模式,支持生产者和消费者不在同一个系统中,即允许远程调用的情况。通常,消费者作为服务端,放置在远程的系统中,提供接口,生产者调用接口,并发送消息。

RPC模式如下图所示:

RPC模式是一种远程调用的模式,因为需要http请求,因此速度比系统内部调用慢。而且rpc模式下,通常不易区分哪些是来自外部的请求,哪些是内部的请求,导致整体速度较慢。因此,不能滥用rpc模式。

二、回调队列(Callback queue)

要实现rpc模式,生产者需要发送回调队列。方法如下:

list($queue_name,,) = $channel->queue_declare("", false, false, true, false);
$msg = newAMQPMessage(
    $payload,
    array('reply_to' => $queue_name));
$channel->basic_publish($msg,'', 'rpc_queue');

三、AMQP消息属性

AMQP是一种消息传输协议,RabbitMQ是基于此协议的组件。其中,对消息(Message)的属性,有如下几个常用定义:

1)delivery_mode

消息的模式,当该值是2,表示消息需要持久化;当值是1,表示该消息不用持久化。

2)content_type

消息的类型,用来标记消息编码的类型,通常采用json,则此值是application/json,类似在HTML中的定义。

3)reply_to

用于定义回调队列的名字。

4)correlation_id

用于关联rpc的消息请求发送与消息响应接收。(request 和 response)

四、correlation_id

采用回调队列的方式,效率不够高,rabbitMQ还提供了一种方式,即correlation_id。对于每个请求,可以设定一个特定的、唯一的correlation_id。则当收到回复时,仍查看回复消息的此属性,则可以将请求和响应进行关联。

此时,当接收的correlation_id不存在,则表示该响应不是对该生产者发送请求的响应,生产者会丢弃接收到的消息。

采用抛弃消息,而不是报错,是因为服务端(消费者)可能存在竞争条件(race condition),因此存在可能,当服务器(消费者)刚刚发送ack回馈消息给客户端(生产者),服务器宕机。则服务器重启后,会重新发送ack给客户端。但是由于客户端在此之前,已经完成处理,则再次接收到correlation_id时,correlation_id不存在。因此,客户端对待重复的回复是采取抛弃消息的方式,而不是报错。

五、工作流程

1、生产者(Client)开始生产消息后,创建了匿名的、独一无二的回调队列。

2、生产者(Client)发送请求时,包含两个属性:reply_to,即回调队列;correlation_id,即用于标记请求的属性。

3、请求(request )被发送到rpc_queue队列。

4、消费者(The RPC worker)等待请求,收到时,其处理生产者发送的特定的reply_to的消息。

5、生产者等待消息的ack回复,当收到回复后,其校验correlation_id,如果正确则回到应用程序中。

——written by linhxx 2017.08.24

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-08-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xingoo, 一个梦想做发明家的程序员

简单的客户机服务器投射模拟

下面模拟了,简单的客户机服务器投射模拟的过程。客户机像服务器发送数据,服务器接受到数据后,发送回给客户机。再由客户机打印出来。 需要的函数: 网络方面 服务器 ...

1725
来自专栏linux驱动个人学习

Linux下0号进程的前世(init_task进程)今生(idle进程)----Linux进程的管理与调度(五)【转】

Linux下有3个特殊的进程,idle进程(PID = 0), init进程(PID = 1)和kthreadd(PID = 2)

662
来自专栏决胜机器学习

Redis专题(十一) ——Redis虚拟内存

Redis专题(十一) ——Redis虚拟内存 (原创内容,转载请注明来源,谢谢) 一、概述 Redis的数据是保存在内存中,当物理内存不足...

3168
来自专栏开发与安全

linux网络编程之socket(九):使用select函数改进客户端/服务器端程序

一、当我们使用单进程单连接且使用readline修改后的客户端程序,去连接使用readline修改后的服务器端程序,会出现一个有趣的现象,先来看输出: 先运行服...

2780
来自专栏owent

Redis全异步(HA)Driver设计稿

现在Redis的集群功能已经Release。但是并没有一个官方直接提供的高可用性的API可以使用。有的只有解决方案,Sentinel和Cluster。所以有必要...

631
来自专栏余林丰

【试验局】ReentrantLock中非公平锁与公平锁的性能测试

硬件环境:   CPU:AMD Phenom(tm) II X4 955 Processor   Memory:8G   SSD(128G):/   HDD(1...

1759
来自专栏开发与安全

linux网络编程之System V 信号量(三):基于生产者-消费者模型实现先进先出的共享内存段

生产者消费者问题:该问题描述了两个共享固定大小缓冲区的进程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到...

2200
来自专栏存储

spring boot redis分布式锁

随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁。分布式锁的实现有很多种,比如基于数据库、zookeeper等,本文主要介绍使用Redis做分布式锁...

4125
来自专栏软件测试经验与教训

LR windows 计数器

2646
来自专栏技术/开源

TypeScript设计模式之备忘录、命令

看看用TypeScript怎样实现常见的设计模式,顺便复习一下。 学模式最重要的不是记UML,而是知道什么模式可以解决什么样的问题,在做项目时碰到问题可以想到...

1876

扫码关注云+社区