io.github.smart.cloud.starter.rabbitmq.util.MqUtil Maven / Gradle / Ivy
The newest version!
/*
* Copyright © 2019 collin ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.smart.cloud.starter.rabbitmq.util;
import io.github.smart.cloud.starter.rabbitmq.MqConstants;
import io.github.smart.cloud.starter.rabbitmq.adapter.IRabbitMqAdapter;
import io.github.smart.cloud.starter.rabbitmq.annotation.MqConsumerFailRetry;
import io.github.smart.cloud.starter.rabbitmq.enums.RetryResult;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.core.annotation.AnnotationUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* mq工具类
*
* @author collin
* @date 2021-06-30
*/
@Slf4j
public final class MqUtil {
/**
* 消费失败后是否能重试
*/
@Setter
private static boolean enableRetryAfterConsumerFail = false;
private MqUtil() {
}
/**
* 创建DIRECT类型延迟交换机
*
* @param exchangeName 交换机名称
* @return
*/
public static Exchange createDelayExchange(String exchangeName) {
return createDelayExchange(exchangeName, ExchangeTypes.DIRECT);
}
/**
* 创建延迟交换机
*
* @param exchangeName 交换机名称
* @param exchangeType 交换机类型
* @return
* @see ExchangeTypes
*/
public static Exchange createDelayExchange(String exchangeName, String exchangeType) {
Map args = new HashMap<>(1);
args.put(MqConstants.DELAY_EXCHANGE_TYPE_KEY, exchangeType);
return new CustomExchange(exchangeName, MqConstants.DELAY_MESSAGE_TYPE, true, false, args);
}
/**
* 发送消息
*
* delayTime取值example:String.valueOf(TimeUnit.SECONDS.toMillis(delayMillis))
*
* @param rabbitMqAdapter
* @param exchange
* @param routingKey
* @param body
* @param retriedTimes
* @param delayMillis
* @param
*/
public static void send(IRabbitMqAdapter rabbitMqAdapter, String exchange, String routingKey, T body, Integer retriedTimes, Long delayMillis) {
Message message = null;
if (body instanceof Message) {
message = (Message) body;
} else {
message = rabbitMqAdapter.getMessageConverter().toMessage(body, new MessageProperties());
}
MessageProperties messageProperties = message.getMessageProperties();
if (delayMillis != null && delayMillis > 0) {
messageProperties.setHeader(MessageProperties.X_DELAY, delayMillis);
}
if (retriedTimes != null) {
messageProperties.setHeader(MqConstants.CONSUMER_RETRIED_TIMES, retriedTimes);
}
if (log.isInfoEnabled()) {
log.info("mq.send|exchange={}, routingKey={}, delayMillis={}, retriedTimes={}, msg={}", exchange, routingKey, delayMillis, retriedTimes, message);
}
rabbitMqAdapter.send(exchange, routingKey, message);
}
/**
* 消费失败重试
*
* @param rabbitMqAdapter
* @param body
* @param headers
* @param consumerClass
* @param
* @return
*/
public static RetryResult retryAfterConsumerFail(IRabbitMqAdapter rabbitMqAdapter, T body, Map headers, Class> consumerClass) {
if (!MqUtil.enableRetryAfterConsumerFail) {
return RetryResult.NOT_SUPPORT;
}
if (body == null) {
return RetryResult.NOT_SUPPORT;
}
RabbitListener rabbitListener = AnnotationUtils.findAnnotation(consumerClass, RabbitListener.class);
if (rabbitListener == null) {
return RetryResult.NOT_SUPPORT;
}
// 失败后,发送延迟消息重试
MqConsumerFailRetry mqConsumerFailRetry = AnnotationUtils.findAnnotation(consumerClass, MqConsumerFailRetry.class);
if (mqConsumerFailRetry == null) {
log.warn("MqConsumerFailRetry not found, retry is skipped!");
return RetryResult.NOT_SUPPORT;
}
Object currentRetriedTimes = headers.get(MqConstants.CONSUMER_RETRIED_TIMES);
int nextRetriedTimes = (currentRetriedTimes == null) ? 1 : ((int) currentRetriedTimes + 1);
if (nextRetriedTimes > mqConsumerFailRetry.maxRetryTimes()) {
log.warn("Maximum times[{}] of retries reached", mqConsumerFailRetry.maxRetryTimes());
return RetryResult.REACHED_RETRY_THRESHOLD;
}
// 队列的名称
String queueName = rabbitListener.queues()[0];
//延迟交换机名称
String retryExchangeName = MqNameUtil.getRetryExchangeName(queueName, mqConsumerFailRetry);
//延迟路由键
String retryRouteKeyName = MqNameUtil.getRetryRouteKeyName(queueName, mqConsumerFailRetry);
long retryIntervalSeconds = getRetryIntervalSeconds(mqConsumerFailRetry, nextRetriedTimes);
send(rabbitMqAdapter, retryExchangeName, retryRouteKeyName, body, nextRetriedTimes, TimeUnit.SECONDS.toMillis(retryIntervalSeconds));
return RetryResult.SUCCESS;
}
/**
* 获取重试的间隔时间(单位:秒)
*
* @param mqConsumerFailRetry
* @param nextRetriedTimes nextRetriedTimes从1开始
* @return
*/
private static long getRetryIntervalSeconds(MqConsumerFailRetry mqConsumerFailRetry, int nextRetriedTimes) {
long[] retryIntervalSeconds = mqConsumerFailRetry.retryIntervalSeconds();
int index = (nextRetriedTimes <= retryIntervalSeconds.length) ? (nextRetriedTimes - 1) : retryIntervalSeconds.length - 1;
return retryIntervalSeconds[index];
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy