阿里云MNS消息`The receipt handle you provided has expired`

项目中做一个ES打标功能,当促销活动变动时(启用、禁用、审核通过等),通过阿里云MNS队列推送消息,消费方监听消息进行业务处理。
因为活动分多钟类型,有的类型门店、商品数量较多,消费处理需要一定时间,基础组件封装了消息消费,在消费完成后会调用阿里云MNS的SDK删除消息,如下:

this.mnsClient.getQueueRef(this.consumerQueue).deleteMessage(message.getReceiptHandle());

日志中发现异常信息:

com.aliyun.mns.common.ServiceException: The receipt handle you provided has expired.
        at com.aliyun.mns.common.http.ExceptionResultParser.parse(ExceptionResultParser.java:42)
        at com.aliyun.mns.common.http.ExceptionResultParser.parse(ExceptionResultParser.java:12)
        at com.aliyun.mns.common.http.HttpCallback.handleResult(HttpCallback.java:155)
        at com.aliyun.mns.common.http.HttpCallback.buildResponseMessage(HttpCallback.java:128)
        at com.aliyun.mns.common.http.HttpCallback.completed(HttpCallback.java:88)
        at com.aliyun.mns.common.http.HttpCallback.completed(HttpCallback.java:22)
        at shaded.org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:119)
        at shaded.org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseCompleted(DefaultClientExchangeHandlerImpl.java:177)
        at shaded.org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:412)
        at shaded.org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:305)
        at shaded.org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:267)
        at shaded.org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81)
        at shaded.org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39)
        at shaded.org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:116)
        at shaded.org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:164)
        at shaded.org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:339)
        at shaded.org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:317)

同时观察日志发现消息有被重复消费。
查询官方文档:

队列消息消费有个到期时间VisibilityTimeout,默认为30s。
消息被消费端接收,消息状态从active变为inactive,超过VisibilityTimeout后,又变为active,然后消息可继续被其他消费端消费,并且消息的ReceiptHandle失效。
因为消息处理慢超过了30s,因此项目中消费方又接收到了消息,消息的ReceiptHandle失效因此删除消息报错。

解决方法:

  • 方法1:
    监听者拿到消息,在记录日志后处理消息前删除消息
  • 方法2:
    在阿里云后台创建队列的界面中,修改VisibilityTimeout时间,默认30s,根据实际处理情况调大点,比如改为600s;
    同时根据消息id,在消息日志表里判断是否已处理过该消息,避免重复消费
posted @ 2020-10-31 22:42  cdfive  阅读(996)  评论(0编辑  收藏  举报