作者:石臻臻, CSDN博客之星Top5、Kafka Contributor 、nacos Contributor、华为云 MVP ,腾讯云TVP, 滴滴Kafka技术专家 、KnowStreaming。
KnowStreaming 是滴滴开源的Kafka运维管控平台, 有兴趣一起参与参与开发的同学,但是怕自己能力不够的同学,可以联系我,当你导师带你参与开源!。
1 Kafka监控
Kafka 使用 Yammer Metrics 在服务器中报告指标,Java 客户端使用 Kafka Metrics,这是一个内置的指标注册表. 两者都通过 JMX 公开指标
启用JMX并上报指标
Kafka 默认禁用远程 JMX,Kafka启动JMX方式
方式一:
JMX_PORT=端口号 nohup bin/kafka-server-start.sh config/server.properties &
在这里插入图片描述
方式二:
在启动脚本里面 对JMX_PORT 赋值,在kafka-server-start.sh
增加一句
export JMX_PORT="端口号"
在这里插入图片描述
然后再启动脚本,JMX就会自动开启了
方式三:在IDEA中启用JMX
如果你是在IDEA启动Kafka源码的形式开启JMX 那么你可以在启动的时候加入以下参数
-Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=端口 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
在这里插入图片描述
方式四:安全启用JMX
在生产场景中启用远程 JMX 时,您必须启用安全性,以确保未经授权的用户无法监视或控制您的代理或应用程序以及运行它们的平台.
更详细的请看:使用 JMX 技术进行监控和管理
查看JMX指标的方式
启动JMX之后, 我们在Zookeeper中的节点/brokers/ids/{brokerID}
数据中可以看到我们的端口是否注册成功。
{ "features": {}, "listener_security_protocol_map": { "PLAINTEXT": "PLAINTEXT" }, "endpoints": ["PLAINTEXT://localhost:9092"], "jmx_port": 9999, "port": 9092, "host": "localhost", "version": 5, "timestamp": "1659670870502" }
其中数据 jmx_port": 9999 就可以指定我们的JMX已经开启并且端口号是 9999
使用jconsole连接信息并打开
在按照JDK的时候,jconsole已经按照好了, 我们可以直接使用这个工具来可视化界面监控Java程序运行状况。
shizhenzhen@localhost % jconsole
在这里插入图片描述
这里可以连接本地的也可以是远程的,链接之后, 选择MBean就可以看到指标了
在这里插入图片描述
2 指标采集和统计机制
看 TODO
3 常见指标分析
指标的属性
Kafka中的指标有几百个,我们这边不可能把每一个指标都给分析一遍,这里我们从里面挑出来几个监控指标来分析分析
想要查看所有指标请跳转官网:Kafka监控
我们用jconsole连接上Broker之后, 可以看到所有的指标,如下图
在这里插入图片描述
如图所示有很多的指标,并且每个指标有很多的属性值
比如指标
kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec
表示的是这台Broker每秒写入的消息条数。
但是这个数据是如何统计的呢, 可以看看 图解Kafka中的数据采集和统计机制
一般情况下我们获取这个数据的话 是拿的 OneMinuteRate 一分钟内流入的平均速度。
kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec.OneMinuteRate
当然还有FiveMinuteRate 、FifteenMinuteRate
每个指标下面都会有很多属性,一般可能有以下几个
属性名 | 描述 |
RateUnit | 时间单位, 值固定为SECONDS 秒,它和EventType组成这个指标的单位,即messages/s |
EventType | 事件类型,对于MessagesIn来说,它的值是messages, 表示消息的个数,对于其他一些类型的指标来说可能会有所不同 |
Count | 消息流入的总数 |
MeanRate | 平均速率,自统计开始时候的平均 |
OneMinuteRate | 一分钟内流入的平均速率 |
FiveMinuteRate | 五分钟内流入的平均速率 |
FifteenMinuteRate | 十五分钟内流入的平均速率 |
那如果我还想知道在这台Broker上某个Topic的指标呢?
刚刚上面说的指标是流入这台Broker的消息数速率, 但是它的子目录下还有各个Topic的统计数据 指标名:kafka.server:type=BrokerTopicMetrics,name=BytesInPerSec,topic=P1_R1
常见重要指标
1. UnderReplicatedPartitions 失效副本分区数
指标:kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions
含义: 失效副本的分区数量, 代码逻辑为 统计该Broker上的Leader分区,并且该分区的副本数 - isr数量 > 0 的数量
异常值: 非0值
这个UnderReplicatedPartitions表示的是什么意思呢?我们直接看代码它是怎么统计的
ReplicaManager
通过代码所示, UnderReplicatedPartitions是Gauge类型,也就是说表示 瞬时数据, 会不停的把这个数据上报给JmxReport 那么主要的数值计算逻辑是:
leaderPartitionsIterator.count(_.isUnderReplicated) def isUnderReplicated: Boolean = isLeader && (assignmentState.replicationFactor - isrState.isr.size) > 0
代码逻辑:统计该Broker上的Leader分区,并且该分区的副本数 - isr数量 > 0 的数量
简单来说: UnderReplicatedPartitions值表示该Broker上的Leader分区存在有没有完全同步并跟上ISR的副本的 分区数量
问题分析
如果你这个指标出现了 , 说明该Broker上的Leader分区存在Follower副本跟不上ISR的情况。
这么个情况就是 副本为何掉出ISR 的问题了
PS:当我们在进行分区副本重分配的时候可能会出现这种情况,因为有可能新增了副本并且还没有跟上ISR.
1. 可能存在某个Broker宕机
在这里插入图片描述
看 KnowStreaming 的展示, Broker2存在5个UnderReplicatedPartitions, 通过左边可以看到刚好是Broker-0宕机了。
这种很容易就找到问题所在, 然后启动Broker恢复副本同步。
2. 可能副本所在磁盘故障/写满,导致副本离线
当磁盘出现故障时,会导致磁盘IO能力下降、集群吞吐下降、消息读写延时或日志目录offline等问题。
当磁盘写满时,相应磁盘上的Kafka日志目录会出现offline问题,此时,该磁盘上的分区副本不可读写,降低了分区的可用性与容错能力,同时由于leader迁移到其他Broker,增加了其他Broker的负载
我们可以通过指标 OfflineLogDirectoryCount来及时发现日志Offline的情况。
指标:kafka.log:type=LogManager,name=OfflineLogDirectoryCount
含义: 离线日志目录数量
异常值: 非0值
在这里插入图片描述
如果我们这个值是>0 的话,表示已经有目录处于离线中了, 具体是哪个处于离线中我们也可以通过指标来确定
指标:kafka.log:type=LogManager,name=LogDirectoryOffline,logDirectory="绝对路径地址"
含义: 该目录是否离线
异常值: 非0值, 0表示正常, 1表示离线
当然如果你想监控到具体的离线目录的话,你可以先把Broker上的所有目录绝对路径查询出来,然后再遍历一下这个指标就行了。
在这里插入图片描述
如果确定是目录离线了, 那么接下来就是让副本上线就行了, 如果磁盘满了可以考虑删除旧数据或更换磁盘,如果磁盘坏了那就换磁盘吧。
3. 性能问题,导致副本来不及同步数据
首先我们先了解一下Kafka的 ISR的伸缩机制
一般会有两种情况导致副本失效
- Follower副本进程卡住,在一段时间内根本没有向Leader发起同步请求,比如频繁的Full GC.
- Follower副本进程同步过慢, 在一段时间内都无法追赶上Leader副本,比如I/O开销过大。
出现1的情况可能性不是那么大,你可以通过查看kafka的gc日志kafkaServer-gc.log
来确定是否存在频繁的Full GC
其他情况呢, 我们可以先检查一下是否有一些异常日志出现, 看看具体的异常是什么
Error sending fetch request {} to node {} Failed to connect within $socketTimeout ms"
因为ISR伸缩的时候,在更新HW的时候需要加一个leaderIsrUpdateLock写锁, 这个时候消息的发送、客户端的读取等等都会发生锁竞争,并发度会下降。
解决问题的方案
我们可以尝试的调大replica.lag.time.max.ms
,2.5之前默认值是10s, 后面是30s.
也可以调大num.replica.fetchers
的值,这个值表示的是:Broker去读取消息的Fetcher线程数,增加这个值可以增加follow broker中的I/O并行度。默认是1