|
|
@@ -0,0 +1,133 @@
|
|
|
+package com.uas.ps.message.rabbit;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.rabbitmq.client.AMQP;
|
|
|
+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;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+
|
|
|
+/**
|
|
|
+ * base MessageListener, 实现了消息确认,消息失败延迟机制
|
|
|
+ * @author liuam
|
|
|
+ * @since 2018/9/13 0013 下午 14:37
|
|
|
+ */
|
|
|
+public abstract class BaseMessageListener implements ChannelAwareMessageListener {
|
|
|
+
|
|
|
+ private final static Logger logger = LoggerFactory.getLogger(BaseMessageListener.class);
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onMessage(Message message, Channel channel) throws Exception {
|
|
|
+ String messageJson = new String(message.getBody());
|
|
|
+ long tag = message.getMessageProperties().getDeliveryTag();
|
|
|
+ String queueName = message.getMessageProperties().getConsumerQueue();
|
|
|
+ processMessage(messageJson, channel, tag, queueName);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理消息
|
|
|
+ *
|
|
|
+ * @param messageJson 消息Json内容
|
|
|
+ * @param channel 管道
|
|
|
+ * @param tag Delivery Tag
|
|
|
+ * @param queueName 队列名
|
|
|
+ */
|
|
|
+ private void processMessage(String messageJson, Channel channel, long tag, String queueName) {
|
|
|
+ MessageInfo messageInfo = getMessageInfo(messageJson);
|
|
|
+ //当消息不符合格式MessageInfo格式时,丢弃消息
|
|
|
+ if (messageInfo == null) {
|
|
|
+ logger.warn("接收消息处理.消息格式.异常,messageJson:{},tag:{}", messageJson, tag);
|
|
|
+ basicNack(channel, tag);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ logger.info("接收消息处理[RabbitMessageListener.receiveMessage].处理开始,messageJson:{},tag:{}", messageJson, tag);
|
|
|
+ processMessage(messageInfo);
|
|
|
+ logger.info("接收消息处理[RabbitMessageListener.receiveMessage].处理结束,messageJson:{},tag:{}", messageJson, tag);
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("接收消息处理[RabbitMessageListener.receiveMessage].异常,messageJson:{},tag:{}", messageJson, tag, e);
|
|
|
+ //出现异常时,消息转发为延时消息
|
|
|
+ sendDelayMessage(messageInfo, channel, queueName);
|
|
|
+ } finally {
|
|
|
+ basicAck(channel, tag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送延时消息
|
|
|
+ *
|
|
|
+ * @param messageInfo
|
|
|
+ * @param channel
|
|
|
+ * @param queueName
|
|
|
+ */
|
|
|
+ private void sendDelayMessage(MessageInfo messageInfo, Channel channel, String queueName) {
|
|
|
+ //重试次数+1
|
|
|
+ messageInfo.setRetryCount(messageInfo.getRetryCount() + 1);
|
|
|
+ String messageJson = JSON.toJSONString(messageInfo);
|
|
|
+
|
|
|
+ try {
|
|
|
+ String dalayQueueName = queueName + RabbitConstants.DELAY_QUEUE_NAME_SUFFIX;
|
|
|
+ AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
|
|
|
+ builder.expiration(RabbitConstants.DELAY_TIME);
|
|
|
+
|
|
|
+ channel.basicPublish(RabbitConstants.AMQ_DIRECT, dalayQueueName, builder.build(), messageJson.getBytes());
|
|
|
+ logger.info("发送延时消息[RabbitMessageListener.sendDelayMessage].正常,messageJson:{},queueName:{}", messageJson, queueName);
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("发送延时消息[RabbitMessageListener.sendDelayMessage].异常,messageJson:{},queueName:{}", messageJson, queueName, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理消息
|
|
|
+ *
|
|
|
+ * @param messageInfo 消息体
|
|
|
+ * @throws Exception 处理失败时,抛出异常
|
|
|
+ */
|
|
|
+ public abstract void processMessage(MessageInfo messageInfo) throws Exception;
|
|
|
+
|
|
|
+
|
|
|
+ private MessageInfo getMessageInfo(String messageJson) {
|
|
|
+ MessageInfo messageInfo = null;
|
|
|
+ try {
|
|
|
+ messageInfo = JSON.parseObject(messageJson, MessageInfo.class);
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("获取消息内容实体[RabbitMessageListener.getMessageInfo].异常,messageJson:{}", messageJson, e);
|
|
|
+ }
|
|
|
+ return messageInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 消息应答No
|
|
|
+ *
|
|
|
+ * @param channel
|
|
|
+ * @param tag
|
|
|
+ */
|
|
|
+ private void basicNack(Channel channel, long tag) {
|
|
|
+ try {
|
|
|
+ channel.basicNack(tag, false, false);
|
|
|
+ logger.info("接收消息处理.消息应答No[RabbitMessageListener.receiveMessage.basicNack].正常,tag:{}", tag);
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("接收消息处理.消息应答No[RabbitMessageListener.receiveMessage.basicNack].异常,tag:{}", tag, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 消息应答Yes
|
|
|
+ *
|
|
|
+ * @param channel
|
|
|
+ * @param tag
|
|
|
+ */
|
|
|
+ private void basicAck(Channel channel, long tag) {
|
|
|
+ try {
|
|
|
+ channel.basicAck(tag, false);
|
|
|
+ logger.info("接收消息处理.消息应答Yes[RabbitMessageListener.receiveMessage.basicAck].正常,tag:{}", tag);
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("接收消息处理.消息应答Yes[RabbitMessageListener.receiveMessage.basicAck].异常,tag:{}", tag, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|