Spring集成消息队列RabbitMQ
来源:互联网 发布:怎么申请农村淘宝 编辑:程序博客网 时间:2024/05/21 14:55
1. RabbitMQ简介
1.1. RabbitMQ
RabbitMQ是由Erlang(爱立信公司)语言开发,实现Advanced Message Queuing Protocol (AMQP高级消息队列协议)的消息中间件。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
1.2. 结构图
• Broker:消息队列服务器实体,例如RabbitMQ服务
• Vhost:虚拟主机,默认为“/”,一个broker里可以有多个vhost,区分不同用户权限,类似java的命令空间
• Connection:应用程序与broker连接,可有多个连接
• Channel:消息通道,connection中可建立多个channel,每个channel代表一个会话任务,所有操作都在channel中进行。
• Exchange:消息交换机,channel中可有多个,用于投递消息。应用程序发送消息时先把消息给交换机,由交换机投递给队列,不是直接给队列。
类型有三种:fanout(广播)、Direct(处理路由键,轮播实现)、Topic(支持消息模糊匹配)
• Queue:队列,用于存放消息
• Message:消息,应用程序需要发送的数据
• Bind:根据routingKey绑定exchange与queue规则,决定消息发送的方向
1.3. 对象间关系
2. rabbitMQ与spring集成
使用spring封装的rabbitmq的 https://github.com/spring-projects/spring-amqp 做集成。
2.1. 发送消息Producer
发送接口
public interface SimpleMQProducer { /** * 发送消息至MQ */ public void sendDataToMQ(Object message); /** * 发送消息至MQ */ public void sendDataToMQ(Object message, String msgid); }
发送接口实现
public class SmartMQProducer implements InitializingBean,SimpleMQProducer{ protected final Loggerx logger = Loggerx.getLogger("dao"); protected RabbitTemplate rabbitTemplate = new RabbitTemplate(); protected String queue; protected String exchange; protected String routingKey; protected ConnectionFactory connectionFactory; protected MessageConverter messageConverter; protected RetryTemplate retryTemplate; protected ConfirmCallback confirmCallback; protected ReturnCallback failedCallback; public RabbitTemplate getRabbitTemplate() { return rabbitTemplate; } public void setRabbitTemplate(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } public void setQueue(String queue) { this.queue = queue; } public void setExchange(String exchange) { this.exchange = exchange; } public void setRoutingKey(String routingKey) { this.routingKey = routingKey; } public void setConnectionFactory(ConnectionFactory connectionFactory) { this.connectionFactory = connectionFactory; } public void setMessageConverter(MessageConverter messageConverter) { this.messageConverter = messageConverter; } public void setRetryTemplate(RetryTemplate retryTemplate) { this.retryTemplate = retryTemplate; } public void setConfirmCallback(ConfirmCallback confirmCallback) { this.confirmCallback = confirmCallback; } public void setFailedCallback(ReturnCallback failedCallback) { this.failedCallback = failedCallback; } @Override public void sendDataToMQ(Object message) { CorrelationData correlationId = null; try { correlationId = new CorrelationData(GUID.genTxNo(25)); } catch (Exception e) { logger.error(LogType.EX, "产生消息id失败",e); correlationId = new CorrelationData(UUID.randomUUID().toString()); } this.rabbitTemplate.convertAndSend(this.routingKey, message, correlationId); logger.info(LogType.EX, "发送到MQ的消息内容["+JsonUtil.toJSONString(message)+"],消息ID["+correlationId.getId()+"]"); } @Override public void sendDataToMQ(Object message, String msgid) { CorrelationData correlationId = new CorrelationData(msgid); this.rabbitTemplate.convertAndSend(this.routingKey, message, correlationId); logger.info(LogType.EX, "发送到MQ的消息内容["+JsonUtil.toJSONString(message)+"],消息ID["+correlationId.getId()+"]"); } @Override public void afterPropertiesSet() throws Exception { this.rabbitTemplate.setQueue(this.queue); this.rabbitTemplate.setExchange(this.exchange); this.rabbitTemplate.setRoutingKey(this.routingKey); this.rabbitTemplate.setConnectionFactory(this.connectionFactory); this.rabbitTemplate.setMessageConverter(this.messageConverter); this.rabbitTemplate.setMandatory(true); if (null == this.failedCallback) { // 确认消息是否到达broker服务器,也就是只确认是否正确到达exchange中即可,只要正确的到达exchange中,broker即可确认该消息返回给客户端ack。 this.rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() { @Override public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) { //记录本地日志 Object object = StringUtil.ByteToObject(message.getBody()); logger.error(LogType.EX, "消息发送到MQ失败,内容["+object+"]"); } }); }else { this.rabbitTemplate.setReturnCallback(this.failedCallback); } //设置回调 this.rabbitTemplate.setConfirmCallback(this.confirmCallback); }}
发送到MQ失败回调处理
public abstract class SmartMQFailedCallBack implements ReturnCallback { protected final Loggerx logger = Loggerx.getLogger("bo"); /** * 确认消息是否到达broker服务器,也就是只确认是否正确到达queue中即可,只要正确的到达queue中,broker即可确认该消息返回给客户端ack。 */ public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) { if (null != message) { Object object = StringUtil.ByteToObject(message.getBody()); logger.error(LogType.EX, "消息发送到MQ失败,内容["+object+"]"); executeFailedMessage(object); }else { logger.error(LogType.EX, "消息发送到MQ失败,消息内容为null"); } } public abstract void executeFailedMessage(Object message);}
发送到MQ后回调处理(不分成功或失败)
public abstract class SmartMQConfirmCallBack implements ConfirmCallback{ protected final Logger logger = Logger.getLogger("bo"); /** * 确认消息是否到达broker服务器,也就是只确认是否正确到达exchange中即可,只要正确的到达exchange中,broker即可确认该消息返回给客户端ack。 * */ public void confirm(CorrelationData correlationData, boolean ack) { if (ack) { logger.info(LogType.INFO, "消息成功消费,消息ID["+correlationData.getId()+"]"); } else { logger.error(LogType.EX, "消息失败消费,消息ID["+correlationData.getId()+"]"); } executeCallBack(correlationData.getId(),ack); } public abstract void executeCallBack(String msgID,boolean ack);}
发送端spring
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd"> <!-- 连接服务配置 --> <bean id="mqConnectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory"> <constructor-arg value="xxx.xxx.xx.xx"/> <property name="username" value="guest"/> <property name="password" value="guest"/> <property name="virtualHost" value="/"/> <property name="channelCacheSize" value="50"/> <property name="publisherConfirms" value="true"/> <property name="publisherReturns" value="true"/> </bean> <rabbit:admin connection-factory="mqConnectionFactory" /> <!-- 声明消息转换器为SimpleMessageConverter --> <bean id="msgConverter" class="org.springframework.amqp.support.converter.SimpleMessageConverter" /> <!-- 消息发送重试 ,可选项--> <bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate"> <property name="backOffPolicy"> <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy"> <property name="initialInterval" value="500" /> <property name="multiplier" value="10.0" /> <property name="maxInterval" value="10000" /> </bean> </property> </bean> <!-- queue 队列声明 --> <!-- durable=true,交换机持久化,rabbitmq服务重启交换机依然存在,保证不丢失; durable=false,相反 --> <!-- auto-delete=true:无消费者时,队列自动删除; auto-delete=false:无消费者时,队列不会自动删除 --> <!-- 排他性,exclusive=true:首次申明的connection连接下可见; exclusive=false:所有connection连接下都可见--> <rabbit:queue id="test" durable="true" auto-delete="false" exclusive="false" name="test" /> <!-- exchange queue binging key 绑定 --> <!-- durable=true,交换机持久化,rabbitmq服务重启交换机依然存在,保证不丢失; durable=false,相反 --> <!-- auto-delete=true:无消费者时,队列自动删除; auto-delete=false:无消费者时,队列不会自动删除 --> <rabbit:direct-exchange name="test" durable="true" auto-delete="false" id="test"> <rabbit:bindings> <rabbit:binding queue="test" key="test_key" /> </rabbit:bindings> </rabbit:direct-exchange> <!-- 消息发送到mq回调处理,需要处理错误消息,可选项 --> <bean id="testfailedCallback" class="xxx.TestMsgFailedCallBack"></bean> <!-- 消息发送到mq回调处理,接着业务处理 ,可选项--> <bean id="testconfirmCallback" class="xxx.TestconfirmCallback"></bean> <bean id="testProducer" class="XXXX.SmartMQProducer"> <property name="connectionFactory" ref="mqConnectionFactory" /> <property name="messageConverter" ref="msgConverter" /> <property name="retryTemplate" ref="retryTemplate" /> <property name="confirmCallback" ref="testconfirmCallback" /> <property name="failedCallback" ref="testfailedCallback" /> <property name="exchange" value="test" /> <property name="queue" value="test" /> <property name="routingKey" value="test" /> </bean> </beans>
2.2. 消费端Consumer
接收端spring配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <!-- 连接服务配置 --> <bean id="mqConnectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory"> <constructor-arg value="xxx.xxx.xxx.xxx" /> <property name="username" value="guest" /> <property name="password" value="guest" /> <property name="virtualHost" value="/" /> <property name="channelCacheSize" value="50" /> </bean> <!-- 创建rabbitAdmin 代理类 --> <rabbit:admin connection-factory="mqConnectionFactory" /> <!-- 声明消息转换器为SimpleMessageConverter --> <bean id="msgConverter" class="org.springframework.amqp.support.converter.SimpleMessageConverter" /> <!-- queue 队列声明 --> <rabbit:queue id="test" name="test" durable="true" auto-delete="false" exclusive="false" /> <!-- exchange queue binging key 绑定 --> <!-- durable=true,交换机持久化,rabbitmq服务重启交换机依然存在,保证不丢失; durable=false,相反 --> <!-- auto-delete=true:无消费者时,队列自动删除; auto-delete=false:无消费者时,队列不会自动删除 --> <!-- 通过Binding来判定Queue、Exchange、routingKey --> <rabbit:direct-exchange id="test" name="test" durable="true" auto-delete="false"> <rabbit:bindings> <rabbit:binding queue="test" key="test_key" /> </rabbit:bindings> </rabbit:direct-exchange> <bean id="testMsgHandler" class="xxxx.testMsgHandler" /> <bean id="testMsgAdapter" class="org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter"> <constructor-arg ref="testHandler" /> <property name="defaultListenerMethod" value="handleTxMsg"></property> <property name="messageConverter" ref="msgConverter"></property> </bean> <bean id="testlistenerContainer" class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer"> <property name="queueNames" value="test"></property> <property name="connectionFactory" ref="mqConnectionFactory"></property> <property name="messageListener" ref="testAdapter"></property> <property name="maxConcurrentConsumers" value="100" /> <property name="concurrentConsumers" value="20" / </bean></beans>
接收端封装
public abstract class ConsumerHandler{ protected static Logger logger = Logger.getLogger("bo"); public void handleTxMsg(Object message) { try { //基类的业务处理 } logger.info(LogType.MQ, "消息内容["+JsonUtil.toJSONString(message)+"]"); handler(message); } catch (Exception e) { logger.error(LogType.EX, e, e); } finally { LogContextHolder.getInstance().removeLogContext(); } } //实际的业务处理 public abstract void handler(Object message);}
3. 效果
- Spring集成消息队列RabbitMQ
- Spring集成消息队列RabbitMQ
- 消息队列RabbitMQ与Spring集成
- 消息队列RabbitMQ与Spring集成
- 消息队列RabbitMQ与Spring集成
- 消息队列RabbitMQ与Spring集成
- Spring集成rabbitMQ监听消费队列消息
- 消息队列RabbitMQ与Spring集成
- Spring集成消息队列RabbitMQ(消息失败处理)
- spring boot Rabbitmq集成,延时消息队列实现
- spring整合消息队列rabbitmq
- spring整合消息队列rabbitmq
- spring整合消息队列rabbitmq
- spring整合消息队列rabbitmq
- spring整合消息队列rabbitmq
- spring整合消息队列rabbitmq
- spring整合消息队列rabbitmq
- 消息队列RabbitMQ与Spring
- android 优雅的判断程序是否在后台运行
- Using the Chrome Debugger Tools, part 3: The Sources Tab
- 互斥锁和内存可见性
- Sublime Text3配置lua环境
- 面向对象知识点归纳
- Spring集成消息队列RabbitMQ
- Java之美[从菜鸟到高手演变]系列之博文阅读导航
- 已知某年某月某日计算这是这一年的哪一天
- 如何安全退出已调用多个Activity的Application?
- jdbc批处理+事务处理 十万级数据导入
- Swift 单例
- Android开发 这19个开发工具
- HOWTO: Enumerate handles
- FreeCMS视频教程 单位管理