在云计算环境中,很多时候需要用它其他机器的计算资源,把一部分计算任务分配到其他节点来完成。RabbitMQ 如何使用 RPC 呢?下面将会通过其它节点完成斐波纳契示例。

流程图

  • 当客户端启动时,它创建了匿名的 callback queue
  • 客户端发起 RPC 请求时将同时设置两个 properties:reply_to 设置为 callback queue;correlation_id 设置为每个请求都是独一无二的值
  • 请求将被发送到一个 rpc_queue 队列
  • RPC 端或者说 Server 一直在等待那个 queue 的请求,当请求到达时,它将通过在 reply_to 指定的 queue 回复一个 Message 给客户端
  • client 一直等待 callback queue 的数据,当 Message 到达时,它将检查 correlation_id 的值,如果值和它 request 发送时的一致那么就将返回响应

整合代码

rpc_client.php

<?php

/**
* RPC客户端
*/
$routing_key = 'rpc_queue';
$num = empty($argv[1]) ? 0 : intval($argv[1]); // 建立TCP连接
$connection = new AMQPConnection([
'host' => 'localhost',
'port' => '5672',
'vhost' => '/',
'login' => 'guest',
'password' => 'guest'
]);
$connection->connect() or die("Cannot connect to the broker!\n"); $channel = new AMQPChannel($connection); $client_queue = new AMQPQueue($channel);
$client_queue->setFlags(AMQP_EXCLUSIVE);
$client_queue->declareQueue();
$callback_queue_name = $client_queue->getName(); $corr_id = uniqid();
$properties = [
'correlation_id' => $corr_id,
'reply_to' => $callback_queue_name
]; $exchange = new AMQPExchange($channel);
$exchange->publish($num, $routing_key, AMQP_NOPARAM, $properties); $client_queue->consume(function($envelope, $queue) use ($corr_id){
if ($envelope->getCorrelationId() == $corr_id) {
$msg = $envelope->getBody();
var_dump('Received Data: ' . $msg);
$queue->nack($envelope->getDeliveryTag());
return false;
}
}); // 断开连接
$connection->disconnect();

rpc_server.php

<?php

/**
* RPC服务端
*/
$routing_key = 'rpc_queue'; // 建立TCP连接
$connection = new AMQPConnection([
'host' => 'localhost',
'port' => '5672',
'vhost' => '/',
'login' => 'guest',
'password' => 'guest'
]);
$connection->connect() or die("Cannot connect to the broker!\n"); $channel = new AMQPChannel($connection);
$channel->setPrefetchCount(1); $server_queue = new AMQPQueue($channel);
$server_queue->setName($routing_key);
$server_queue->declareQueue(); $exchange = new AMQPExchange($channel); $server_queue->consume(function($envelope, $queue) use ($exchange){
$num = intval($envelope->getBody());
$response = fib($num);
$exchange->publish($response, $envelope->getReplyTo(), AMQP_NOPARAM, [
'correlation_id' => $envelope->getCorrelationId(),
]);
$queue->ack($envelope->getDeliveryTag());
}); // 断开连接
$connection->disconnect(); // 斐波那契函数
function fib($num) {
if ($num == 0)
return 1;
else if ($num == 1)
return 1;
else
return fib($num - 1) + fib($num - 2);
}

先运行脚本:

php rpc_server.php

再运行另外的脚本:

php rpc_client.php 1
php rpc_client.php 5
php rpc_client.php 15
php rpc_client.php 20

效果展示:

RabbitMQ 入门教程(PHP版) 第六部分:远程调用(RPC)的更多相关文章

  1. RabbitMQ 入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)

    发布/订阅 在上篇第二部分教程中,我们搭建了一个工作队列.每个任务之分发给一个工作者(worker).在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers).这种模式 ...

  2. RabbitMQ 入门教程(PHP版) 第二部分:工作队列(Work queues)

    工作队列 在第一篇教程中,我们已经写了一个从已知队列中发送和获取消息的程序.在这篇教程中,我们将创建一个工作队列(Work Queue),它会发送一些耗时的任务给多个工作者(Works ). 工作队列 ...

  3. RabbitMQ 入门教程(PHP版) 第一部分:Hello World

    abbitMQ是一个消息代理.它的核心原理非常简单:接收和发送消息.你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处.在这个比喻中,RabbitMQ是一个邮箱.邮局.邮递 ...

  4. RabbitMQ 入门教程(PHP版) 使用rabbitmq-delayed-message-exchange插件实现延迟功能

    延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ...

  5. RabbitMQ 入门教程(PHP版) 延迟队列,延迟任务

    延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ...

  6. RabbitMQ 入门教程(PHP版) 简单Demo

    RabbitMQ的关键字说明 (1)Broker:经纪人.提供一种传输服务,维护一条从生产者到消费者的传输线路,保证消息数据能按照指定的方式传输.粗略的可以将图中的RabbitMQ Server当作B ...

  7. RabbitMQ 入门教程(PHP版) 第四部分:路由(Routing)

    路由(Routing) 在前面的第三部分教程中,我们实现了一个简单的日志系统.可以把日志消息广播给多个接收者. 本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集.例如,我们只需要把严重 ...

  8. 转 RabbitMQ 入门教程(PHP版) 使用rabbitmq-delayed-message-exchange插件实现延迟功能

    延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ...

  9. RabbitMQ 入门教程(PHP版) 第五部分:通过主题进行消息分发(Topics)

    对于 Message 的 routing_key 字符串格式是有限制的:以点号"."分割的字符表,如php.laravel,并且长度不能超过 255 个字节. 对于 routing ...

随机推荐

  1. destoon6.0搜索页熊掌号页面改造技巧【原创】

    大家都知道,DT官方是封禁搜索页的,是不让百度蜘蛛抓取的,但是搜索页又是大型网站优化的重点,今天来说说关于DT6.0搜索页熊掌号的改造方法,如果您要改造内容页面可以查看我前几期的分享! 首先要开启百度 ...

  2. js通过html的url获取参数值

    function getUrlParameter(name){ name = name.replace(/[]/,"\[").replace(/[]/,"\[" ...

  3. Linux Shell 如何获取参数

    $# 是传给脚本的参数个数 $0 是脚本本身的名字 $1 是传递给该shell脚本的第一个参数 $2 是传递给该shell脚本的第二个参数 $@ 是传给脚本的所有参数的列表 $* 是以一个单字符串显示 ...

  4. php之大文件断点续传

    前段时间做视频上传业务,通过网页上传视频到服务器. 视频大小 小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:1,文件过大,超出服务端的请求大小限制:2,请求时间过长, ...

  5. java文件夹上传下载组件

    核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...

  6. C语言实现金字塔

    #include <stdio.h> int main(void) { int i=0, j =0, k= 0, line; printf("请输入金字塔的总行数:") ...

  7. luogu P1058 立体图

    做了这个题后明确了自己的定位... 恩...普及- 题目大意估计都知道.. 给个传送门:   luogu 做了半上午 + 一整个下午的题... 占了我今天到的绝大多数时间. 其实此题不难, 核心代码我 ...

  8. Day15:大前端

    垂直水平居中 css: display: table-cell; text-align: center; vertical-align: middle; div: display: inline-bl ...

  9. [WC2010]重建计划(长链剖分版)

    传送门 Description Solution 时隔多年,补上了这题的长链剖分写法 感觉比点分治要好写的多 我们假设\(pos\)是当前点的\(dfn\),它距离所在链的底端的边的数量是\(len\ ...

  10. 生成uuid 和 检验

    //注意replaceAll前面的是正则表达式 String uuid = UUID.randomUUID().toString().replaceAll("-","&q ...