消息请求应答与RPC
来源:互联网 发布:毒丸计划 白衣骑士知乎 编辑:程序博客网 时间:2024/05/18 21:51
消息请求应答与RPC
AmqpTemplate同样提供了大量的sendAndReceive方法,这些方法和上面讲到的方法接收到同样的参数来完成一次性的发送工作。这些方法在请求应答场景中很有用,因为它们在发送之前配置了reply-to属性,因此它可以监听响应消息(内部穿件了一个专属队列来完成)。
类似,同样存在这convertSendAndReceive方法,在请求和响应的时候使用了MessageConverter。
默认的情况下,每个应答都使用一个新的临时的队列。然而,可以在模板上配置应答队列,这样更高效,同时你还可以为这个队列设置参数,在这种情况下,你必须提供<reply-listener/>子元素。这个子元素提供了应答队列的监听容器,template是监听者。在消息监听容器配置中配置的东西都可以在这里配置,除了connection-factory,message-converter,这些东西将继承template的配置。
<rabbit:template id="amqpTemplate"
connection-factory="connectionFactory" reply-queue="replies">
<rabbit:reply-listener/>
</rabbit:template>
因为容器和模板共享一个连接,但是它们不共享同一个channel,因此请求和应答不在一个事物中。
应答队列中的消息关联
当你使用固定的应答队列,提供关联数据很有必要,这样请求和响应才能关联上。在默认的情况下,标准的correlationId属性会被用来持有关联数据。然而,如果你想使用定制的属性来持有关联数据,你可以设置<rabbit-template/>的correlation-key属性。这种情况下,设置correlationId和忽略这个属性一样。当然,客户端和服务器端必须使用同样的头来关联数据。
应答监听容器
当你使用固定的应答队列时,使用SimpleListnerContainer来接收应答,使用RabbitTemplate来进行消息监听。当使用<rabbit:template/>时,像上面那样,解析器会定义容器,并且将模板定义为监听器。
注意:
当你不使用固定的replyQueue时,监听容器没有必要。
如果你通过<bean/>或者使用@Configuration来定义RabbitTemplate,你需要自己定义监听容器。如果你不这样做,你将永远都接收不到应答,最终导致超时,返回空给sendAndReceive方法。
注意:
当你自己装配应答监听和模板的时候,确保模板的replyQueue和容器的queues属性参照同一个队列很重要。模板将响应队列插入到发送消息的replyTo属性中。
下面是手动专配这些beans:
<bean id="amqpTemplate" class="org.springframework.amqp.rabbit.core.RabbitTemplate">
<constructor-arg ref="connectionFactory"/>
<property name="exchange" value="foo.exchange"/>
<property name="routingKey" value="foo"/>
<property name="replyQueue" ref="replyQ"/>
<property name="replyTimeout" value="600000"/>
</bean>
<bean class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<constructor-arg ref="connectionFactory"/>
<property name="queues" ref="replyQ"/>
<property name="messageListener" ref="amqpTemplate"/>
</bean>
<rabbit:queue id="replyQ" name="my.reply.queue"/>
@Bean
publicRabbitTemplate amqpTemplate() {
RabbitTemplate rabbitTemplate = newRabbitTemplate(connectionFactory());
rabbitTemplate.setMessageConverter(msgConv());
rabbitTemplate.setReplyQueue(replyQueue());
rabbitTemplate.setReplyTimeout(60000);
returnrabbitTemplate;
}
@Bean
publicSimpleMessageListenerContainer replyListenerContainer() {
SimpleMessageListenerContainer container = newSimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.setQueues(replyQueue());
container.setMessageListener(amqpTemplate());
returncontainer;
}
@Bean
publicQueue replyQueue() {
return newQueue("my.reply.queue");
}
使用AMQP进行Spring Remoting
Spring Framework具有通用的远程调用的能力,使用不同的传输协议。Spring-AMQP支持类似机制,在客户端使用AmqpProxyFactoryBean,在服务器端使用AmqpInvokerServiceExporter。这里通过AMQP提供RPC。在客户端RabbitTemplate像上面描述的那样使用。在服务器端,调用者接收消息,调用配置服务,使用接收到的replyTo信息返回应答。
客户端工厂可以注入到任何一个bean;这样客户端可以通过代理触发方法,最终通过AMQP获得远程调用的结果。
注意:
使用默认转换器MessageConverter,方法参数和返回结果必须是Serializable的实例。
在服务器端,AmqpInvokerServiceExporter拥有AmqpTemplate和MessageConverter属性。目前,模板的MessageConverter不会使用。如果你想使用定制的消息转换器,你必须使用messgeConverter属性进行设置。在客户端,定制的转换器可以通过AmqpTemplate的进行添加,AmqpTemplate通过AmqpProxyFactoryBean的amqpTemplate属性进行设置。
客户端与服务器端的最简配置如下:
<bean id="client"
class="org.springframework.amqp.remoting.client.AmqpProxyFactoryBean">
<property name="amqpTemplate" ref="template"/>
<property name="serviceInterface" value="foo.ServiceInterface"/>
</bean>
<rabbit:connection-factory id="connectionFactory"/>
<rabbit:template id="template" connection-factory="connectionFactory" reply-timeout="2000"
routing-key="remoting.binding" exchange="remoting.exchange"/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:queue name="remoting.queue"/>
<rabbit:direct-exchange name="remoting.exchange">
<rabbit:bindings>
<rabbit:binding queue="remoting.queue" key="remoting.binding"/>
</rabbit:bindings>
</rabbit:direct-exchange>
<bean id="listener"
class="org.springframework.amqp.remoting.service.AmqpInvokerServiceExporter">
<property name="serviceInterface" value="foo.ServiceInterface"/>
<property name="service" ref="service"/>
<property name="amqpTemplate" ref="template"/>
</bean>
<bean id="service" class="foo.ServiceImpl"/>
<rabbit:connection-factory id="connectionFactory"/>
<rabbit:template id="template" connection-factory="connectionFactory"/>
<rabbit:queue name="remoting.queue"/>
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="listener" queue-names="remoting.queue"/>
</rabbit:listener-container>
注意:
AmqpInvokerServiceExporter只能处理一定格式的消息,例如AmqpProxyFactoryBean发来的消息。如果它发来的消息没有办法解析,一个RuntimeException将会被抛出。如果这个消息没有replyToAddress这个属性,这个消息将被拒绝,如果没有配置Dead Letter Exchange它将丢失。
0 0
- 消息请求应答与RPC
- SIP请求消息类型与应答码
- 回显请求与应答
- [老老实实学WCF] 第九篇 消息通信模式(上) 请求应答与单向
- 老老实实学WCF 第九篇 消息通信模式(上) 请求应答与单向
- SIP应答消息状态码与功能
- SIP应答消息状态码与功能
- SIP应答消息状态码与功能
- SIP应答消息状态码与功能
- ICMP时间戳请求与应答
- Java 浏览器请求与web服务器应答
- 一个请求返回多个应答消息的支持
- RabbitMQ(三)—消息应答与消息持久化
- 2. [netty-RPC]--消息的请求、响应与接口和实现的映射容器
- 005 ZeroMQ REQ-<ROUTER-Dealer>-REP代理应答与请求
- 94-ICMP 协议(回显请求与应答)
- 96-ICMP 协议(时间戳请求与应答)
- 一个简单的HTTP请求与应答基于socket
- JAVA String.format 方法使用介绍
- cocos2d-js学习笔记<二> 创建工程
- CentOS 6.4上安装 oracle 11g R2图文安装教程
- yuicompressor 与 maven结合,打包,压缩js,css
- selenium的中文文字类型转换错误
- 消息请求应答与RPC
- Git分支管理策略
- cocos2dx 常见的49中动作详解
- 怎样进入国外的游戏行业工作?
- Git的深入理解与GitHub托管服务的使用
- [LeetCode]94.Binary Tree Inorder Traversal
- 磁条卡磁道数据格式检测指南
- ADDRESPONSE - ADDING TO MEMORY ONLY: http://XXXXXXXX的解决方法
- ORACLE数据库存储结构简介(转)