rabbitmq (五)RPC
Remote Procedure Call or RPC(远程函数调用)
当我们需要在远程计算机上运行一个函数,并且等待结果的时候,我们用到RPC
在rabbitmq客户端使用call函数,发送RPC请求并阻塞等待结果返回.
提示:虽然RPC是一个很好计算处理的常见模式,但是有时程序员无法判断
一个函数调用时一个本地调用还是一个缓慢的RPC调用.所以有很多错误的不可预知的结果.
并且增加调试的复杂性.
有三个建议:
1.确定函数调用时本地还是远程调用.
2.给系统添加文档,确定各个组件之间的依赖
3.处理每个RPC调用过程中的异常,
callback queue
因为通常订阅/发布是一个单向过程,只需要一个队列,但是在RPC调用的时候需要制定两个队列,一个发送,一个接受结果.所以用ReplyTo属性指定接受结果队列名称.
correlation Id
为每一个RPC调用创建一个callback queue是低效的,所以可以使用一个公用的callback queue使用关联id来标识每个请求.
源码:
客户端
public class RpcClient
{
private readonly IConnection connection;
private readonly IModel channel;
private readonly string replyQueueName;
private readonly EventingBasicConsumer consumer;
private readonly BlockingCollection<string> respQueue = new BlockingCollection<string>();
private readonly IBasicProperties props; public RpcClient()
{
var factory = new ConnectionFactory() { HostName = "your ip", UserName = "your name", Password = "your pwd" }; connection = factory.CreateConnection();
channel = connection.CreateModel();
replyQueueName = channel.QueueDeclare().QueueName;
consumer = new EventingBasicConsumer(channel); props = channel.CreateBasicProperties();
var correlationId = Guid.NewGuid().ToString();
props.CorrelationId = correlationId;
props.ReplyTo = replyQueueName; consumer.Received += (model, ea) =>
{
var body = ea.Body;
var response = Encoding.UTF8.GetString(body);
if (ea.BasicProperties.CorrelationId == correlationId)
{
respQueue.Add(response);
}
};
} public string Call(string message)
{
var messageBytes = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(
exchange: "",
routingKey: "rpc_queue",
basicProperties: props,
body: messageBytes); channel.BasicConsume(
consumer: consumer,
queue: replyQueueName,
autoAck: true); return respQueue.Take(); ;
} public void Close()
{
connection.Close();
}
}
class Program
{
static void Main(string[] args)
{
var rpcClient = new RpcClient(); Console.WriteLine(" [x] Requesting fib(30)");
var response = rpcClient.Call(""); Console.WriteLine(" [.] Got '{0}'", response);
rpcClient.Close();
}
}
服务端:
public static void Main()
{
var factory = new ConnectionFactory() { HostName = "your ip", UserName = "your name", Password = "your pwd" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "rpc_queue", durable: false,
exclusive: false, autoDelete: false, arguments: null);
channel.BasicQos(, , false);
var consumer = new EventingBasicConsumer(channel);
channel.BasicConsume(queue: "rpc_queue",
autoAck: false, consumer: consumer);
Console.WriteLine(" [x] Awaiting RPC requests"); consumer.Received += (model, ea) =>
{
string response = null; var body = ea.Body;
var props = ea.BasicProperties;
var replyProps = channel.CreateBasicProperties();
replyProps.CorrelationId = props.CorrelationId; try
{
var message = Encoding.UTF8.GetString(body);
int n = int.Parse(message);
Console.WriteLine(" [.] fib({0})", message);
response = fib(n).ToString();
}
catch (Exception e)
{
Console.WriteLine(" [.] " + e.Message);
response = "";
}
finally
{
var responseBytes = Encoding.UTF8.GetBytes(response);
channel.BasicPublish(exchange: "", routingKey: props.ReplyTo,
basicProperties: replyProps, body: responseBytes);
channel.BasicAck(deliveryTag: ea.DeliveryTag,
multiple: false);
}
}; Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
} /// /// Assumes only valid positive integer input.
/// Don't expect this one to work for big numbers, and it's
/// probably the slowest recursive implementation possible.
/// private static int fib(int n)
{
if (n == || n == )
{
return n;
} return fib(n - ) + fib(n - );
}
rabbitmq (五)RPC的更多相关文章
- RabbitMQ(四):RPC的实现
原文:RabbitMQ(四):RPC的实现 一.RPC RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. ...
- RabbitMQ 实现RPC
实现RPC 首先要弄明白,RPC是个什么东西. (RPC) Remote Procedure Call Protocol 远程过程调用协议 在一个大型的公司,系统由大大小小的服务构成,不同的团队维护不 ...
- RabbitMQ中RPC的实现及其通信机制
RabbitMQ中RPC的实现:客户端发送请求消息,服务端回复响应消息,为了接受响应response,客户端需要发送一个回调队列的地址来接受响应,每条消息在发送的时候会带上一个唯一的correlati ...
- 基于RabbitMQ的Rpc框架
参考文档:https://www.cnblogs.com/ericli-ericli/p/5917018.html 参考文档:RabbitMQ 实现RPC MQ的使用场景大概包括解耦,提高峰值处理能力 ...
- RabbitMQ除开RPC的五种消模型----原生API
2.五种消息模型 RabbitMQ提供了6种消息模型,但是第6种其实是RPC,并不是MQ,因此不予学习.那么也就剩下5种. 但是其实3.4.5这三种都属于订阅模型,只不过进行路由的方式不同. 通过一个 ...
- RabbitMQ 笔记-RPC
RabbitMQ中实现RPC的机制是: 客户端发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14中properties,这些属性会随着消息一起发送)中设置 ...
- RabbitMQ、RPC、SaltStack "贡"具的使用
消息队列 使用队列的场景 在程序系统中,例如外卖系统,订单系统,库存系统,优先级较高 发红包,发邮件,发短信,app消息推送等任务优先级很低,很适合交给消息队列去处理,以便于程序系统更快的处理其他请求 ...
- rabbitmq五种消息模型整理
目录 0. 配置项目 1. 基本消息模型 1.1 生产者发送消息 1.2 消费者获取消息(自动ACK) 1.3 消息确认机制(ACK) 1.4 消费者获取消息(手动ACK) 1.5 自动ACK存在的问 ...
- RabbitMQ 五种工作模式
官网介绍:https://www.rabbitmq.com/getstarted.html 五种工作模式的主要特点 简单模式:一个生产者,一个消费者 work模式:一个生产者,多个消费者,每个消费者获 ...
随机推荐
- 【linux基础】ubuntu系统NVIDIA驱动安装
在安装GPU环境下的软件工具,特别是CUDA/CUDNN等,一定要先把GPU环境搭建好. NVIDIA驱动安装会遇到各种问题,真希望黄教主可以将各个工具如何安装使用讲解的更加细致.清楚一些,有时候按照 ...
- Linux查询日志内容
1.查询日志中含有某个关键字的信息 cat app.log |grep 'error' 2.查询日志尾部最后10行的日志 tail -n 10 app.log 3.查询10行之后的所有日志 tail ...
- JSF生命周期&Facelets的生命周期
1.JSF生命周期 1)恢复视图(Restore View) 视图表示组成特定页面的所有组件.它被保存在 客户端(通常存储在隐藏字段中)或服务器中(通常在会话中).根据请求访问的视图ID(页面地址), ...
- Java中如何拆分字符串为字符数组
题目:输入一串字符,由(){}[]组成,判断是否所有的括号都是闭括号,是的返回TRUE,不是返回FALSE. /*输入字符串,拆解为字符数组 * 用函数s.charAt(i)来完成 * * */imp ...
- ODS ,EDW,DM
ODS: 操作数据存储ODS(Operational Data Store),操作型数据仓库,最早的数据仓库模型,是数据仓库体系结构中的一个可选部分,ODS具备数据仓库的部分特征和OLTP系统的部分特 ...
- Javascript 3.3 编写DOM脚本的四个基本方法
id属性的用途是给某个元素加上独一无二的标识符,搭配"#"使用 class搭配"."使用 getElementById()方法:方法名称的大小写不能写错,方法将 ...
- 自己用的Xshell配色方案
[comfort]text=dce2e2cyan(bold)=2ad1b8text(bold)=dce2e2magenta=dd3682green=55bb55green(bold)=55bb55ba ...
- python中自定义的栈
# 栈 先进后出 例如蒸笼,弹夹,饭菜等 class StackFullException(Exception): """自定义一个栈溢出异常""&q ...
- mysql的基础用法,水一下
#和上一篇是一起的,上一篇就是为这个做insert <blockquote>/*思考题*/ create database spj; use spj;create table s( sno ...
- vue添加class类名
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...