如何把一個執行完好的Kafka搞崩
Kafka其實也只是一個JVM程序,要想把一個程序搞崩潰,相信大家的nice idea(騷操作)也不少。本文中只是用了一種很常見的方式來使得Kafka的程序崩潰,通過分析崩潰的原因來讓我們可以更合理的使用Kafka。
你可以試著在一臺普通的Linux機器上建立10000個分割槽的主題。比如下面示例中建立一個主題topic-bomb:

執行完成之後你可以檢查一下Kafka的程序是否還存在(比如通過jps命令或者ps -aux|grep kafka命令)。一般情況下,你會發現原本執行完好的Kafka服務已經崩潰。此時,你或許會想到,建立這麼多個分割槽,是不是記憶體不夠而引起的程序崩潰,我在啟動Kafka的時候將JVM堆設定的大一點是不是就可以解決了。其實不然,建立這點兒分割槽而引起的記憶體增加完全不足以讓Kafka畏懼。
想要知道真相,我們可以開啟Kafka的服務日誌檔案($KAFKA_HOME/logs/server.log)來一探究竟,你會發現服務日誌中出現大量的如下異常:

異常中最關鍵的資訊是:“Too many open flies”,這是一種常見的Linux系統錯誤,通常意味著檔案描述符不足,它一般會發生在建立執行緒、建立Socket、開啟檔案這些場景下。在Linux系統中的預設設定下,這個檔案描述符的個數不是很高,可以通過ulimit檢視:

ulimit是在系統允許的情況下,提供對特定shell可利用的資源的控制。(Provides control over the resources avaliable to the shell and to processes started by it, on systems that allow such control)
-H和-S選項設定指定資源的硬限制和軟限制。硬限制設定之後不能再新增,而軟限制則可以增加到硬限制規定的值。如果-H和-S選項都沒有指定,則軟限制和硬限制同時設定。限制值可以是指定資源的數值或者hard、soft、unlimited這些特殊值,其中hard代表當前硬限制, soft代表當前軟體限制, unlimited代表不限制。如果不指定限制值, 則列印指定資源的軟限制值, 除非指定了-H選項。硬限制是可以在任何時候任何程序中設定 但硬限制只能由超級使用者提起。軟限制是核心實際執行的限制,任何程序都可以將軟限制設定為任意小於等於對程序限制的硬限制的值
我們可以通過測試來驗證一下本案例中的Kafka崩潰是否是由於檔案描述符的限制而引起的。首先啟動Kafka叢集,叢集中有3個節點,配置一樣。挑選其中的一臺節點node1做具體分析,通過jps命令我們可以檢視到kafka的程序pid的值:

檢視當前Kafka程序所佔用的檔案描述符的個數(注意這個值並不是Kafka第一次啟動時就需要佔用的檔案描述符的個數,示例中的Kafka環境下已經存在了若干主題):

我們再新建一個只有一個分割槽的主題,並檢視Kafka程序所佔用的檔案描述符的個數:

可以看到增加了一個分割槽對應的也只增加了一個檔案描述符。
之前我們通過ulimit命令可以看到軟限制是1024,不妨我們就建立一個具有829(1024-195=829)個分割槽的主題:

可以看到Kafka程序此時佔用了1024個檔案描述符,並且執行完好。這時我們還可以聯想到硬限制4096這個關鍵數字,不妨我們再建立一個包含有3071(4096-1024=3072,這裡特定少建立1個分割槽)個分割槽的主題,示例如下:

Kafka程序依舊完好,檔案描述符佔用為4095,逼近最高值4096。最後我們再次建立一個只有一個分割槽的主題:

此時Kafka已經崩潰,檢視程序號時已沒有相關資訊。檢視Kafka中的日誌,還會發現報錯文章開頭的異常“java.io.IOException: Too many open files”,表明已到達上限。
如何避免這種異常情況?對於一個高併發高效能的應用來說,1024或者4096的檔案描述符限制未免太少,可以適當的調大這個引數。比如使用ulimit -n 65535命令將上限提高到65535,這樣足以應對大多數的應用情況,再高也完全沒有必要了。

也可以在/etc/security/limits.conf檔案中設定,參考如下:

limits.conf檔案修改之後需要重啟才能生效。limits.conf與ulimit的區別在於前者是針對所有使用者的,而且在任何shell都是生效的,即與shell無關,而後者只是針對特定使用者的當前shell的設定。在修改最大檔案開啟數時,最好使用limits.conf檔案來修改,通過這個檔案,可以定義使用者,資源型別,軟硬限制等。也可修改/etc/profile檔案加上ulimit的設定語句來是的全域性生效。
設定之後可以再次執行文中開頭的建立10000個分割槽的主題的命令,試一下,Kafka是否還會再次崩潰?
歡迎工作一到五年的Java工程師朋友們加入Java架構開發:744677563
群內提供免費的Java架構學習資料(裡面有高可用、高併發、高效能及分散式、Jvm效能調優、Spring原始碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!