起因
实现一个封号功能,可以封1,3,7,30,永久的不同天数,其中1,3,7,30是通过springcloud stream整合rabbitmq的延迟队列来实现,到期自动解封.
问题
当时间设置30天会出现立即解封的情况
- 生产者:
Map<String, Object> paramMap = Maps.newHashMap();
paramMap.put("uid", userId);
//延迟发送解禁消息到 MQ
if (lockDays > 0) {
Message message = MessageBuilder.withPayload(JSON.toJSONString(paramMap)).setHeader("x-delay", 60 * 60 * 24 * 1000 * lockDays).build();
customSink.doLockoutput().send(message);
}
- 消费者:
@StreamListener(CustomSink.LOCK_INPUT)
public void loclReceiver(Message msg,@Headers Map headers) {
String payload = new String(((byte[]) msg.getPayload()));
Map<String, Object> paramMap = JSON.parseObject(payload, Map.class);
Long userId = Long.valueOf(paramMap.getOrDefault("uid", "0").toString());
log.debug("headers{}",headers);
log.info("发起解锁请求:msg={}, userId={}", msg, userId);
try {
int flag = iSysUserService.unLockUser(userId);
log.info("处理解锁消息: flag={}, userId={}", flag, userId);
} catch (Exception e) {
log.error("loclReceiver message exception: {}", e.getMessage());
}
}
原因
通过查看headers
{
amqp_receivedDeliveryMode=PERSISTENT,
amqp_receivedRoutingKey=delay-lock-topic,
amqp_receivedExchange=delay-lock-topic,
amqp_deliveryTag=1, deliveryAttempt=1,
amqp_consumerQueue=delay-lock-topic.lock-user,
amqp_receivedDelay=-1702967296,
amqp_redelivered=false,
id=eaa38080-5977-921c-a7b8-67950143cf99,
amqp_consumerTag=amq.ctag-3UBapAhFMzbbTRfuZvIRxQ,
contentType=application/json,
timestamp=1596440890730
}
发现amqp_receivedDelay=-1702967296,即消息延迟时间
原来当时间设置30天的时候,超过了int的最大值,这时候为负数
解决方案
改用long计算
Tips
单独使用rabbitmq,来实现,这种情况会报错,不会出现立即消费的情况