rabbitmq的延迟消息队列实现
第一部分:延迟消息的实现原理和知识点
使用RabbitMQ来实现延迟任务必须先了解RabbitMQ的两个概念:消息的TTL和死信Exchange,通过这两者的组合来实现上述需求。
消息的TTL(Time To Live)
消息的TTL就是消息的存活时间。RabbitMQ可以对队列和消息分别设置TTL。对队列设置就是队列没有消费者连着的保留时间,也可以对每一个单独的消息做单独的设置。超过了这个时间,我们认为这个消息就死了,称之为死信。如果队列设置了,消息也设置了,那么会取小的。所以一个消息如果被路由到不同的队列中,这个消息死亡的时间有可能不一样(不同的队列设置)。这里单讲单个消息的TTL,因为它才是实现延迟任务的关键。
可以通过设置消息的expiration字段或者x-message-ttl属性来设置时间,两者是一样的效果。只是expiration字段是字符串参数,所以要写个int类型的字符串:

当上面的消息扔到队列中后,过了3分钟,如果没有被消费,它就死了。不会被消费者消费到。这个消息后面的,没有“死掉”的消息对顶上来,被消费者消费。死信在队列中并不会被删除和释放,它会被统计到队列的消息数中去。单靠死信还不能实现延迟任务,还要靠Dead Letter Exchange。
Dead Letter Exchanges
Exchage的概念在这里就不在赘述。一个消息在满足如下条件下,会进死信路由,记住这里是路由而不是队列,一个路由可以对应很多队列。
1. 一个消息被Consumer拒收了,并且reject方法的参数里requeue是false。也就是说不会被再次放在队列里,被其他消费者使用。
2. 上面的消息的TTL到了,消息过期了。
3. 队列的长度限制满了。排在前面的消息会被丢弃或者扔到死信路由上。
Dead Letter Exchange其实就是一种普通的exchange,和创建其他exchange没有两样。只是在某一个设置Dead Letter Exchange的队列中有消息过期了,会自动触发消息的转发,发送到Dead Letter Exchange中去。
实现延迟队列
延迟任务通过消息的TTL和Dead Letter Exchange来实现。我们需要建立2个队列,一个用于发送消息,一个用于消息过期后的转发目标队列。

生产者输出消息到Queue1,并且这个消息是设置有有效时间的,比如3分钟。消息会在Queue1中等待3分钟,如果没有消费者收掉的话,它就是被转发到Queue2,Queue2有消费者,收到,处理延迟任务。
完成延迟任务的实现。
第二部分:具体实现例子
1、新建立消息队列配置文件rabbitmq.properties
#rabbitmq消息队列的属性配置文件properties
rabbitmq.study.host=192.168.56.101
rabbitmq.study.username=duanml
rabbitmq.study.password=1qaz@WSX
rabbitmq.study.port=5672
rabbitmq.study.vhost=studymq #Mail 消息队列的相关变量值
mail.exchange=mailExchange
mail.exchange.key=mail_queue_key #Phone 消息队列的相关变量值
phone.topic.key=phone.one
phone.topic.key.more=phone.one.more #delay 延迟消息队列的相关变量值
delay.directQueue.key=TradePayNotify_delay_2m
delay.directMessage.key=TradePayNotify_delay_3m
2、新建立配置文件,申明延迟队列相关的配置信息如:spring-rabbigmq-dlx.xml
<?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: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/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd"> <!--利用rabbitmq的TTL和延迟队列,实现延迟通知任务的例子
1、申明了一个订单通知服务的队列 queue_Notify
2、申明了一个延迟队列Notify_delay_15s,给整个队列设置消息过期时间 为15秒 ——————》 queue ttl 例子
3、申明了一个延迟队列Notify_delay_30s 给发送到这个队列的消息,消息本身设置过期时间 ————————》 message ttl 例子
4、当消息发送到2、3队列的时候,达到了过期时间,即转发到订单通知服务工作队列 1、
5、给队列1 配置消费者服务工作监听,即可完成延迟任务的结果。
--> <!-- ################ 订单通知服务消费者配置 ################ -->
<!--队列声明-->
<rabbit:queue id="queue_Notify" name="queue_Notify" durable="true" auto-delete="false" exclusive="false"/> <!-- 订单通知服务消费者 exchange -->
<rabbit:direct-exchange name="trade_direct" durable="true" auto-delete="false">
<rabbit:bindings>
<rabbit:binding queue="queue_Notify" key="TradePayNotify"/>
</rabbit:bindings>
</rabbit:direct-exchange> <!-- 订单通知监听处理器 -->
<bean id="notifyConsumerListener" class="org.seckill.rabbitmqListener.notify.NotifyConsumerListener"/>
<!--订单消息队列确认回调-->
<bean id="notifyConfirmCallBackListener" class="org.seckill.rabbitmqListener.notify.NotifyConfirmCallBackListener"></bean>
<!--订单消息队列消息发送失败回调-->
<bean id="notifyFailedCallBackListener" class="org.seckill.rabbitmqListener.notify.NotifyFailedCallBackListener"></bean> <!-- 监听器acknowledge=manual表示手工确认消息已处理(异常时可以不确认消息),auto表示自动确认(只要不抛出异常,消息就会被消费) -->
<rabbit:listener-container connection-factory="connectionFactory" acknowledge="manual">
<rabbit:listener queues="queue_Notify" ref="notifyConsumerListener"/>
</rabbit:listener-container> <!--*****************************************分割线*********************************************************--> <!-- ################ 延迟队列生产者配置 ################ -->
<rabbit:template id="rabbitTemplateDelay" mandatory="true" exchange="trade_direct_delay"
connection-factory="connectionFactory"
confirm-callback="notifyConfirmCallBackListener"
return-callback="notifyFailedCallBackListener"
message-converter="jsonMessageConverter"/> <!--配置生产消息的延迟队列操作主体类-->
<bean id="delayMQProducerImpl" class="org.seckill.utils.rabbitmq.Impl.MQProducerImpl">
<property name="rabbitTemplate" ref="rabbitTemplateDelay"></property>
</bean> <!--申明一个延迟队列,给整个队列的消息设置消息过期时间 x-message-ttl 2分钟
当消息达到过期时间的时候,rabbitmq将会把消息重新定位转发到其它的队列中去,本例子转发到
exchange:trade_direct
routing-key:TradePayNotify
满足如上两点的队列中去即为:queue_Notify
-->
<rabbit:queue id="Notify_delay_2m" name="Notify_delay_2m" durable="true" auto-delete="false"
exclusive="false">
<rabbit:queue-arguments>
<entry key="x-message-ttl" value="120000" value-type="java.lang.Long"/>
<entry key="x-dead-letter-exchange" value="trade_direct"/>
<entry key="x-dead-letter-routing-key" value="TradePayNotify"/>
</rabbit:queue-arguments>
</rabbit:queue> <!--申明一个延迟队列,在发送消息的时候给消息设置过期时间 3分钟
当消息达到过期时间的时候,rabbitmq将会把消息重新定位转发到其它的队列中去,本例子转发到
exchange:trade_direct
routing-key:TradePayNotify
满足如上两点的队列中去即为:queue_Notify
-->
<rabbit:queue id="Notify_delay_3m" name="Notify_delay_3m" durable="true" auto-delete="false"
exclusive="false">
<rabbit:queue-arguments>
<entry key="x-dead-letter-exchange" value="trade_direct"/>
<entry key="x-dead-letter-routing-key" value="TradePayNotify"/>
</rabbit:queue-arguments>
</rabbit:queue> <!-- 延迟队列工作的 exchange -->
<rabbit:direct-exchange name="trade_direct_delay" durable="true" auto-delete="false">
<rabbit:bindings>
<rabbit:binding queue="Notify_delay_2m" key="TradePayNotify_delay_2m"/>
<rabbit:binding queue="Notify_delay_3m" key="TradePayNotify_delay_3m"/>
</rabbit:bindings>
</rabbit:direct-exchange> </beans>
3、新建立延迟队列测试Controller
package org.seckill.web; import org.seckill.dto.SeckillResult;
import org.seckill.entity.Seckill;
import org.seckill.utils.rabbitmq.Impl.MQProducerImpl;
import org.seckill.utils.rabbitmq.MQProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import java.util.Date; /**
* <p>Title: org.seckill.web</p>
* <p>Company:东软集团(neusoft)</p>
* <p>Copyright:Copyright(c)2018</p>
* User: 段美林
* Date: 2018/5/30 17:33
* Description: 消息队列测试
*/
@Controller
@RequestMapping("/rabbitmq")
public class RabbitmqController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Value("${delay.directQueue.key}")
private String delay_directQueue_key; @Value("${delay.directMessage.key}")
private String delay_directMessage_key; @Autowired
private MQProducerImpl delayMQProducerImpl;
/**
* @Description: 消息队列
* @Author:
* @CreateTime:
*/
@ResponseBody
@RequestMapping("/sendDelayQueue")
public SeckillResult<Long> testDelayQueue() {
SeckillResult<Long> result = null;
Date now = new Date();
try {
Seckill seckill = new Seckill();
//第一种情况,给队列设置消息ttl,详情见配置文件
for (int i = 0; i < 2; i++) {
seckill.setSeckillId(1922339387 + i);
seckill.setName("delay_queue_ttl_" + i);
String msgId = delayMQProducerImpl.getMsgId();
Message message = delayMQProducerImpl.messageBuil(seckill,msgId);
delayMQProducerImpl.sendDataToRabbitMQ(delay_directQueue_key, message);
}
//第二种情况,给消息设置ttl
for (int i = 0; i < 2; i++) {
seckill.setSeckillId(1922339287 + i);
seckill.setName("delay_message_ttl_" + i);
String msgId = delayMQProducerImpl.getMsgId();
Message message = delayMQProducerImpl.messageBuil(seckill,msgId);
if (message != null) {
//给消息设置过期时间ttl,为3分钟
message.getMessageProperties().setExpiration("180000");
delayMQProducerImpl.sendDataToRabbitMQ(delay_directMessage_key, message);
}
}
result = new SeckillResult<Long>(true, now.getTime());
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return result;
} }
4、编写延迟消息确认类和监听类:
NotifyConfirmCallBackListener.java
package org.seckill.rabbitmqListener.notify; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.support.CorrelationData; /**
* <p>Title: org.seckill.rabbitmqListener.notify</p>
* <p>Company:东软集团(neusoft)</p>
* <p>Copyright:Copyright(c)2018</p>
* User: 段美林
* Date: 2018/6/3 0:27
* Description: 延迟任务测试--->消息确认回调类
*/
public class NotifyConfirmCallBackListener implements ConfirmCallback { private final Logger logger = LoggerFactory.getLogger(this.getClass()); /**
* Confirmation callback.
*
* @param correlationData correlation data for the callback.
* @param ack true for ack, false for nack
* @param cause An optional cause, for nack, when available, otherwise null.
*/
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
logger.info("延迟测试---确认消息完成-------->confirm--:correlationData:" + correlationData.getId() + ",ack:" + ack + ",cause:" + cause);
}
}
NotifyConsumerListener.java
package org.seckill.rabbitmqListener.notify; import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener; /**
* <p>Title: org.seckill.rabbitmqListener.notify</p>
* <p>Company:东软集团(neusoft)</p>
* <p>Copyright:Copyright(c)2018</p>
* User: 段美林
* Date: 2018/6/3 0:27
* Description: 订单通知队列监听服务
* 实现延迟任务的功能
*/
public class NotifyConsumerListener implements ChannelAwareMessageListener { private final Logger logger = LoggerFactory.getLogger(this.getClass()); /**
* Callback for processing a received Rabbit message.
* <p>Implementors are supposed to process the given Message,
* typically sending reply messages through the given Session.
*
* @param message the received AMQP message (never <code>null</code>)
* @param channel the underlying Rabbit Channel (never <code>null</code>)
* @throws Exception Any.
*/
public void onMessage(Message message, Channel channel) throws Exception {
try {
//将字节流对象转换成Java对象
// Seckill seckill=(Seckill) new ObjectInputStream(new ByteArrayInputStream(message.getBody())).readObject(); String returnStr = new String(message.getBody(),"UTF-8");
JSONObject jsStr = JSONObject.parseObject(returnStr); logger.info("延迟测试--消费开始:名称为--===>" + jsStr.getString("name") + "----->返回消息:" + returnStr + "||||消息的Properties:--》" + message.getMessageProperties()); //TODO 进行相关业务操作 //成功处理业务,那么返回消息确认机制,这个消息成功处理OK
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); } catch (Exception e) {
if (message.getMessageProperties().getRedelivered()) {
//消息已经进行过一次轮询操作,还是失败,将拒绝再次接收本消息
logger.info("消息已重复处理失败,拒绝再次接收...");
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true); // 拒绝消息 //TODO 进行相关业务操作 } else {
//消息第一次接收处理失败后,将再此回到队列中进行 再一次轮询操作
logger.info("消息即将再次返回队列处理...");
//处理失败,那么返回消息确认机制,这个消息没有成功处理,返回到队列中
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
}
}
}
}
NotifyFailedCallBackListener.java
package org.seckill.rabbitmqListener.notify; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback; /**
* <p>Title: org.seckill.rabbitmqListener.notify</p>
* <p>Company:东软集团(neusoft)</p>
* <p>Copyright:Copyright(c)2018</p>
* User: 段美林
* Date: 2018/6/3 0:28
* Description: 延迟任务测试----> 消息发送失败回调类
*/
public class NotifyFailedCallBackListener implements ReturnCallback { private final Logger logger = LoggerFactory.getLogger(this.getClass()); /**
* Returned message callback.
*
* @param message the returned message.
* @param replyCode the reply code.
* @param replyText the reply text.
* @param exchange the exchange.
* @param routingKey the routing key.
*/
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
logger.info("延迟测试------------->return--message:" +
new String(message.getBody()) +
",replyCode:" + replyCode + ",replyText:" + replyText +
",exchange:" + exchange + ",routingKey:" + routingKey);
}
}
5、编写消息队列的操作类和接口:
MQProducer.java
package org.seckill.utils.rabbitmq; import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.support.CorrelationData; /**
* <p>Title: org.seckill.utils.rabbitmq</p>
* <p>Company:东软集团(neusoft)</p>
* <p>Copyright:Copyright(c)2018</p>
* User: 段美林
* Date: 2018/5/30 11:49
* Description: No Description
*/
public interface MQProducer { /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a default routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param message
*/
void sendDataToRabbitMQ(java.lang.Object message); /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a default routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param message
* @param messagePostProcessor
*/
void sendDataToRabbitMQ(java.lang.Object message, MessagePostProcessor messagePostProcessor); /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a default routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param message
* @param messagePostProcessor
* @param correlationData
*/
void sendDataToRabbitMQ(java.lang.Object message, MessagePostProcessor messagePostProcessor, CorrelationData correlationData); /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param routingKey
* @param message
*/
void sendDataToRabbitMQ(java.lang.String routingKey, java.lang.Object message); /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param routingKey
* @param message
* @param correlationData
*/
void sendDataToRabbitMQ(java.lang.String routingKey, java.lang.Object message, CorrelationData correlationData); /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param routingKey
* @param message
* @param messagePostProcessor
*/
void sendDataToRabbitMQ(java.lang.String routingKey, java.lang.Object message, MessagePostProcessor messagePostProcessor); /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param routingKey
* @param message
* @param messagePostProcessor
* @param correlationData
*/
void sendDataToRabbitMQ(java.lang.String routingKey, java.lang.Object message, MessagePostProcessor messagePostProcessor, CorrelationData correlationData); /**
* Convert a Java object to an Amqp Message and send it to a specific exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param exchange
* @param routingKey
* @param message
*/
void sendDataToRabbitMQ(java.lang.String exchange, java.lang.String routingKey, java.lang.Object message); /**
* Convert a Java object to an Amqp Message and send it to a specific exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param exchange
* @param routingKey
* @param message
* @param correlationData
*/
void sendDataToRabbitMQ(java.lang.String exchange, java.lang.String routingKey, java.lang.Object message, CorrelationData correlationData); /**
* Convert a Java object to an Amqp Message and send it to a specific exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param exchange
* @param routingKey
* @param message
* @param messagePostProcessor
*/
void sendDataToRabbitMQ(java.lang.String exchange, java.lang.String routingKey, java.lang.Object message, MessagePostProcessor messagePostProcessor); /**
* Convert a Java object to an Amqp Message and send it to a specific exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
* @param exchange
* @param routingKey
* @param message
* @param messagePostProcessor
* @param correlationData
*/
void sendDataToRabbitMQ(java.lang.String exchange, java.lang.String routingKey, java.lang.Object message, MessagePostProcessor messagePostProcessor, CorrelationData correlationData); Message messageBuil(Object handleObject, String msgId); String getMsgId();
}
MQProducerImpl.java
package org.seckill.utils.rabbitmq.Impl; import com.alibaba.fastjson.JSONObject;
import org.seckill.utils.rabbitmq.MQProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.stereotype.Component; import java.io.UnsupportedEncodingException;
import java.util.UUID; /**
* <p>Title: org.seckill.utils.rabbitmq.Impl</p>
* <p>Company:东软集团(neusoft)</p>
* <p>Copyright:Copyright(c)2018</p>
* User: 段美林
* Date: 2018/6/2 22:54
* Description: 消息生产者操作主体类
*/
@Component
public class MQProducerImpl implements MQProducer{ private static final Logger logger = LoggerFactory.getLogger(MQProducerImpl.class); private RabbitTemplate rabbitTemplate; /**
* Sets the rabbitTemplate.
* <p>
* <p>You can use getRabbitTemplate() to get the value of rabbitTemplate</p>
*
* @param rabbitTemplate rabbitTemplate
*/
public void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
} /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a default routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param message
*/
public void sendDataToRabbitMQ(Object message) {
try {
if (message instanceof Message){
Message messageSend = (Message) message;
String msgId = messageSend.getMessageProperties().getCorrelationId();
CorrelationData correlationData = new CorrelationData(msgId);
rabbitTemplate.convertAndSend(rabbitTemplate.getRoutingKey(),message,correlationData);
}else {
rabbitTemplate.convertAndSend(message);
}
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a default routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param message
* @param messagePostProcessor
*/
public void sendDataToRabbitMQ(Object message, MessagePostProcessor messagePostProcessor) {
try {
if (message instanceof Message){
Message messageSend = (Message) message;
String msgId = messageSend.getMessageProperties().getCorrelationId();
CorrelationData correlationData = new CorrelationData(msgId);
rabbitTemplate.convertAndSend(rabbitTemplate.getRoutingKey(),message,messagePostProcessor,correlationData);
}else {
rabbitTemplate.convertAndSend(message, messagePostProcessor);
}
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a default routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param message
* @param messagePostProcessor
* @param correlationData
*/
public void sendDataToRabbitMQ(Object message, MessagePostProcessor messagePostProcessor, CorrelationData correlationData) {
try {
rabbitTemplate.convertAndSend(message, messagePostProcessor, correlationData);
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param routingKey
* @param message
*/
public void sendDataToRabbitMQ(String routingKey, Object message) {
try {
if (message instanceof Message){
Message messageSend = (Message) message;
String msgId = messageSend.getMessageProperties().getCorrelationId();
CorrelationData correlationData = new CorrelationData(msgId);
rabbitTemplate.convertAndSend(routingKey,message,correlationData);
}else {
rabbitTemplate.convertAndSend(routingKey, message);
}
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param routingKey
* @param message
* @param correlationData
*/
public void sendDataToRabbitMQ(String routingKey, Object message, CorrelationData correlationData) {
try {
rabbitTemplate.convertAndSend(routingKey, message, correlationData);
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param routingKey
* @param message
* @param messagePostProcessor
*/
public void sendDataToRabbitMQ(String routingKey, Object message, MessagePostProcessor messagePostProcessor) {
try {
if (message instanceof Message){
Message messageSend = (Message) message;
String msgId = messageSend.getMessageProperties().getCorrelationId();
CorrelationData correlationData = new CorrelationData(msgId);
rabbitTemplate.convertAndSend(routingKey,message,messagePostProcessor,correlationData);
}else {
rabbitTemplate.convertAndSend(routingKey, message, messagePostProcessor);
}
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a default exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param routingKey
* @param message
* @param messagePostProcessor
* @param correlationData
*/
public void sendDataToRabbitMQ(String routingKey, Object message, MessagePostProcessor messagePostProcessor, CorrelationData correlationData) {
try {
rabbitTemplate.convertAndSend(routingKey, message, messagePostProcessor, correlationData);
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a specific exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param exchange
* @param routingKey
* @param message
*/
public void sendDataToRabbitMQ(String exchange, String routingKey, Object message) {
try {
if (message instanceof Message){
Message messageSend = (Message) message;
String msgId = messageSend.getMessageProperties().getCorrelationId();
CorrelationData correlationData = new CorrelationData(msgId);
rabbitTemplate.convertAndSend(routingKey,message,correlationData);
}else {
rabbitTemplate.convertAndSend(exchange, routingKey, message);
}
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a specific exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param exchange
* @param routingKey
* @param message
* @param correlationData
*/
public void sendDataToRabbitMQ(String exchange, String routingKey, Object message, CorrelationData correlationData) {
try {
rabbitTemplate.convertAndSend(exchange, routingKey, message, correlationData);
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a specific exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param exchange
* @param routingKey
* @param message
* @param messagePostProcessor
*/
public void sendDataToRabbitMQ(String exchange, String routingKey, Object message, MessagePostProcessor messagePostProcessor) {
try {
rabbitTemplate.convertAndSend(exchange, routingKey, message, messagePostProcessor);
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* Convert a Java object to an Amqp Message and send it to a specific exchange with a specific routing key.
* 由于配置了JSON转换,这里是将Java对象转换成JSON字符串的形式。
*
* @param exchange
* @param routingKey
* @param message
* @param messagePostProcessor
* @param correlationData
*/
public void sendDataToRabbitMQ(String exchange, String routingKey, Object message, MessagePostProcessor messagePostProcessor, CorrelationData correlationData) {
try {
rabbitTemplate.convertAndSend(exchange, routingKey, message, messagePostProcessor, correlationData);
} catch (AmqpException e) {
logger.error(e.getMessage(), e);
}
} /**
* 构建Message对象,进行消息发送
* @param handleObject
* @param msgId
* @return
*/
public Message messageBuil(Object handleObject, String msgId) {
try {
//先转成JSON
String objectJSON = JSONObject.toJSONString(handleObject);
//再构建Message对象
Message messageBuil = MessageBuilder.withBody(objectJSON.getBytes("UTF-8")).setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)
.setCorrelationId(msgId).build();
return messageBuil;
} catch (UnsupportedEncodingException e) {
logger.error("构建Message出错:" + e.getMessage(),e);
return null;
}
} /**
* 生成唯一的消息操作id
* @return
*/
public String getMsgId() {
return UUID.randomUUID().toString();
} }
至此就完成了延迟消息队列的所有代码实现,
rabbitmq的延迟消息队列实现的更多相关文章
- 基于redis的延迟消息队列设计
需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...
- 基于redis的延迟消息队列设计(转)
需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...
- RabbitMQ AMQP (高级消息队列协议)
目录 RabbitMQ AMQP (高级消息队列协议) Message Queue 简介 概念 基本组成 场景及作用 AMQP简介 模型架构 基础组件 AMQP-RabbitMQ 简介 模型 特性 参 ...
- 第二百九十二节,RabbitMQ多设备消息队列-Python开发
RabbitMQ多设备消息队列-Python开发 首先安装Python开发连接RabbitMQ的API,pika模块 pika模块为第三方模块 对于RabbitMQ来说,生产和消费不再针对内存里的一 ...
- 第二百九十一节,RabbitMQ多设备消息队列-安装与简介
RabbitMQ多设备消息队列-安装与简介 RabbitMQ简介 解释RabbitMQ,就不得不提到AMQP(Advanced Message Queuing Protocol)协议. AMQP协议是 ...
- Delayer 基于 Redis 的延迟消息队列中间件
Delayer 基于 Redis 的延迟消息队列中间件,采用 Golang 开发,支持 PHP.Golang 等多种语言客户端. 参考 有赞延迟队列设计 中的部分设计,优化后实现. 项目链接:http ...
- 阿里云RocketMQ定时/延迟消息队列实现
新的阅读体验:http://www.zhouhong.icu/post/157 一.业务需求 需要实现一个提前二十分钟通知用户去做某件事的一个业务,拿到这个业务首先想到的最简单得方法就是使用Redis ...
- AMQP协议与RabbitMQ、MQ消息队列的应用场景
什么是AMQP? 在异步通讯中,消息不会立刻到达接收方,而是被存放到一个容器中,当满足一定的条件之后,消息会被容器发送给接收方,这个容器即消息队列,而完成这个功能需要双方和容器以及其中的各个组件遵守统 ...
- spring boot Rabbitmq集成,延时消息队列实现
本篇主要记录Spring boot 集成Rabbitmq,分为两部分, 第一部分为创建普通消息队列, 第二部分为延时消息队列实现: spring boot提供对mq消息队列支持amqp相关包,引入即可 ...
随机推荐
- Openlayers4中地图的导出
概述: 本文讲述Openlayers4中地图的导出,包括调用天地图切片跨域.Geoserver11 WMS跨域等. 效果: 导出图片 页面展示 实现代码: document.getElementByI ...
- Win7系统Visual Studio 2013配置OpenCV3.1图文详解
Win7系统Visual Studio 2013配置OpenCV3.1图文详解 OpenCV3.1对硬件加速和移动开发的支持相对于老版本都有了较大改进,支持新的开发工具,更易于扩展,配置方式也比以前简 ...
- Jenkins上War文件部署实战
War文件部署 1.jenkins需要安装Deploy Plugin插件:在[系统管理]-[插件管理]下,如果没有安装,则在可选插件下找到该插件,然后安装(如图是1.5版本安装好的截图) 2.在构建的 ...
- 在Outlook中修改脱机文件(.ost)的保存位置
方法一 少读者所在公司的邮箱客户端都在使用微软 Exchange Server 的“缓存 Exchange 模式”.Outlook会默认将脱机文件(.ost文件)保存在C盘上. 但很多读者不希望Out ...
- ab压力测试之post与get请求
安装ab工具 yum install httpd-tools 参数说明 -n:执行的请求个数,默认时执行一个请求 -c:一次产生的请求个数,即并发个数 -p:模拟post请求,文件格式为gid=2&a ...
- debian8下pgsql的主备同步热切手动脚本
9以后,通过流复制直接做 主:192.168.1.111 从:192.168.1.222 需要在postgres帐号下先配置ssh互信,双机都配置 sh-keygen -t rsa ssh-copy- ...
- Windows应用程序的VC链接器设置
Windows应用程序的VC链接器设置 /*转载请注明出自 听风独奏 www.GbcDbj.com */ Windows应用程序分为GUI(Graphical User Interface)和CUI( ...
- Java 字符串拼接 StringBuilder() StringBuffer
字符串拼接 普通方式 public class StringDemo2 { public static void main(String[] args) { // 表示获取从1970- ...
- nginx学习1
访问abc.xxx.com就跳转到www.xxx.com/abc.html server { listen 80; server_name abc.xxx.com; rewrite ^.*$ ww ...
- Hive文件的存储格式
hive文件存储格式包括以下几类: TEXTFILE SEQUENCEFILE RCFILE 自定义格式 其中TEXTFILE为默认格式,建表时不指定默认为这个格式,导入数据时会直接把数据文件拷贝到h ...