如何把一个运行完好的Kafka搞崩溃
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。
歡迎跳轉到本文的原文鏈接:https://honeypps.com/mq/how-do-you-crash-a-well-functioning-kafka-instance/
Kafka其實也只是一個JVM進程,要想把一個進程搞崩潰,相信大家的nice idea(騷操作)也不少。本文中只是用了一種很常見的方式來使得Kafka的進程崩潰,通過分析崩潰的原因來讓我們可以更合理的使用Kafka。
你可以試著在一臺普通的Linux機器上創建10000個分區的主題。比如下面示例中創建一個主題topic-bomb:
[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic topic-bomb --replication-factor 1 --partitions 10000 Created topic "topic-bomb".執行完成之后你可以檢查一下Kafka的進程是否還存在(比如通過jps命令或者ps -aux|grep kafka命令)。一般情況下,你會發現原本運行完好的Kafka服務已經崩潰。此時,你或許會想到,創建這么多個分區,是不是內存不夠而引起的進程崩潰,我在啟動Kafka的時候將JVM堆設置的大一點是不是就可以解決了。其實不然,創建這點兒分區而引起的內存增加完全不足以讓Kafka畏懼。
想要知道真相,我們可以打開Kafka的服務日志文件($KAFKA_HOME/logs/server.log)來一探究竟,你會發現服務日志中出現大量的如下異常:
[2018-09-13 00:36:40,019] ERROR Error while creating log for topic-bomb-xxx in dir /tmp/kafka-logs (kafka.server.LogDirFailureChannel) java.io.IOException: Too many open filesat java.io.UnixFileSystem.createFileExclusively(Native Method)at java.io.File.createNewFile(File.java:1012)at kafka.log.AbstractIndex.<init>(AbstractIndex.scala:54)at kafka.log.OffsetIndex.<init>(OffsetIndex.scala:53)at kafka.log.LogSegment$.open(LogSegment.scala:634)at kafka.log.Log.loadSegments(Log.scala:503)at kafka.log.Log.<init>(Log.scala:237)異常中最關鍵的信息是:“Too many open flies”,這是一種常見的Linux系統錯誤,通常意味著文件描述符不足,它一般會發生在創建線程、創建Socket、打開文件這些場景下。在Linux系統中的默認設置下,這個文件描述符的個數不是很高,可以通過ulimit查看:
[root@node1 kafka_2.11-2.0.0]# ulimit -n 1024 [root@node1 kafka_2.11-2.0.0]# ulimit -Sn 1024 [root@node1 kafka_2.11-2.0.0]# ulimit -Hn 4096ulimit是在系統允許的情況下,提供對特定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的值:
[root@node1 kafka_2.11-2.0.0]# jps -l 31796 kafka.Kafka查看當前Kafka進程所占用的文件描述符的個數(注意這個值并不是Kafka第一次啟動時就需要占用的文件描述符的個數,示例中的Kafka環境下已經存在了若干主題):
[root@node1 kafka_2.11-2.0.0]# ls /proc/31796/fd | wc -l 194我們再新建一個只有一個分區的主題,并查看Kafka進程所占用的文件描述符的個數:
[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic topic-bomb-1 --replication-factor 1 --partitions 1 Created topic "topic-bomb-1". [root@node1 kafka_2.11-2.0.0]# ls /proc/31796/fd | wc -l 195可以看到增加了一個分區對應的也只增加了一個文件描述符。
之前我們通過ulimit命令可以看到軟限制是1024,不妨我們就創建一個具有829(1024-195=829)個分區的主題:
可以看到Kafka進程此時占用了1024個文件描述符,并且運行完好。這時我們還可以聯想到硬限制4096這個關鍵數字,不妨我們再創建一個包含有3071(4096-1024=3072,這里特定少創建1個分區)個分區的主題,示例如下:
[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic topic-bomb-3 --replication-factor 1 --partitions 3071 Created topic "topic-bomb-3". [root@node1 kafka_2.11-2.0.0]# ls /proc/31796/fd | wc -l 4095Kafka進程依舊完好,文件描述符占用為4095,逼近最高值4096。最后我們再次創建一個只有一個分區的主題:
[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic topic-bomb-4 --replication-factor 1 --partitions 1 Created topic "topic-bomb-4". [root@node1 kafka_2.11-2.0.0]# ls /proc/31796/fd | wc -l ls: cannot access /proc/31796/fd: No such file or directory 0此時Kafka已經崩潰,查看進程號時已沒有相關信息。查看Kafka中的日志,還會發現報錯文章開頭的異常“java.io.IOException: Too many open files”,表明已到達上限。
如何避免這種異常情況?對于一個高并發高性能的應用來說,1024或者4096的文件描述符限制未免太少,可以適當的調大這個參數。比如使用ulimit -n 65535命令將上限提高到65535,這樣足以應對大多數的應用情況,再高也完全沒有必要了。
[root@node1 kafka_2.11-2.0.0]# ulimit -n 65535 #可以再次查看一下相應的軟硬限制數 [root@node1 kafka_2.11-2.0.0]# ulimit -Hn 65535 [root@node1 kafka_2.11-2.0.0]# ulimit -Sn 65535也可以在/etc/security/limits.conf文件中設置,參考如下:
#nofile - max number of open file descriptors root soft nofile 65535 root hard nofile 65535limits.conf文件修改之后需要重啟才能生效。limits.conf與ulimit的區別在于前者是針對所有用戶的,而且在任何shell都是生效的,即與shell無關,而后者只是針對特定用戶的當前shell的設定。在修改最大文件打開數時,最好使用limits.conf文件來修改,通過這個文件,可以定義用戶,資源類型,軟硬限制等。也可修改/etc/profile文件加上ulimit的設置語句來是的全局生效。
設置之后可以再次執行文中開頭的創建10000個分區的主題的命令,試一下,Kafka是否還會再次崩潰?歡迎在下方留言區留下你的探索-
歡迎跳轉到本文的原文鏈接:https://honeypps.com/mq/how-do-you-crash-a-well-functioning-kafka-instance/
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。
總結
以上是生活随笔為你收集整理的如何把一个运行完好的Kafka搞崩溃的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Kafka与Spark集成系列四]
- 下一篇: sun.misc.Unsafe操作手册