https://github.com/apache/kafka/pull/17128
背景故事
相信每個 Kafka 的重度使用者都遇過 rolling upgrade的痛苦,也就是惡名昭彰的 double roll,第一次更新 binary、第二次更新 protocol,這兩次更新的過程很明顯的造成額外的時間,這在許多大型應用中造成很多麻煩。然而我們偉大的 Kafka 總不可能從沒思考過解決辦法吧?
當然不是!
在講述解法之前,我們先來看看為何需要第二次的更新,也就是為何需要更新 protocol?這個答案其實很好想像,為了不讓服務下線,在升級的過程中我們的叢集勢必處於龍蛇混雜的狀態,新舊軟體混合在一起,那就會出現一個問題:有的節點支援新的請求、有的不支援!因此 Kafka 為了有效處理這個不一致,在啟動服務的時候可以先喊這次的運行要基於哪個等級的 protocol,不管你這個節點的軟體多新多猛多屌,超過這個 protocol 的請求都不準處理!
所以這個「問題」其實不是問題,而是為了讓大家的叢集更安全更穩定!這也是為何這個現象雖然有些麻煩,但大家都可以共體時艱繼續愛護 Kafka。可是聰明的工程師馬上就想到,如果是為了讓叢集內每個節點都提供一樣的請求服務,那難道不能在上線後動態調整嗎?
沒錯,你想到的我們也想到了!所以 Kafka 已經建構了一套機制,可以用來在動態管理「整個叢集」的可用版本,換言之,使用者可以在叢集運行的過程隨時調整整個叢集能支援的「功能」,更棒的是以後升級只要弄好 binary,從此生活就可以幸福美滿了!
可惜每個美好的故事都有一個隱藏的哀傷,而這個哀傷就是在這完美機制的開發過程,我們不小心放了一個長達數年的 bugs …,這個致命的錯誤導致 Kafka 在數個路徑上會無法接受「未知的新功能」,包含:
如果大家仔細看一下,會發現啊幹這個 bugs 有夠嚴重的,幾乎是讓整個叢集都無法運作了!所以在多年後我們注意到後開始嘗試努力修復,最重要的是我們還必須確保舊版的 Kafka 一樣可以繼續運作 … 那該怎麼辦?
解決方式
其實經過上面一連串的描述,相信聰明的大家已經想到解決辦法了,那就是如果要溝通的對象是懷有這個嚴重bug,那我們就把未知的新功能從請求中移除,當然這樣的副作用就是該節點永遠不會知道到底有哪些尚未啟用的新功能 …
後續
這個題目從多個月前的 kafka 3.8 就已經開始討論,陸陸續續發現了更多需要解決的路徑,最後最後才選擇了這個雷霆手段,由此大家可以知道 Kafka 對於不同版本之間的相容性是相當在意,一切一切都是為了讓使用者可以有更好的體驗,尤其當你家的 Kafka 使用者是特別難搞的部門 …
廣告
歡迎訂閱全臺最鬆散的開源社群源來適你,上面不定期會有各種開源的廢文。也歡迎參加全臺最鬆散的開源討論頻道,上面有一群網友一起在刷開源技術