配置类
/**
* 商户金融权益分配rebbit配置
*/
@Configuration
public class ShopDelegateRabbitMqConfig {
private static final Logger log = LoggerFactory.getLogger(ShopDelegateRabbitMqConfig.class);
@Autowired
private DelegateShopConfig delegateShopConfig;
private String queueName;
private String exchangeName;
private String routingKey;
@PostConstruct
private void init() {
String ip = getIp();
if (ip.startsWith("17216")) {
queueName = concatString(delegateShopConfig.getQueueName(), ip.replace(".", ""));
exchangeName = concatString(delegateShopConfig.getExchangeName(), ip.replace(".", ""));
routingKey = concatString(delegateShopConfig.getRoutingKey(), ip.replace(".", ""));
} else {
queueName = delegateShopConfig.getQueueName();
exchangeName = delegateShopConfig.getExchangeName();
routingKey = delegateShopConfig.getRoutingKey();
}
log.info("mq初始化信息完成,{},{},{}", queueName, exchangeName, routingKey);
}
private String getIp() {
InetAddress ip = null;
String localIp = "";
try {
ip = InetAddress.getLocalHost();
localIp = ip.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return localIp.replace(".", "");
}
private String concatString(String str, String ip) {
return str + "_" + ip;
}
@Bean
public Queue shopDelegateDelayQueue() {
return new Queue(queueName);
}
/*@Bean
public Queue shopDelegateDelayQueue() {
return new Queue("shopDelegate_queue1");
}*/
@Bean
public CustomExchange shopDelegateDelayExchange() {
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-delayed-type", "direct");
return new CustomExchange(exchangeName, "x-delayed-message", true, false, args);
}
@Bean
public Binding bindingshopDelegateDelayNotify(@Qualifier("shopDelegateDelayQueue") Queue queue,
@Qualifier("shopDelegateDelayExchange") CustomExchange customExchange) {
return BindingBuilder.bind(queue).to(customExchange).with(routingKey).noargs();
}
public String getQueueName() {
return queueName;
}
public void setQueueName(String queueName) {
this.queueName = queueName;
}
public String getExchangeName() {
return exchangeName;
}
public void setExchangeName(String exchangeName) {
this.exchangeName = exchangeName;
}
public String getRoutingKey() {
return routingKey;
}
public void setRoutingKey(String routingKey) {
this.routingKey = routingKey;
}
}
判断并入队
@Override
public Object autoDelegate(int shopId, int currentUserId) throws Exception {
log.info("商户金融权益自动分配,商户ID:{}", shopId);
// 获取金融权益数据,判断是否已分配
Map<String, Object> shopDelegateInfo = shopDelegateMapper.findShopDelegateInfo(shopId);
if (shopDelegateInfo != null && !shopDelegateInfo.isEmpty()
&& StringUtils.isNotBlank(ObjectUtils.toString(shopDelegateInfo.get("developidaft"), ""))) {
log.info("商户金融权益已分配,禁止自动分配,商户ID:{}", shopId);
return ResultDataUtils.failResult("商户已分配金融权益,禁止自动分配");
}
// 如果未分配,投递金融权益队列,自动分配
Map<String, Object> params = new HashMap<>();
params.put("shopId", shopId);
rabbitTemplate.convertAndSend(shopDelegateRabbitMqConfig.getExchangeName(),
shopDelegateRabbitMqConfig.getRoutingKey(), JSONObject.toJSONString(params));
return ResultDataUtils.successResult("已开始自动分配,请稍后查询分配结果");
}
监听并消费
@Component
public class ShopDelegateListener {
private static Logger log = LoggerFactory.getLogger(ShopDelegateListener.class);
private static final String delegateKey = "DELEGATE_";
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RedisUtil redisUtil;
@Autowired
private DelegateShopMapper shopDelegateMapper;
@Autowired
private DelegateShopService shopDelegateService;
@Autowired
private DelegateShopConfig delegateShopConfig;
@Autowired
private ShopDelegateRabbitMqConfig shopDelegateRabbitMqConfig;
/*@RabbitListener(queues = "shopDelegate_queue1")*/
/*@RabbitListener(queues = "${delegate.queueName}")*/
@RabbitListener(queues = "#{shopDelegateRabbitMqConfig.getQueueName()}")
@RabbitHandler
public void directMessage(String sendMessage, Channel channel, Message message) throws Exception {
String shopId = "";
long num = 0;
try {
// prefetchCount限制每个消费者在收到下一个确认回执前一次可以最大接受多少条消息,
//通过basic.qos方法设置prefetch_count=1,这样RabbitMQ就会使得每个Consumer在同一个时间点最多处理一个Message
channel.basicQos(1);
log.info("接收到金融权益分配请求[{}]", sendMessage);
JSONObject reqJson = JSONObject.parseObject(sendMessage);
shopId = reqJson.getString("shopId");
String redisKey = delegateKey + shopId;
num = redisUtil.incr(redisKey, 1);
redisUtil.expire(redisKey, 5 * 60);
if (StringUtils.isBlank(sendMessage) || StringUtils.isBlank(shopId)) {
log.info("权益分配请求参数为空!");
return;
}
log.info("商户[{}]第[{}]次金融权益分配开始", shopId, num);
// 调用金融权益分配请求
shopDelegateService.shopDelegate(Integer.valueOf(shopId));
// 确认消息已经消费成功
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
log.info("--" + sendMessage);
} catch (Exception e) {
log.error("商户[" + shopId + "]金融权益分配失败:", e);
// 判断已投递次数是否超过最大限值
if (isSend(shopId)) {
//延时重新处理 ,延迟投递60秒
log.info("商户[{}]第[{}]次金融权益分配失败,延迟投递60秒。。。", shopId, num);
SendDelayMQ(sendMessage, 60 * 1000);
} else {
log.info("商户[{}]分配金融权益,已补偿超过限值,分配失败", shopId);
shopDelegateMapper.updateDelegateStatus(shopId);
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
protected void SendDelayMQ(String orderNum, final Integer delay) {
rabbitTemplate.convertAndSend(shopDelegateRabbitMqConfig.getExchangeName(),
shopDelegateRabbitMqConfig.getRoutingKey(), orderNum, p -> {
p.getMessageProperties().setDelay(delay);
return p;
});
}
/**
* 判断是否继续投递 true 是 false 否
* @param shopId
* @return
*/
private boolean isSend(String shopId) {
// 分配失败,失败次数+1
int num = shopDelegateMapper.updateSendNum(shopId);
return num > 0 ? true : false;
}
}
/**
* 补偿轮询次数+1
* @param shopId
* @return
*/
@Update("update wm_shop_dispatch_delegate set sendNum = sendNum +1 where shopId = #{shopId} and sendNum < limitNum")
int updateSendNum(@Param("shopId") String shopId);
/**
* 更改分配金融权益失败
* @param shopId
* @return
*/
@Update("update wm_shop_dispatch_delegate set status = 2 where shopId = #{shopId}")
int updateDelegateStatus(@Param("shopId") String shopId);