iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0
Software Development

每天罵爆一隻 Kafka Pull Request系列 第 22

KAFKA-15859 Fixed the Unsupported version error when new admin connects to old broker


  • 分享至 

  • xImage
  •  

https://github.com/apache/kafka/pull/17358

背景故事

今天來聊聊Kafka序列化裡最重要的一件事情,版本相容性!如果你是這系列廢文的忠實讀者,應該會馬上覺得這個詞很熟悉,好像之前幾篇文章都提過版本和相容性等字眼,你的直覺沒錯,版本之間的相容性一直都是Kafka很在乎的事情,這是為了讓Kafka使用者可以避免升級時的痛苦,也可以讓Kafka維護者可以更勇敢努力放心的去升級。

那麼在序列化的過程我們是如何處理版本呢?首先在Kafka的序列化定義中可以指定這個資料支援哪些版本,這裏看一個例子:

"name": "TimeoutMs", "type": "int32", "versions": "10+", "ignorable": true

在上述的定義中,TimeoutMs這筆資料只支援10+的版本,換言之,這個欄位只有在10+以上才可以正常運作,否則就會 ... 就會 ... 就會怎樣呢?假如今天我們要把這個請求送給只支援版本9的對象,那麼該欄位的值究竟是要忽略還是拋出錯誤呢?當然這個問題並不是是否題,因為不同的情境可能會有不同的選擇,那麼什麼時候應該要拋出錯誤呢?例如這個欄位是用來取代版本9之前的舊欄位,那麼在產生資料的時候我們就會依照版本來產生對應的資料,而不是產生版本10也產生版本9的資料,這樣才不會有資源浪費,因此這個時候在序列化的過程我們就會採取拋出錯誤的手段,藉此有效防止我們產生了不正確的資料。至於另一種策略,也就是忽略不屬於該版本的資料就比較好理解了,例如該欄位是針對新的行為,那麼針對版本9的資料自然就不需要序列化該欄位,畢竟版本9也不知道該如何執行版本10的功能。

所以在上述的定義中,欄位ignorable就是用來選擇你是要拋出錯誤還是採取忽略的手法,大家可以看以下Kafka自動產生的序列化程式碼。

if (_version >= 10) {
    _writable.writeInt(timeoutMs);
}

這個例子可以看出在"ignorable": true的時候,序列化過程會直接忽略掉版本不匹配的資料,這樣做還可以節省傳輸的成本,畢竟如果對方根本不認識這個版本,那麼自然他也無法解析這個版本的資料。看到這裏可能會好奇那如果"ignorable": false會怎樣?可以看看下方的範例程式碼,在拋出錯誤的策略下,當資料的版本不匹配時,該欄位的值如果被改變了,也就是非預設值,此時就會拋出UnsupportedVersionException的例外來提醒我們這個版本無法接受此資料

if (_version >= 10) {
    _writable.writeInt(timeoutMs);
} else {
    if (this.timeoutMs != 0) {
        throw new UnsupportedVersionException("Attempted to write a non-default timeoutMs at version " + _version);
    }
}

背景故事閱讀到這邊,我們來回頭看看題目,這個題目在講什麼呢?它在講LIST_OFFSET這個請求在傳送給舊版本的時候會出問題,爲什麼呢?自然就是因為它採取了拋出錯誤的策略,同時在產生該請求時又沒有針對版本做特定資料的設定,所以當遇到舊版本的伺服器時,用了新版本的資料自然就會出現錯誤。

解決辦法

既然知道了我們有ignorable可以使用,同時也確定該欄位屬於新版本的行為,那麼正確的解法自然是採取忽略的策略,也就是把ignorable=true加上去,讓這個請求可以在面對舊版的時候自動忽略掉不匹配的資料。一行修復看似簡單,但背後的辛苦原理誰人知呢?

廣告

歡迎訂閱全臺最鬆散的開源社群源來適你,上面不定期會有各種開源的廢文。也歡迎參加全臺最鬆散的開源討論頻道,上面有一群網友一起在刷開源技術


上一篇
KAFKA-15908: Remove deprecated Consumer.poll(long timeout)
下一篇
KAFKA-17542 Use actions/labeler for automatic PR labeling
系列文
每天罵爆一隻 Kafka Pull Request30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言