第一部分:延迟消息的实现原理和知识点

使用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的延迟消息队列实现的更多相关文章

  1. 基于redis的延迟消息队列设计

    需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...

  2. 基于redis的延迟消息队列设计(转)

    需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...

  3. RabbitMQ AMQP (高级消息队列协议)

    目录 RabbitMQ AMQP (高级消息队列协议) Message Queue 简介 概念 基本组成 场景及作用 AMQP简介 模型架构 基础组件 AMQP-RabbitMQ 简介 模型 特性 参 ...

  4. 第二百九十二节,RabbitMQ多设备消息队列-Python开发

    RabbitMQ多设备消息队列-Python开发 首先安装Python开发连接RabbitMQ的API,pika模块 pika模块为第三方模块  对于RabbitMQ来说,生产和消费不再针对内存里的一 ...

  5. 第二百九十一节,RabbitMQ多设备消息队列-安装与简介

    RabbitMQ多设备消息队列-安装与简介 RabbitMQ简介 解释RabbitMQ,就不得不提到AMQP(Advanced Message Queuing Protocol)协议. AMQP协议是 ...

  6. Delayer 基于 Redis 的延迟消息队列中间件

    Delayer 基于 Redis 的延迟消息队列中间件,采用 Golang 开发,支持 PHP.Golang 等多种语言客户端. 参考 有赞延迟队列设计 中的部分设计,优化后实现. 项目链接:http ...

  7. 阿里云RocketMQ定时/延迟消息队列实现

    新的阅读体验:http://www.zhouhong.icu/post/157 一.业务需求 需要实现一个提前二十分钟通知用户去做某件事的一个业务,拿到这个业务首先想到的最简单得方法就是使用Redis ...

  8. AMQP协议与RabbitMQ、MQ消息队列的应用场景

    什么是AMQP? 在异步通讯中,消息不会立刻到达接收方,而是被存放到一个容器中,当满足一定的条件之后,消息会被容器发送给接收方,这个容器即消息队列,而完成这个功能需要双方和容器以及其中的各个组件遵守统 ...

  9. spring boot Rabbitmq集成,延时消息队列实现

    本篇主要记录Spring boot 集成Rabbitmq,分为两部分, 第一部分为创建普通消息队列, 第二部分为延时消息队列实现: spring boot提供对mq消息队列支持amqp相关包,引入即可 ...

随机推荐

  1. vue url生产二维码

    <template> <div id="QRcode"> <div class='QR-qrcode' style='display:none;'&g ...

  2. I.MX6 GPS Android HAL Framework 调试

    I.MX6 GPS Android HAL Framework 调试 一.参考文章: android4. GPS定位问题 http://blog.csdn.net/bzw073/article/det ...

  3. ambassador 学习九 多ambassador部署说明

    目前官方稳文档没有写,但是demo 里面有,所以就整理出来,其实目前demo里面的 多实例部署用了多个服务的service(使用nodeport 暴露地址,具体使用就是制定ambassador 实例的 ...

  4. Eclipse添加中文javadoc

    SUN官方API中文版[JDK1.6]1.6API文档(中文)的下载地址:ZIP格式用来设置javadoc,下载地址:http://download.java.net/jdk/jdk-api-loca ...

  5. gridview 绑定多个格式相同的数据源(数据查询合并)

    在做项目时,要求在同一个GridView中同时显示不同分组中的前若干条数据 几个技术要点: 1.数据分组,本方法中未用group by 2.几个结果格式相同的查询合并绑定 3.取查询结果的前或后若干条 ...

  6. FreeFileSync 4.2 发布,文件夹比较和同步工具

    FreeFileSync 是一款开源的文件夹比较和同步工具,可用于 Win 和 Lin 平台,最近发布了 4.2 版本. FreeFileSync 采用双面板设计,使用方法很简单: 在左面版和右面版上 ...

  7. 堆排序算法-python实现

    #-*- coding: UTF-8 -*- import numpy as np def MakeHeap(a): for i in xrange(a.size / 2 - 1, -1, -1):# ...

  8. CentOS查看显卡及GPU相关信息

    lspci  | grep -i vga 这样就可以显示机器上的显卡信息,比如 [root@localhost conf]# lspci | grep -i vga01:00.0 VGA compat ...

  9. jetty之嵌入式开发

    一.Jetty 是一个开源的servlet容器,它为基于Java的web容器,例如JSP和servlet提供运行环境.Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布.开发人员可 ...

  10. 使用PHP自带zlib函数 几行代码实现PHP文件打包下载zip

    <?php //获取文件列表 function list_dir($dir){ $result = array(); if (is_dir($dir)){ $file_dir = scandir ...