说到RPC(RemoteProcedureCallProtocol远程过程调用协议),小伙伴们脑海中浮现的大概就是RESTfulAPI、Dubbo、WebService、JavaRMI、CORBA等。其实RabbitMQ也为我们提供了RPC功能,使用起来也非常简单。今天宋哥就通过一个简单的案例和大家分享一下SpringBoot+RabbitMQ是如何实现一个简单的RPC调用的。注意,有些朋友可能对RabbitMQ实现RPC调用有一些误解,认为这不简单?创建两个消息队列,queue_1和queue_2。首先,客户端向queue_1发送消息,服务端监听queue_1上的消息,收到后进行处理;处理完成后,服务端将消息发送给queue_2,然后客户端监听queue_2队列上的消息,这样就知道服务端的处理结果了。这个方法也不是不行,就是有点麻烦!RabbitMQ提供了现成的解决方案,可以直接使用,非常方便。接下来我们一起学习吧。1.架构首先我们来看一个简单的架构图:这个图把问题说的很清楚了:首先,Client发送消息。与普通消息相比,这条消息多了两个关键内容:一是correlation_id,表示这条消息的唯一id,内容是reply_to,表示消息回复队列的名称。服务器从消息发送队列中获取消息,并处理相应的业务逻辑。处理完成后,将处理结果发送到reply_to指定的回调队列。客户端从回调队列中读取消息以了解消息的执行情况。这种情况其实很适合处理异步调用。2.实践接下来我们通过一个具体的例子来看看这是如何实现的。2.1客户端开发首先,我们创建一个名为producer的SpringBoot项目。作为消息生产者,在创建时添加web和rabbitmq依赖,如下图:项目创建成功后,首先在application.properties中配置RabbitMQ的基本信息,如下:spring.rabbitmq.host=localhostspring.rabbitmq.port=5672spring.rabbitmq.username=guestspring.rabbitmq.password=guestspring.rabbitmq.publisher-confirm-type=correlatedspring.rabbitmq.publisher-returns=true这个配置的前四行很容易理解,所以我不会详细介绍。接下来两行:首先,配置消息确认方式。我们通过相关确认。只有启用此配置后,correlation_id才会包含在以后的消息中。只有通过correlation_id才能发送消息和链接返回值。最后一行配置是开启发送失败返回。接下来我们提供一个配置类,如下:/***@author江南一场小雨*@微信公众号江南一场小雨*@网站http://www.itboyhub.com*@国际站http://www.javaboy.org*@微信a_java_boy*@GitHubhttps://github.com/lenve*@Giteehttps://gitee.com/lenve*/@ConfigurationpublicclassRabbitConfig{publicstaticfinalStringRPC_QUEUE1="queue_1";publicstaticfinalStringRPC_QUEUE2="queue_2";publicstaticfinalStringRPC_EXCHANGE="rpc_exchange";/***设置消息发送RPC队列*/@BeanQueuemsgQueue(){returnnewQueue(RPC_QUEUE1);}/***设置返回队列*/@BeanQueuereplyQueue(){returnnewQueue(RPC_QUEUE2);}/***设置交换*/@BeanTopicExchangeexchange(){returnnewTopicExchange(RPC_EXCHANGE);}/***请求队列和exchangeBuilder绑定*/@BeanBindingmsgBinding(){returnBindingBuilder.bind(msgQueue()).to(exchange()).with(RPC_QUEUE1);}/***返回队列和交换绑定*/@BeanBindingreplyBinding(){r返回BindingBuilder.bind(replyQueue()).to(exchange()).with(RPC_QUEUE2);}/***使用RabbitTemplate收发消息*并设置回调队列地址*/@BeanRabbitTemplaterabbitTemplate(ConnectionFactoryconnectionFactory){RabbitTemplatetemplate=newRabbitTemplate(connectionFactory);template.setReplyAddress(RPC_QUEUE2);template.setReplyTimeout(6000);返回模板;}/***为返回队列设置监听器*/@BeanSimpleMessageListenerContainerreplyContainer(ConnectionFactoryListenerconnectionMtainerage){=newSimpleMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.setQueueNames(RPC_QUEUE2);container.setMessageListener(rabbitTemplate(connectionFactory));返回容器;}}在这个配置类中,我们分别配置消息发送队列msgQueue和消息返回队列replyQueue,然后将这两个队列绑定到消息交换机上。这是RabbitMQ的正常运行,没什么好说的。在SpringBoot中,我们负责发送消息的工具是RabbitTemplate。默认情况下,系统会自动提供这个工具,但是这里我们需要重新自定义这个工具,主要是添加消息发送的返回队列,最后我们需要给返回队列设置一个监听器。好了,那我们就可以开始发送具体消息了:/***@author江南小雨*@微信公众号江南小雨*@Websitehttp://www.itboyhub.com*@国际站http://www.javaboy.org*@微信a_java_boy*@GitHubhttps://github.com/lenve*@Giteehttps://gitee.com/lenve*/@RestControllerpublicclassRpcClientController{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(RpcClientController.class);@AutowiredprivateRabbitTemplaterabbitTemplate;@GetMapping("/send")publicStringsend(Stringmessage){//创建消息对象MessagenewMessage=MessageBuilder.withBody(message.getBytes()).build();logger.info("客户端发送:{}",newMessage);//客户端发送消息Messageresult=rabbitTemplate.sendAndReceive(RabbitConfig.RPC_EXCHANGE,RabbitConfig.RPC_QUEUE1,newMessage);字符串响应="";if(result!=null){//获取发送消息的correlationIdStringcorrelationId=newMessage.getMessageProperties().getCorrelationId();logger.info("合作relationId:{}",correlationId);//获取响应头信息HashMap
