阿里雲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,在消息日志表里判斷是否已處理過該消息,避免重復消費


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM