日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
你知道嗎?Pulsar 也會重復消費?

背景

許久沒有分享 Java 相關(guān)的問題排查了,最近幫同事一起排查了一個問題:

創(chuàng)新互聯(lián)公司專注于保靖企業(yè)網(wǎng)站建設,成都響應式網(wǎng)站建設公司,商城網(wǎng)站制作。保靖網(wǎng)站建設公司,為保靖等地區(qū)提供建站服務。全流程按需定制開發(fā),專業(yè)設計,全程項目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務

在使用 Pulsar 消費時,發(fā)生了同一條消息反復消費的情況。

排查

當他告訴我這個現(xiàn)象的時候我就持懷疑態(tài)度,根據(jù)之前使用的經(jīng)驗 Pulsar 在官方文檔以及 API 中都解釋過:

只有當設置了消費的 ackTimeout 并超時消費時才會重復投遞消息,默認情況下是關(guān)閉的,查看代碼也確實沒有開啟。

那會不會是調(diào)用了 negativeAcknowledge() 方法呢(調(diào)用該方法也會觸發(fā)重新投遞),因為我們使用了一個第三方庫 https://github.com/majusko/pulsar-java-spring-boot-starter 只有當拋出異常時才會調(diào)用該方法。

查閱代碼之后也沒有地方拋出異常,甚至整個過程中都沒看到異常產(chǎn)生;這就有點詭異了。

復現(xiàn)

為了捋清楚整個事情的來龍去脈,詳細了解了他的使用流程;

其實也就是業(yè)務出現(xiàn)了 bug,他在消息消費時 debug 然后進行單步調(diào)試,當走完一次調(diào)試后,沒多久馬上又收到了同樣的消息。

但奇怪的是也不是每次 debug 后都能重復消費,我們都說如果一個 bug 能 100% 完全復現(xiàn),那基本上就解決一大半了。

所以我們排查的第一步就是完全復現(xiàn)這個問題。

為了排除掉是 IDEA 的問題(雖然極大概率不太可能)既然是 debug 的時候產(chǎn)生的問題,那其實轉(zhuǎn)換到代碼也就是 sleep 嘛,所以我們打算在消費邏輯里直接 sleep 一段時間看能否復現(xiàn)。

經(jīng)過測試,sleep 幾秒到幾十秒都無法復現(xiàn),最后索性 sleep 一分鐘,神奇的事情發(fā)生了,每次都成功復現(xiàn)!

既然能成功復現(xiàn)那就好說了,因為我自己的業(yè)務代碼也有使用到 Pulsar 的地方,為了方便調(diào)試就準備在自己的項目里再復現(xiàn)一次。

結(jié)果詭異的事情再次發(fā)生,我這里又不能復現(xiàn)了。

雖然這才是符合預期的,但這就沒法調(diào)了呀。

本著相信現(xiàn)代科學的前提,我們倆唯一的區(qū)別就是項目不一樣了,為此我對比了兩邊的代碼。

  @PulsarConsumer(
topic = xx,
clazz = Xx.class,
subscriptionType = SubscriptionType.Shared
)
public void consume(Data msg) {
log.info("consume msg:{}", msg.getOrderId());
Lock lock = redisLockRegistry.obtain(msg.getOrderId());
if (lock.tryLock()) {
try {
orderService.do(msg.getOrderId());
} catch (Exception e) {
log.error("consumer msg:{} err:", msg.toString(), e);
} finally {
lock.unlock();
}
}

}

結(jié)果不出所料,同事那邊的代碼加了鎖;一個基于 Redis 的分布式鎖,這時我一拍大腿不會是解鎖的時候超時了導致拋了異常吧。

為了驗證這個問題,在能復現(xiàn)的基礎上我在框架的 Pulsar 消費處打了斷點:

果然破案了,異常提示已經(jīng)非常清楚了:加鎖已經(jīng)過了超時時間。

進入異常后直接 negative 消息,同時異常也被吃掉了,所以之前沒有發(fā)現(xiàn)。

查閱了 RedisLockRegistry 的源碼,默認超時時間正好是一分鐘,所以之前我們 sleep 幾十秒也無法復現(xiàn)這個問題。

總結(jié)

事后我向同事了解了下為啥這里要加鎖,因為我看下來完全沒有加鎖的必要;結(jié)果他是因為從別人那里復制的代碼才加上的,壓根沒想那么多。

所以這事也能得出一些教訓:

  • ctrl C/V 雖然方便,但也得充分考慮自己的業(yè)務場景。
  • 使用一些第三方 API 時,需要充分了解其作用、參數(shù)。

網(wǎng)頁名稱:你知道嗎?Pulsar 也會重復消費?
轉(zhuǎn)載源于:http://www.dlmjj.cn/article/dhidsoe.html