RabbitMQ RPC

服务间,系统间信息交互,简单的方式可以是http,但比http更为高效的是RPC,gRPC是比较流行的RPC工具了,使用上也比较简单。那么,我们不妨也了解一下RabbitMQ实现RPC又是怎样一番风味。

RabbitMQ是单向的消息传递,生产者将消息发送给消费者之后就不再管后续的业务处理了。实际业务中,有的时候我们还需要等待消费者返回结果给我们,或者是说我们需要消费者上的一个功能、一个方法或是一个接口返回给我们相应的值,而往往大型的系统软件,生产者跟消费者之间都是相互独立的两个系统,部署在两个不同的电脑上,不能通过直接对象.方法的形式获取想要的结果,这时候我们就需要用到RPC(Remote Procedure Call)远程过程调用方式。

RabbitMQ实现RPC的方式很简单,生产者发送一条带有标签(消息ID(correlation_id)+回调队列名称)的消息到发送队列,消费者(也称RPC服务端)从发送队列获取消息并处理业务,解析标签的信息将业务结果发送到指定的回调队列,生产者从回调队列中根据标签的信息获取发送消息的返回结果。
    


    如图,客户端C发送消息,指定消息的ID=rpc_id,回调响应的队列名称为rpc_resp,消息从C发送到rpc_request队列,服务端S获取消息业务处理之后,将correlation_id附加到响应的结果发送到指定的回调队列rpc_resp中,客户端从回调队列获取消息,匹配与发送消息的correlation_id相同的值为消息应答结果。

事件总线模式下RabbitMQ,客户端发送消息,并等待返回值:

 var command = new GetAllPackageCommand();

            var res = BusFactory.DefaultBus.SendCommand<GetAllPackageCommand, List<PackageContract>>(command);

            var packages = res.GetResult();

当客户端发起消息的时候,程序对DefaultBus作了初始化,其主要代码是初始化客户端 生产者和消费者 身份:

 

 1     publishConnection = RabbitConnectionManager.Allocate(this.busUri, true);  //客户端作为生产者 连接MQ
 2     publishChannel = publishConnection.CreateModel();//客户端作为生产者 创建信道
 3     publishConfirmChannelPool = new ComfireSelectChannelPool(publishConnection);//客户端作为生产者 信道设置 confirm select模式,以确保能发消息到队列
 4     consumeConnection = RabbitConnectionManager.Allocate(this.busUri); //客户端作为 消息者 连接MQ
 5     consumeChannel = consumeConnection.CreateModel(); 客户端作为消费者 创建信道
 6 
 7     var args = new Dictionary<string, object>();
 8     args.Add("x-expires", this.responseQueueExpireTime);
 9 
//接收模型consumeChannel,绑定队列 MyQueueingBasicConsumer。MyQueueingBasicConsumer 监听 this.responseQuque,当消息到来时,存入自身的Queue队列中。
10     consumeChannel.QueueDeclare(this.responseQuque, true, false, false, args);  
12     consumer = new MyQueueingBasicConsumer(consumeChannel);
13     consumeChannel.BasicConsume(this.responseQuque, true, consumer);
14 
15     consumerCancellation = new CancellationTokenSource();
16     
// 启动了 consumerTask, 内部一直在轮询 MyQueueingBasicConsumer.Queue队列。发现消息后,根据消息的关系id,获取发送的 BusResponse 对象,并赋值。 17 consumerTask = new Task(() => ProcessResponse(this.consumerCancellation.Token), TaskCreationOptions.LongRunning); 18 consumerTask.Start();

 

当客户端发起请求,它作为生产者的同时,也成为了一个等待结果的消费者,这个消费者一直在监听着 响应队列(response) 里面的消息。

 

转载于:https://www.cnblogs.com/wikiz/p/11363839.html

在C#中,RabbitMQ通常用于消息队列通信,而不是RPC(Remote Procedure Call,远程过程调用)。然而,如果你想在RabbitMQ中实现类似RPC的功能,一种方法是结合AMQP协议和序列化库(如MessagePack或Json.NET)来封装请求-响应模型。 以下是一个简单的示例,展示了如何使用RabbitMQ和NServiceBus(一个基于RabbitMQ的消息传递框架)来实现实现RPC: ```csharp using NServiceBus; using Newtonsoft.Json; // 定义一个接口作为服务 public interface IRpcService { string Add(int a, int b); } // 实现接口 [EndpointName("RpcService")] public class RpcServiceImpl : IRpcService { public string Add(int a, int b) { return $"The sum is {a + b}"; } } // 在发送端(客户端) class Client { private IBus bus; public Client() { bus = Bus.Create(); } public async Task<string> CallAddAsync(int a, int b) { var request = new { Method = "Add", Args = new[] { a, b } }; // 序列化成JSON var jsonRequest = JsonConvert.SerializeObject(request); await bus.SendLocal(new RpcRequest { Destination = "RpcService", // 服务器端接口名称 Body = jsonRequest }); // 接收并反序列化响应 var response = await bus.Receive<RpcResponse>(); return JsonConvert.DeserializeObject<RpcResponse>(response.Body).Result; } } // 定义一个接收消息并处理的类(服务器端) public class RpcRequestHandler : IHandleMessages<RpcRequest> { public void Handle(RpcRequest message) { // 反序列化请求 var request = JsonConvert.DeserializeObject<Dictionary<string, object>>(message.Body); // 获取服务对象并执行方法 var service = container.Resolve<IRpcService>(); var result = service.Add((int)request["Args"], (int)request["Args"]); // 序列化结果为响应 var response = new RpcResponse { Result = result }; // 发送响应回客户端 bus.SendLocally(response); } } // 配置NServiceBus public class EndpointConfig : IConfigureThisEndpoint, AsA_Server { public void Customize(BusConfiguration configuration) { configuration.UseJsonSerializer(); configuration.UseTransport<RabbitMQTransport>() .ConnectionString(() => Configuration.Settings.RabbitMQ.ConnectionString); } } ``` 在这个例子中,`Client`通过序列化的JSON向`RpcService`发送请求,`RpcRequestHandler`负责接收到请求后调用相应的方法并返回结果。这个架构并非真正的RPC,因为消息在发送者和接受者之间是异步的,并不是直接从一个进程到另一个进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值