不要被kafka的異步模式欺騙了

啥是異步模式

kafka的生產者可以選擇使用異步方式發送數據,所謂異步方式,就是我們調用 send() 方法,並指定一個回調函數, 服務器在返回響應時調用該函數。

kafka在客戶端裏暴露了兩個send方法,我們可以自己選擇同步或者異步模式。我們來看一個kafka的生產者發送示例,有個直觀的感受。這個示例是一個同步的模式。

ProducerRecord<String, String> record = new ProducerRecord<>(“Kafka”, “Kafka_Products”, “測試”);//Topic Key Value
try{
Future future = producer.send(record);
future.get();//獲取執行結果
} catch(Exception e) {
e.printStackTrace();
}

我們從源碼層面來繼續看下。

首先kafka定義了一個接口,

在這裏插入圖片描述

然後KafkaProducer實現了這兩個方法,我們看下異步方法的實現邏輯。

在這裏插入圖片描述

可以看到最終是調用doSend方法,調用的時候傳入一個回調。這個回調就是監聽方法的執行結果的。

異步模式也會阻塞的

很多人會認爲,既然是異步模式,不管結果是成功還是失敗,肯定方法調用會馬上返回的。那我只能告訴你,不好意思,不一定是這樣。我自己就曾經踩過這個坑。

我們當時有個業務流程需要在執行完成後發送kakfa消息給某個業務方,爲了儘量減少影響我這個主流程的執行時間,採用了異步方式發送kafka消息。在使用中,因爲配錯了kafka的TOPIC信息,發現流程阻塞發送消息這裏長達6秒(kafka默認的發送超時時間)。

究竟爲啥異步方式還會阻塞呢?我們繼續看源碼。

在這裏插入圖片描述
不管是同步模式還是異步模式,最終都會調用到doSend方法,注意看上圖中的waitOnMetadata方法,我上面說的阻塞的情況就是阻塞在這個方法裏。那我們繼續看這個方法。

在這裏插入圖片描述
通過代碼中的註釋我們大概能瞭解這個方法的功能,不過我這裏還是要解釋下。(防止有人看不懂英文,哈哈)

waitOnMetadata獲取當前的集羣元數據信息,如果緩存有,並且分區沒有超過指定分區範圍則緩存返回,否則觸發更新,等待新的metadata。這個等待的操作在下面這行代碼:

metadata.awaitUpdate(version, remainingWaitMs);

然後就繼續跟嘍,

在這裏插入圖片描述
這個方法很好理解,就是一直在等一個條件,這個條件達到了就返回,否則一直等待超時退出。而這個條件就是當前的版本號要大於上個版本號。

那麼誰來更新版本號呢?就是我們前面提到的sender線程。當我們的topic配置錯誤的時候導致metadata一直無法更新,然後一直等到超時。

破案了!

總結

kafka的異步模式可以讓我們在業務場景中發送消息時即刻返回,不必等待發送的結果。但是當metadata取不到時,發送的過程還是需要等待一直超時的。

程序員是一個尤其需要不斷學習的工種,平時養成閱讀源碼的習慣,不光能避免踩一些坑,還能在遇到問題是快遞定位到問題的根源。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章