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的更多相关文章

  1. RabbitMQ(四):RPC的实现

    原文:RabbitMQ(四):RPC的实现 一.RPC RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. ...

  2. RabbitMQ 实现RPC

    实现RPC 首先要弄明白,RPC是个什么东西. (RPC) Remote Procedure Call Protocol 远程过程调用协议 在一个大型的公司,系统由大大小小的服务构成,不同的团队维护不 ...

  3. RabbitMQ中RPC的实现及其通信机制

    RabbitMQ中RPC的实现:客户端发送请求消息,服务端回复响应消息,为了接受响应response,客户端需要发送一个回调队列的地址来接受响应,每条消息在发送的时候会带上一个唯一的correlati ...

  4. 基于RabbitMQ的Rpc框架

    参考文档:https://www.cnblogs.com/ericli-ericli/p/5917018.html 参考文档:RabbitMQ 实现RPC MQ的使用场景大概包括解耦,提高峰值处理能力 ...

  5. RabbitMQ除开RPC的五种消模型----原生API

    2.五种消息模型 RabbitMQ提供了6种消息模型,但是第6种其实是RPC,并不是MQ,因此不予学习.那么也就剩下5种. 但是其实3.4.5这三种都属于订阅模型,只不过进行路由的方式不同. 通过一个 ...

  6. RabbitMQ 笔记-RPC

    RabbitMQ中实现RPC的机制是: 客户端发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14中properties,这些属性会随着消息一起发送)中设置 ...

  7. RabbitMQ、RPC、SaltStack "贡"具的使用

    消息队列 使用队列的场景 在程序系统中,例如外卖系统,订单系统,库存系统,优先级较高 发红包,发邮件,发短信,app消息推送等任务优先级很低,很适合交给消息队列去处理,以便于程序系统更快的处理其他请求 ...

  8. rabbitmq五种消息模型整理

    目录 0. 配置项目 1. 基本消息模型 1.1 生产者发送消息 1.2 消费者获取消息(自动ACK) 1.3 消息确认机制(ACK) 1.4 消费者获取消息(手动ACK) 1.5 自动ACK存在的问 ...

  9. RabbitMQ 五种工作模式

    官网介绍:https://www.rabbitmq.com/getstarted.html 五种工作模式的主要特点 简单模式:一个生产者,一个消费者 work模式:一个生产者,多个消费者,每个消费者获 ...

随机推荐

  1. 学习笔记 Optional

    今天学习到的一种新的防止空指针的方法下面是我自己写的一个例子:节省空间,bean的get set 省略... /** * 类目 * @author 唐 * @date 2018/5/6 17:45 * ...

  2. Fiddler实现手机抓包——小白入门

    方法1:https://www.cnblogs.com/hzg1981/p/5610530.html 方法2:转载自:http://blog.csdn.net/gld824125233/article ...

  3. 更改手机系统的User-Agent & okhttp

    okhttp 和 volley 1. 之前用的是volley,其中一部分功能,比如User-Agent,是系统去处理的,改成okhttp库后,这部分功能需要浏览器自己处理 2. 具体区别可以参考: h ...

  4. axios 重复点击利用CancelToken阻止请求多次发送

    import axios from 'axios'; axios.defaults.timeout = 5000; axios.defaults.baseURL =''; let pending = ...

  5. div 隐藏显示各种例子

    <html><head><title>jquery show()</title><script type="text/javascrip ...

  6. FixedUpdate()使用

    当MonoBehaviour启用时,其 FixedUpdate在每一帧被调用. 处理Rigidbody时,需要用FixedUpdate代替Update.例如:给刚体加一个作用力时,你必须应用作用力在F ...

  7. java标志性接口

    标识接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情.使用标记接口的唯一目的是使得可以用instanceof进行类型查询,例如:if(obj inst ...

  8. eclipse中的项目为什么无法添加到tomcat中?

    1.右键点击项目,选择properties 2.点击Project facets 3.在右侧的Runtimes中选中apache tomcat 4.勾选Dynamic Web Module 最终改为下 ...

  9. ODS ,EDW,DM

    ODS: 操作数据存储ODS(Operational Data Store),操作型数据仓库,最早的数据仓库模型,是数据仓库体系结构中的一个可选部分,ODS具备数据仓库的部分特征和OLTP系统的部分特 ...

  10. 移动端单位rem计算

    !(function(doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? ...