Apache Kafka-21-kafka monitor 监控
kafka 监控
Kafka应用程序包含了大量的度量指标,以至于很多人搞不清楚哪些是重要的,哪些可以置之不理。
它们所涉及的范围,从简单的流量速率度量指标到各种请求类型的时间度量指标,既有主题级别的,也有分区级别的。
这些度量指标为broker的每一种行为提供了详细的信息,不过它们也成为了Kafka系统监控者的“噩梦”。
这一章将详细介绍一些常用的关键性度量指标,以及如何根据这些指标采取相应的行动,也会介绍一些用于调试问题的度量指标。
不过,这不是一个完整的度量指标清单。度量指标清单会经常发生变化,而且很多度量指标只对有经验的Kafka开发人员有参考价值。
度量指标基础
在介绍Kafkabroker和客户端的度量指标之前,先来讨论有关监控Java应用程序的基础知识,以及有关监控和告警的最佳实践。
学完本章知识,读者将会对应用程序的监控有一个基本的了解,同时能明白度量指标的重要性。
度量指标在哪里
Kafka提供的所有度量指标都可以通过 Java Management Extensions(JMX)接口来访问。
要在外部监控系统里使用这些度量指标,最简单的方式是将负责收集度量指标的代理(agent)连接到Kafka上。
代理作为一个单独的进程运行在监控系统里,并连接到Kafka的JMX接口上,例如使用NagiosXIcheck_jmx插件或jmxtrans来连接JMX接口;也可以直接在Kafka进程里运行一个JMX代理,然后通过HTTP连接访问度量指标,比如 Jolokia 或 MX4J.
本章将不会深人讨论如何设置监控代理,每一种代理都有多种使用方式。
如果所在的组织没有监控Java应用程序的经验,那么可以考虑使用第三方的监控服务。
如果采用了这种方式,那就需要从服务供应商那里购买监控服务,由他们提供监控代理、度量指标收集点、存储、图形化和告警。
服务供应商可以搭建监控代理,并提供后续的服务支持。
找到JMX端口
broker将JMX端口作为整个broker配置信息的一部分保存在Zookeeper上。
所以,如果要通过编程的方式访问Kafka的JMX,比如管理工具需要在没有端口配置的情况下连接到JMX,那么可以从Zookeeper上获取端口信息。
/brokers/ids/
节点包含了JSON格式的broker信息,里面有JMX对应的主机名(hostnane)和端口(jnx_port)。
内部或外部度量
JMX接口提供的是内部度量指标,它们由被监控的应用程序生成。
对于很多内部度量来说(比如各个请求阶段的时间),使用内部度量指标是最好的选择。没有什么能比应用程序更加了解自己了。
还有一些度量指标,比如请求的整体时间、某种请求类型的可用性,可以在应用程序外部进行度量。
也就是说,这些度量指标是由客户端或其他第三方应用(对于我们来说就是指Kafkabroker)提供的。
另外也有一些度量指标,比如可用性(broker是否可达)或延迟(请求需要的时间)。这些度量指标为被监控的应用程序提供了很有用的外部视图。
网站健康监控就是我们所熟知的一种外部度量。
一个正常运行的Web服务器能够正常处理请求,它向监控系统发送度量指标,一切看起来都很好。
不过,Web服务器本身的防火墙或服务器所处网络的防火墙可能导致客户端无法连接到服务器上。负责检查网站可访问性的外部监控系统将会检测到这个问题,并发送告警。
应用程序健康检测
不管通过哪一种方式从Kafka收集监控信息,都要确保能够通过简单的健康检测来监控应用程序本身的健康状况,这可以通过两种方式来实现。
(1)使用外部进程来报告broker的运行状态(健康检测)。
(2)在broker停止发送度量指标时发出告警(也叫作stale度量指标)。
虽然第二种方式也是可行的,但有时候很难区分是broker出现了问题还是监控系统本身出现了问题。
如果监控的是broker,可以直接连接到它的外部端口(就是客户端连接到broker所使用的端口),看看是否可以得到响应。
如果监控的是Kafka客户端,就会比较复杂,需要检查进程是否处于运行状态,或者通过内部提供的方法来确定应用程序的健康状况。
度量指标的覆盖面
Kafka提供了很多度量指标,如何选择合适的度量指标非常关键,特别是在基于这些度量
指标定义告警的时候。
太多难以确定严重程度的告警很容易让人们陷人“告警疲劳”,我们难以为每一个度量指标定义恰当的阂值并保持更新,告警的可信度也会因此而下降。
一些大覆盖面的告警用处更大。也就是说,这类告警会告诉我们某处出现了问题,然后我们去收集更多的信息,以便确定问题的细节。
想象一下汽车的“检查引擎”告警灯,如果仪表盘上有100个不同的指示器,比如空气过滤器、油箱、排气管等,那么就会让人感到很困惑。
相反,如果用一个指示器就能告诉我们汽车出现了问题,然后我们再去找出问题的其他细节,事情就会变得简单很多,这一章将介绍具有大覆盖面的度量指标,它们可以让告警变得更简单。
broker 的度量指标
broker提供了很多度量指标,它们大部分都是底层的度量,由Kafka开发者出于诊断或调试的目的而增加,也有为预测将来需要的信息而添加,另外还有由Kafka用户请求添加,以供日常操作所需。
这些度量指标提供的信息几乎涵盖了broker的每一项功能。它们很容易造成信息过载,不过也有一些度量指标为Kafka的日常运行提供了必要的信息。
示例:谁来看着watcher
很多组织使用Kafka收集应用程序和系统的度量指标与日志,然后供中心监控系统使用,这样可以很好地解耦应用程序和监控系统。
不过,对于Kafka本身来说却存在一个问题,如果使用这个监控系统来监控Kafka,那么当Kafka崩清时,我们很可能无法感知到,因为监控系统的数据流也随着消失了。
有一些办法可以解决这个问题。一种方法是使用一个单独的监控系统来監控Kafka,这个系统不依赖Kafka提供的数据。另一种方法是,如果有多个数据中心,可以将数据中心A的Kafka集群度量指标生成到数据中心B的Kafka集群上,反之亦然。不管怎样,要确保Kafka的监控和告警不依赖Kafka本身。
本节将从讨论非同步分区度量指标开始,介绍如何根据这些度量指标采取行动,然后讨论其他的度量指标,以便对broker的度量指标有一个全面的认识。这里不会列出broker的所有度量指标,但会列出那些在监控broker和集群时必须用到的部分。在介绍客户端度量指标之前,还会针对日志展开详细的讨论。
非同步分区
如果说broker只有一个可监控的度量指标,那么它一定是指非同步分区的数量。该度量指明了作为首领的broker有多少个分区处于非同步状态。这个度量可以反映Kafka的很多内部问题,从broker的崩溃到资源的过度消耗。因为这个度量指标可以说明很多问题,所以当它的值大于零时,就应该想办法采取相应的行动。本章稍后会介绍更多用于诊断这类问题的度量指标。
表10-1列出了非同步分区度量指标的详细信息。
- 表10-1:度量指标和对应的非同步分区
度量指标名称 | Under-replicated partitions |
---|---|
JMX MBean | kafka.server:type=RepltcaManager ,nane=UnderRepltcatedParttttonis |
值区间 | 非负整数 |
如果集群里多个broker的非同步分区数量一直保持不变,那说明集群中的某个broker已经离线了。
整个集群的非同步分区数量等于离线broker的分区数量,而且离线broker不会生成任何度量指标。
这个时候,需要检查这个broker出了什么问题,并解决问题。
通常有可能是硬件问题,也有可能是操作系统问题或者Java问题,导致进程出现中断或挂起。
默认的副本选举
在诊断问题之前,尝试过运行默认的副本选举(参见第9章)吗?broker在释放首领角色(发生崩渍或被关闭)之后不会自动恢复首领角色(除非启用了首领自动再均衡,不过不建议启用这个功能)。
也就是说,集群里的首领副本很容易出现不均衡。运行默认的副本选举是很容易的,也很安全,所以在出现这类问题时,建议先重新选举首领,看看能否解决问题。
如果非同步分区的数量是波动的,或者虽然数量稳定但并没有broker离线,说明集群出现了性能问题。
这类问题繁复多样,难以诊断,不过可以通过一些步骤来缩小问题的范围。
第一步,先确认问题是与单个broker有关还是与整个集群有关。不过有时候这个也难有定论。如果非同步分区属于单个broker,那么这个broker就是问题的根源,表象是其他broker无法从它那里复制消息。
如果多个broker都出现了非同步分区,那么有可能是集群的问题,也有可能是单个broker的问题。
这时候有可能是因为一个broker无法从其他broker那里复制数据。为了找出这个broker,可以列出集群的所有非同步分区,并检查它们的共性。
使用kafka-topics.sh工具(第9章已详细介绍过)可以获取非同步分区清单。
- 示例:列出集群的非同步分区。
# kafka-topics.sh --zookeeper zoo1.example.com:2181/kafka-cluster --describe --under-replicated
Topic: topicOne Partition: 5 Leader: 1 Replicas: 1,2 Isr: 1
Topic: topicOne Partition: 6 Leader: 3 Replicas: 2,3 Isr: 3
Topic: topicTwo Partition: 3 Leader: 4Replicas: 2,4 Isr: 4
Topic: toptcTwo Partition: Leader: 5 Repltcas: 5,2 Isr: 5
Topic: toptcStx Partition: 1 Leader: 3 Replicas: 2,3 Isr: 3
Topic: toptcSixPartition: :2Leader: Replicas: 1,2 Isr: 1
Topic: toptcSix Partttton: 5 Leader: 6 Repltcas: 2,6 Isr: 6
Toptc: toptcSix Partttton: Leader: Replicas: 7,2 Isr: 7
Topic: toptcNine Partttton: 1 Leader: Replicas: 1,2 Isr: 1
Topic: topicNine Partttion: 3 Leader: 3 Replicas: 2,3 Isr: 3
Toptc: topicNine Partttton: 4 Leader: 3 Replicas: 3,2 Isr: 3
Topic: topicNine Partition: 7 Leader: 3 Replicas: 2,3 Isr: 3
Topic: topicNine Partition: B leader: Replicas: 2,3 Isr: 3
Topic: topicNine Partition: 5 Leader: 6 Replicas: 6,2 Isr: 6
在这个示例中,broker2出现在所有的副本清单里,但没有出现在所有的同步副本(ISR)清单里,所以要将注意力放在这个broker上。
如果没有发现这样的broker,那么问题有可能出在整个集群上。
1.集群级别的问题
集群问题一般分为以下两类。
不均衡的负载。
资源过度消耗。
分区或首领的不均衡问题虽然解决起来有点复杂,但问题的定位是很容易的。为了诊断这个问题,需要用到broker的以下度量指标。
分区的数量。
首领分区的数量。
主题流入字节速率。
主题流入消息速率。
检查指标。在一个均衡的集群里,这些度量指标的数值在整个集群范围内是均等的,如表10-2所示。
- 表10-2:资源使用情况度量指标
Broker | 分区 | 首领 | 流入字节 | 流出字节 |
---|---|---|---|---|
1 | 100 | 50 | 3.56 MB/s | 9.45 MB/s |
2 | 101 | 49 | 3.66 MB/s | 9.25 MB/s |
3 | 100 | 50 | 3.23 MB/s | 9.82 MB/s |
也就是说,所有的broker几乎处理相同的流量。
假设在运行了默认的副本选举之后,这些度量指标出现了很大的偏差,那说明集群的流量出现了不均衡。
要解决这个问题,需要将负载较重的broker分区移动到负载较轻的broker上。
这可以使用第9章介绍的kafka-reassign-partitions.sh 工具来实现。
实现集群负载均衡的辅助工具
broker本身无法在整个集群里实现自动的分区重分配。
也就是说,Kafka集群的流量均衡是一个十分费劲的过程,需要手动检查一大串度量指标,然后进行均衡的副本重分配。
为了解决这个问题,有一些组织开发了自动化工具来帮助完成这个任务。
例如,LinkedIn发布了一个叫作kafka-assigner的工具,可以在GitHub的开源代码仓库kafka-tools里找到。
Kafka提供的企业支持服务也包含了这一功能。
Kafka集群的另一个性能问题是容量瓶颈。
有很多潜在的瓶颈会拖慢整个系统:CPU、磁盘IO和网络吞吐量是其中最为常见的。磁盘的使用并不在其列,因为当磁盘被填满时,broker会在进行适当的操作之后直接崩渍。
系统指标
为了诊断容量问题,可以对如下一些操作系统级别的度量指标进行监控。
CPU使用。
网络输人吞吐量。
网络输出吞吐量。
磁盘平均等待时间。
磁盘使用百分比。
上述任何一种资源出现过度消耗,都会表现为分区的不同步。
要记住,broker的复制过程使用的也是Kafka客户端。
如果集群的数据复制出现了问题,那么集群的用户在生产消息或读取消息时也会出现问题。
所以,有必要为这些度量指标定义一个基线,并设定相应的阂值,以便在容量告急之前定位问题。随着集群流量的增长,对这些度量指标的趋势走向进行检查也是很有必要的。其中,AllTopicsBytesInRate最适合用于显示集群的使用情况。
主机级别的问题
如果性能问题不是出现在整个集群上,而是出现在一两个broker里,那么就要检查broker所在的主机,看看是什么导致它与集群里的其他broker不一样。
主机级别的问题可以分为以下几类。
硬件问题。
进程冲突。
本地配置的不一致。
典型的服务器和典型的问题
当一个服务器及其操作系统承载了数千个组件时,会变得很复杂,任何一个组件都可能出现问题,导致整体的崩溃或者部分的性能衰退。
本书不可能覆盖到所有的内容,关于这个话题的书已经有很多了,而且这种局面还会一直持续下去。
不过,本书可以讨论一些最为常见的问题,这一小节将着重讨论运行Linux操作系统的服务器。
硬件问题很容易被发现,因为服务器会直接停止工作。
不过,引起性能衰退的硬件问题却不那么明显。当出现这类问题时,系统仍旧保持运行,但会降低行为能力。
比如内存出现了坏点,系统检测到坏点,直接跳过这个片段(可用的内存因此减少了)。
类似的问题也会发生在CPU上,对于这类问题,可以使用硬件提供的工具来监控硬件的健康状况,比如智能平台管理接口(IPMI)。出现问题时,可以通过dresg查看输出到系统控制台的内核缓冲区日志。
能够导致Kafka性能衰退的一个比较常见的硬件问题是磁盘故障。
Kafka使用磁盘来存储消息,生产者的性能与磁盘的写人速度有直接关系。这里出现的任何偏差都会表现为生产者和复制消息者的性能问题,而后者会导致分区的不同步,因此,应该持续地监控磁盘,并在出现问题时马上进行修复。
一粒老鼠屎
一个broker的磁盘问题可能会影响到整个集群的性能。因为生产者客户端会\连接到所有的broker上,如果操作得当,这些broker的分区几平能够均等地分布在整个集群里。
如果一个broker性能出现衰退并拖慢了处理请求的速度,就会导致生产者的回压,从而拖慢发给所有broker的请求。
假设你正在通过IPMI或其他硬件管理接口来监控磁盘的状态,与此同时,在操作系统上运行了 SMART (Self-Monitoring, Analysis and Reporting Technology,自行监控、分析和报告技术)工具来监控和测试磁盘。
在故障即将发生时,它会发出告警。
除此之外,还要注意查看磁盘控制器,不管是否使用了RAID硬件都要注意查看。很多磁盘控制器都有板载的缓存,这个缓存只在控制器和电池备份单元(BBU)正常工作时才会被使用。如果BBU发生故障,缓存就会被禁用,磁盘的性能就会衰退。
在网络方面,局部的故障也会带来很大的问题。有些问题是硬件引起的,比如糟糕的光缆或连接器。有些问题是配置不当造成的,比如更改了服务器或上游网络硬件的网络连接速度和双工设置。
网络配置问题还有可能出现在操作系统上,比如网络缓冲区太小,或者太多的网络连接占用了大量的系统内存。在这方面,网络接口的错误数量是一个最为关键的指标。如果这个数字一直在增长,说明网络连接出现了问题。
如果硬件没有问题,那么需要注意系统里的其他应用程序,它们也会消耗系统的资源,而且有可能会给Kafka带来压力。它们有可能是没有被正常安装的软件,或者一个非正常运行的进程,比如监控代理进程。对于这种情况,可以使用top工具来识别那些大量消耗CPU或内存的进程。
如果经过上述的检查还是找不出主机的问题根源,那么有可能是broker或者系统配置不一致造成的。
一个服务器上运行着多个应用程序,每个应用程序有多个配置选项,要找出它们的差别真是一项艰巨的任务,这就是为什么要使用配置管理工具(如Chef或Puppet)来维护操作系统和应用程序(包括Kafka)的配置一致性。
broker 度量指标
除了非同步分区数量外,还有其他很多broker级别的度量指标需要监控。
虽然不一定会为所有的度量指标设定告警阈值,但它们的确提供了关于broker和集群的有价值的信息。它们都应该出现在监控仪表盘上。
1. 活跃控制器数量
该指标表示broker是否就是当前的集群控制器,其值可以是0或1。
如果是1,表示broker就是当前的控制器。
任何时候,都应该只有一个broker是控制器,而且这个broker必须一直是集群控制器。
如果出现了两个控制器,说明有一个本该退出的控制器线程被阻塞了,这会导致管理任务无法正常执行,比如移动分区。
为了解决这个问题,需要将这两个broker重启,而且不能通过正常的方式重启,因为此时它们无法被正常关闭。
表10-3给出了活跃控制器数量度量指标的详细信息。
- 表10-3:活跃控制器数量度量指标
度量指标名称 | Active contraller count |
---|---|
JMX MBean | kafka.controller:type=KafkaController,nane=ActiveControllerCount |
值区间 | 0或1 |
如果集群里没有控制器,集群就无法对状态的变更作出恰当的响应,状态的变更包括主题或分区的创建和broker故障。
这时候要注意检查为什么控制器线程没有正常运行,比如,Zookeeper集群的网络分区就会造成这样的问题。解决底层的问题之后,重启集群里的所有broker,重置控制器线程的状态。2.请求处理器空闲率Kafka使用了两个线程池来处理客户端的请求:网络处理器线程池和请求处理器线程池。网络处理器线程池负责通过网络读人和写出数据。这里没有太多的工作要做,也就是说,不用太过担心这些线程会出现问题。请求处理器线程池负责处理来自客户端的请求,包括从磁盘读取消息和往磁盘写人消息。因此,broker负载的增长对这个线程池有很大的影响。表10-4给出了请求处理器空闲率度量指标的详细信息。
- 表10-4:请求处理器空闲率
度量指标名称 | Request handler average idle percentage |
---|---|
JMX MBean | kafka.server:type=KafkaRequestHandlerPool,nane=RequestHandlerAvgIdlePercent |
值区间 | 从0到1的浮点数(包括1在内) |
智能地使用线程
这样看来,好像需要数百个请求处理器线程,但实际上,请求处理器线程数没必要超过CPU的核数。
Kafka在使用请求处理器时是非常智能的,它会分流需要很长时间来处理的请求。
例如,当请求的配额被限定或每个生产请求需要多个确认时,Kafka就会使用这个功能。
请求处理器平均空闲百分比这个度量指标表示请求处理器空闲时间的百分比。
数值越低,说明broker的负载越高。经验表明,如果空闲百分比低于20%,说明存在潜在的问题,如果低于10%,说明出现了性能问题。除了集群的规模太小之外,还有其他两个原因会增大这个线程池的使用量。
首先,线程池里没有足够的线程。一般来说,请求处理器线程的数量应该与系统的处理器核数一样(包括多线程处理器)。
另一个常见的原因是线程做了不该做的事。
在Kafka0.10之前,请求处理器线程负责解压传人的消息批次、验证消息、分配偏移量,并在写人磁盘之前重新压缩消息。
糟糕的是,压缩方法使用了同步锁。Kafka0.10版本引入了一种新的格式,偏移量可以直接附加在消息批次里。
也就是说,生产者在发送消息批次之前可以设置相对的偏移量,这样broker就可以避免解压缩和重新压缩。
如果使用了支持0.10版本消息格式的生产者和消费者客户端,并且把broker的消息格式也升级到了0.10版本,可以发现性能有了显著的改进。
这样可以降低对请求处理器线程的消耗。
主题流入字节
主题流入字节速率使用b/s来表示,在对broker接收的生产者客户端消息流量进行度量时,这个度量指标很有用。
该指标可以用于确定何时该对集群进行扩展或开展其他与规模增长相关的工作。
它也可以用于评估一个broker是否比集群里的其他broker接收了更多的流量,如果出现了这种情况,就需要对分区进行再均衡。
表10-5给出了详细信息。
- 表10-5:主题流入字节度量指标
度量指标名称 | Bytes in per second |
---|---|
JMX MBean | kafka.server:type=BrokerToptcMetrtcs,nane=BytesInPerSec |
值区间 | 速率为双精度浮点数,计数为整数 |
因为这是第一个速率度量指标,所以有必要对它的属性进行简短的描述。
所有的速率指标都提供了7个属性,使用哪些属性完全取决于实际的需求。
它们可能是具体的数字,也有可能是基于某些时间段的平均值。如果没能恰当地使用这些指标,就无法看到broker真实的状况。
属性值
前两个属性与度量无关,但有助于更好地理解相应的度量指标。
- EventType
这是度量的单位,在这里是“字节”。
- RateUnit
这是速率的时间段,在这里是“秒“。
这两个属性表明,速率是通过b/s来表示的,不管它的值是基于多长的时间段算出的平均值。速率还有其他4个不同粒度的属性。
- OneMinuteRate
前1分钟的平均值。
- FiveMinuteRate
前5分钟的平均值。
- FifteenMinuteRate
前15分钟的平均值。
- MeanRate
从broker启动到目前为止的平均值。
OneMinuteRate波动很快,它提供了“时间点”粒度的度量,适用于查看短期的流量走势,HeanRate一般不会有太大变化,它提供的是整体的流量走势。
虽然有一定的用途,但一般不需要对它设置告警。
FiveMinuteRate和FifteenMinuteRate提供了中间粒度的度量。
除了速率属性外,速率指标还有一个Count属性,会在broker启动之后保持增长。
对于这个指标来说,Count代表了从broker启动以来接收到流量的字节总数。
将该属性用在一个支持计数度量指标的监控系统里,就可以提供度量的完整视图,而不仅仅是平均速率。
主题流出字节
主题流出字节速率与流入字节速率类似,是另一个与规模增长有关的度量指标。流出字节速率显示的是消费者从broker读取消息的速串。
流出速率与流人速率的伸缩方式是不一样的,这要归功于Kafka对多消费者客户端的支持。
很多Kafka的流出速率可以达到流入速率的6倍!所以,单独对流出速率进行观察和走势分析是非常重要的。
表10-6给出了详细信息。
- 表10-6;主题流出字节度量指标
度量指标名称 | Byesoutpersecond |
---|---|
JMX MBean | kafka.server:type=BrokerTopicMetrtcs,name=BytesOutPerSec |
值区间 | 速率为双精度浮点数,计数为整数 |
把复制消费者包括在内
流出速率也包括副本流量,也就是说,如果所有主题都设置了复制系数2,那么在没有消费者客户端的情况下,流出速率与流入速率是一样的。
如果有一个消费者客户端从集群读取所有的消息,那么流出速率会是流人速率的2倍。
如果不知道这一点,光是看着这些指标就会感到很疑惑。
主题流入的消息
之前介绍的字节速率以字节的方式来表示broker的流量,而消息速率则以每秒生成消息个数的方式来表示流量,而且不考虑消息的大小。
这也是一个很有用的生产者流量增长规模度量指标。
它也可以与字节速率一起用于计算消息的平均大小。与字节速率一样,该指标也能反映集群的不均衡情况,表10-7给出了详细信息。
- 表10-7:主题流入消息度量指标
度量指标名称 | Message in per second |
---|---|
JMX MBean | kafka.server:type=BrokerToptcMetrtcs,nane=MessagesInPerSec |
值区间 | 速率为双精度浮点数,计数为整数 |
为什么没有消息的流出速率
经常会有人问,为什么没有broker的“流出消息”度量指标?
因为在消息被读取时,broker将整个消息批次发送给消费者,并没有展开批次,也就不会去计算每个批次包含了多少个消息,所以,broker也就不知道发送了多少个消息。
broker为此提供了一个度量指标叫作每秒获取次数,它指的是请求速率,而不是消息个数。
分区数量
broker的分区数量一般不会经常发生改变,它是指分配给broker的分区总数。
它包括broker的每一个分区副本,不管是首领还是跟随者。
如果一个集群启用了自动创建主题的功能,那么监控这个度量指标会变得很有意思,因为你会发现,这样可以让主题的创建游离于控制之外。
表10-8给出了详细信息。
- 表10-8:分区数量度量指标
度量指标名称 | Partition count |
---|---|
JMX MBean | kafka.server:type=RepltcaManager,nane=PartittonCount |
值区间 | 非负整数 |
首领数量
该度量指标表示broker拥有的首领分区数量。
与broker的其他度量一样,该度量指标也应该在整个集群的broker上保持均等。
我们需要对该指标进行周期性地检查,并适时地发出告警,即使在副本的数量和大小看起来都很完美的时候,它仍然能够显示出集群的不均衡问题。因为broker有可能出于各种原因释放掉一个分区的首领身份,比如Zookeeper会话过期,而在会话恢复之后,这个分区并不会自动拿回首领身份(除非启用了自动首领再均衡功能)。
在这些情况下,该度量指标会显示较少的首领分区数,或者直接显示为零。
这个时候需要运行一个默认的副本选举,重新均衡集群的首领。表10-9给出了详细信息。
- 表10-9:首领数量度量指标
度量指标名称 | Leader count |
---|---|
JMX MBean | kafka.server:type=RepltcaManager,name=LeaderCount |
值区间 | 非负整数 |
可以使用该指标与分区数量一起计算出broker首领分区的百分比。
一个均衡的集群,如果它的复制系数为2,那么所有的broker都应该差不多是它们的50%分区的首领。
如果复制系数是3,这个百分比应该降到33%。
离线分区
与非同步分区数量一样,离线分区数量也是一个关键的度量指标(表10-10)。该度量只能由集群控制器提供(对于其他broker来说,该指标的值为零),它显示了集群里没有首领的分区数量。
发生这种情况主要有两个原因。
(1)包含分区副本的所有broker都关闭了.
(2)由于消息数量不匹配,没有同步副本能够拿到首领身份(并且禁用了不完全首领选举)
- 表10-10:离线分区数量度量指标
度量指标名称 | Offline partiions count: |
---|---|
JMX MBean | kafka.controller:type=KafkaController,nane=offlinePartttonsCount |
值区间 | 非负整数 |
在一个生产环境Kafka集群里,离线分区会影响生产者客户端,导致消息丢失,或者造成回压。
这属于“站点宕机”问题,需要立即解决。
请求度量指标
第5章描述了Kafka协议,它有多种不同的请求,每种请求都有相应的度量指标。
以下的请求类型都有相应的度量指标。
ApiVersions
ControlledShutdown
CreateTopics
DeleteTopics
DescribeGroups
Fetch
FetchConsuner
FetchFollower
GroupCoordtnator
Heartbeat
JoinGroup
LeaderAndIsr
LeaveGroup
ListGroups
Metadata
OffsetComntt
OffsetFetch
offsets
Produce
SaslHandshake
StopReplica
SyncGroup
UpdateMetadata
每一种请求类型都有8个度量指标,它们分别体现了不同请求处理阶段的细节。
例如,Fetch请求有如表10-11所示的度量指标。
- 表10-11:请求度量指标
名字 | JMX MBean |
---|---|
Total Time | kafka.network:type=RequestMetrtcs, nane=TotalTineMs,request=Fetch |
Request Queue Time | kafka.network:type=RequestMetrics,nane=RequestQueueTimeMs,request=Fetch |
Local Time | kafka.network:type=RequestMe'5 ,nane=LocalTineMs, request=Fetch |
Remote Time | kafka.network: type=RequestMetrics,nane=RemoteTineMs, request=Fetch |
Throttle Time | kafka.network:type=RequestMetrics,name=ThrottleTineMs,request*Fetch |
Response Queue Time | kafka.network:type=RequestMetrtcs,nane=ResponseQueueTineMs,request=Fetch |
Response Send Time | kafka.network:type=RequestMetrics, name=ResponseSendTineMs,request=Fetch |
Requests Per Sccond | kafka.network:type=RequestMetrics, nane=RequestsPerSec, request=Fetch |
RequestPerSecond是一个速率指标,前面已经介绍过它的属性,这些属性显示了在单位时间内收到并处理的请求个数。
该度量提供了每种请求类型的频度,尽管很多请求类型都不是很频繁发生,比如StopReplica和UpdateHetadata,
表10-11中的7个time指标分别为请求提供了一组百分比数值以及一个离散的Count属性,类似于速率度量指标。
这些指标都是自broker启动以来开始计算的,所以在查看那些长时间没有变化的度量指标时,请记住:broker代理运行的时间越长,数据就越稳定。
请求处理部分
它们所代表的请求处理的部分如下。
- Total Time
表示broker花在处理请求上的时间,从收到请求开始计算,直到将响应返回给请求者。
- Request Queue Time
表示请求停留在队列里的时间,从收到请求开始计算,直到开始处理请求。
- Local Time
表示首领分区花在处理请求上的时间,包括把消息写人磁盘(但不一定要冲刷),
- Remote Time
表示在请求处理完毕之前,用于等待跟随者的时间。
- Throttle Time
表示暂时搁置响应的时间,以便拖慢请求者,把它们限定在客户端的配额范围内。
- Response Queue Time
表示响应被发送给请求者之前停留在队列里的时间。
- Response Send Time
表示实际用于发送响应的时间。
属性
每个度量指标的属性如下。
- 百分位
50thPercentile, 75thPercenttle, 95thPercentile, 98thPercentile, 99thPercenttle, 999thPercenttle,
- Count
从broker启动至今处理的请求数量。
- Min
所有请求的最小值。
- Max
所有请求的最大值。
- Mean
所有请求的平均值。
- StdDev
整体的请求时间标准偏差
什么是百分位?
百分位是一种常见的时间度量方式,尽管它们容易被人误解。
一个99百分位度量表示,整组取样(这里指请求时间)里有99%的值小于度量指标的值,也就是说,有1%的值大于指标的值,一般情况下需要查看平均值为99%或99.9%的数值,这样就可以分辨出哪些是平均的请求,哪些是异样的请求。
在这些指标和属性中,哪些对于监控来说是比较重要的?我们至少要收集TotalTime和RequestsPerSecond的平均值及较高的百分位(99%或99.9%),这样就可以获知发送请求的整体性能。
如果有可能,尽量为每一种请求类型收集其他6种时间度量指标,这样就可以将性能问题细分到请求的各个阶段。
为时间度量指标设定告警阈值有一定的难度。例如,fetch请求时间受各种因素的影响,包括客户端等待消息的时间、主题的繁忙程度,以及客户端和broker之间的网络连接速度。
不过,对于Produce请求来说,可以为TotalTime设定99.9%百分位度量基线值。
与非同步分区类似,Produce请求的99.9%百分位数值快速增长说明出现了大规模的性能问题。
主题和分区的度量指标
broker的度量指标描述了broker的一般行为,除此之外,还有很多主题实例和分区实例的度量指标。
在大型的集群里,这样的度量指标会有很多,一般情况下,不太可能将它们全部收集到一个度量指标系统里。不过,我们可以用它们来调试与客户端相关的问题。
例如,主题的度量指标可以用于识别出造成集群流量大量增长的主题。我们需要提供这些度量指标,这样Kafka的生产者和消费者就可以使用它们。不管是否会收集这些度量指标,都有必要知道它们的用处。
表10-12中所列的度量指标将使用主题名称“TOPICNAME”,分区ID为0。在实际中,要把主题名称和分区ID替换成自己的名称和ID。
1. 主题实例的度量指标
主题实例的度量指标与之前描述的broker度量指标非常相似。事实上,它们之间唯一的区别在于这里指定了主题名称,也就是说,这些度量指标属于某个指定的主题。主题实例的度量指标数量取决于集群主题的数量,而且用户极有可能不会监控这些度量指标或设置告警。
它们一般提供给客户端使用,客户端依此评估它们对Kafka的使用情况,并进行问题调试。
- 表10-12:主题实例的度量指标
名字 | JMX MBean |
---|---|
Bytes in rale | kafka.server:type=BrokerToptcMetrtcs,name=BytesInPerSec, toptc=TOPICNAME |
Bytes out rate | kafka.server:type=BrokerToptcMetrics,nane=BytesOutPerSec,topi.c=TOPICNAME |
Failed fetch rate | kafka.server:type=BrokerTopicMetrtcs,nane=FailedFetchRequestsPerSec,toptc=TOPICNAME |
Failed producc rate | kafka.server:type=BrokerToptcMetrics, nane=FatledProduceRequestsPerSec,topic=TOPICNAME |
Messages in rale | kafka.server:type=BrokerTopicMetrics,nane=MessagesInPerSec, toptc=TOPICNAME |
Fetch request rate | kafka.server:type=BrokerToptcMetrics,nane=TotalFetchRequestsPerSec,topic=TOPICNAME |
Produce request rate | kafka. server:type-BrokerToptcMetr tcs, naveTotaLProduceRequestsPerSec, toptcTOPICNANE |
2. 分区实例的度量指标
分区实例的度量指标不如主题实例的度量指标那样有用。
另外,它们的数量会更加庞大,因为几百个主题就可能包含数千个分区。
不过不管怎样,在某些情况下,它们还是有一定用处的。
Partitionsize度量指标表示分区当前在磁盘上保留的数据量(见表10-13)。
如果把它们组合在一起,就可以表示单个主题保留的数据量,作为客户端配额的依据。
同一个主题的两个不同分区之间的数据量如果存在差异,说明消息并没有按照生产消息的键进行均匀分布。
Logsegmentcount指标表示保存在磁盘上的日志片段的文件数量,可以与Partitionsize指标结合起来,用于跟踪资源的使用情况。
- 表10-13:分区实例的度量指标
名称 | JMX MBean |
---|---|
Partition size | kafka.log:type=Log,nane=Size,toptc=TOPICNAME,partttton= |
Log segment count | kafka.lLog:type=Log,name=NunLogSegments,topic=TOPICNAME,partition=B |
Log end offset | kafka. Log:type=Log,name=LogEndOffset,toptc=TOPICNAME,partition=B |
Log start offet | kafka.log:type=Log,name=LogStartOffset,topic=TOPICNAME,partition*e |
Log end offset和 Log start offset 这两个度量指标分别表示消息的最大偏移量和最小偏移量。
不过需要注意的是,不能用这两个指标来推算分区的消息数量,因为日志压缩会导致偏移量“丢失”,比如包含相同键的新消息会覆盖掉旧消息。
不过它们在某些情况下还是很有用的,比如在进行时间戳和偏移量映射时,就可以得到更精确的映射,消费者客户端因此可以很容易地回滚到与某个时间点相对应的偏移量(尽管可能没有Kafka0.10.1里引人的基于时间的索引搜索那么重要)。
非同步分区度量指标
在分区实例的度量指标中,有一个指标用于表示分区是否处于非同步状态。
一般情况下,该指标对于日常的运维起不到太大作用,因为这类指标太多了。
可以直接监控broker的非同步分区数量,然后使用命令行工具(参见第9章)确定哪些分区处于非同步状态。
Java虚拟机监控
除了broker的度量指标外,还应该对服务器提供的一些标准度量进行监控,包括Java虚拟机(JVM)。
如果JVM频繁发生垃圾回收,就会影响broker的性能,在这种情况下,就应该得到告警。
JVM的度量指标还能告诉我们为什么broker下游的度量指标会发生变化。
1.垃圾回收
对于JVM来说,最需要监控的是垃圾回收(GC)的状态。
需要监控哪些MBean取决于具体的Java运行时(JRE)和垃圾回收器的设置。
如果JRE使用了OracleJava1.8,并使用了G1垃圾回收器,那么需要监控的MBean如表10-14所示。
- 表10-14:G1垃圾回收器度量指标
名称 | JMX MBean |
---|---|
Full GC cycles | java.lang:type=GarbageCollector,name=G1 Old Generation |
Yong GC cycles | java.lang:type=GarbageCollector,name=G1 Young Generatton |
在垃圾回收语义里,Old和Full的意思是一样的。
我们需要监控这两个指标的CollectionCount和CollectionTine属性。CollectionCount表示从JVM启动开始算起的垃圾回收次数,CollectionTine表示从JVM启动开始算起的垃圾回收时间,以ms为单位。
因为这些属性是计数器,所以它们可以告诉我们发生GC的次数和花费在GC上的时间,还可以用于计算平均每次GC花费的时间,不过在通常的运维中,这样做并没有多大用处。
这些指标还有一个LastGcInfo属性。这是一个由5个字段组成的组合值,用于提供最后一次GC的信息。
其中最重要的一个值是duration值,它以ms为单位,展示最后一次GC花费的时间。其他几个值(GcThreadCount、id,startTine和endTine)虽然也会提供一些信息,但用处不大。
不过要注意的是,我们无法通过该属性查看到每一次GC的信息,因为年轻代GC发生得很频繁。
2.Java操作系统监控
JVM 通过 java.langtype=OperatingSysten 提供了一些操作系统的信息。
不过这些指标的信息量很有限,并不能告知操作系统的完整状况。
这些指标有两个比较有用但在操作系统里难以收集到的属性—— MaxFileDescriptorCount
和 OpenFileDescriptorCount
。
MaxFileDescrtptorCount展示JVM能够打开的文件描述符(FD)数量的最大值,OpenFileDescriptorCount展示目前已经打开的文件描述符数量。
每个日志片段和网络连接都会打开一个文件描述符,所以它们的数量增长得很快。
如果网络连接不能被正常关闭,那么broker很快就会把文件描述符用完。
操作系统监控
JVM并不能告诉用户所有与操作系统有关的信息,因此,用户不仅要收集broker的度量指标,也需要收集操作系统的度量指标。大多数监控系统都会提供代理,用于收集更多有关操作系统的信息。
用户需要监控CPU的使用、内存的使用、磁盘的使用、磁盘IO和网络的使用情况。
在CPU方面,需要监控平均系统负载。系统负载是一个独立的数值,它展示处理器的相对使用情况。
另外,根据类型来捕捉CPU的使用百分比也是很有用的。根据收集方法和操作系统的不同,可以使用如下列出的CPU百分比数值(使用了缩写),既可以使用其中的一部分,也可以使用全部。
属性 | 说明 |
---|---|
us | 用户空间使用的时间。 |
sy | 内核空间使用的时间, |
ni | 低优先级进程使用的时间。 |
td | 空闲时间。 |
wa | 磁盘等待时间。 |
hi | 处理硬件中断的时间。 |
si | 处理软件中断的时间。 |
st | 等待管理程序的时间。 |
什么是系统负载
尽管很多人都知道系统负载是对CPU使用情况的度量,但他们并不知道度量是如何进行的。平均负载是指等待处理器执行的线程数。
在Linux系统里,它还包括处于不可中断睡眠状态的线程,比如磁盘等待。
负载使用3个数值来表示,分别是前1分钟的平均值,前5分钟的平均值和前15分钟的平均值。在单CPU系统里,数值1表示系统负载达到了100%,此时总会存在一个等待执行的线程。而在多CPU系统里,如果负载达到100%,那么负载的数值与CPU的核数相等。例如,如果系统里有24个处理器,那么负载100%表示负载数值为24。
对于broker来说,跟踪CPU的使用情况是很有必要的,因为它们在处理请求时使用了大量的CPU时间。而内存使用情况的跟踪就显得没有那么重要了,因为运行Kafka并不需要太大的内存。
它会使用堆外的一小部分内存来实现压缩功能,其余大部分内存则用于缓存。不过,我们还是要对内存使用情况进行跟踪,确保其他的应用不会影响到broker。可以通过监控总内存空间和可用交换内存空间来确保内存交换空间不会被占用。
对于Kafka来说,磁盘是最重要的子系统。
所有的消息都保存在磁盘上,所以Kafka的性能严重依赖磁盘的性能。我们需要对磁盘空间和索引节点进行监控,确保磁盘空间不会被用光。对于保存数据的分区来说就更是如此。对磁盘IO进行监控也是很有必要的,它们揭示了磁盘的运行效率。我们需要监控磁盘的每秒种读写速度、读写平均队列大小、平均等待时间和磁盘的使用百分比。
最后,还需要监控broker的网络使用情况。简单地说,就是指流入和流出的网络流量,一般使用b/s来表示。
要记住,在没有消费者时,1个流人比特对应1个或多个流出比特,这个数字与主题的复制系数相等。根据消费者的实际数量,流人流量很容易比输出流量高出一个数量级。在设置告警阈值时要切记这一点。
日志
在讨论监控时,如果不涉及日志,那么这个监控就是不完整的。
与其他应用程序一样,Kafka的broker也可以被配置成定期向磁盘写人日志。
为了能够从日志里获得有用的信息,选择合适的日志和日志级别是很重要的。通过记录INFO级别的日志,可以捕捉到很多有关broker运行状态的重要信息。为了获得一系列清晰的日志文件,很有必要对日志进行分类。
可以考虑使用两种日志。
第一种是kafka.controller,可以将它设置为INFO级别。这个日志用于记录集群控制器的信息。在任何时候,集群里都只有一个控制器,因此只有一个broker会使用这个日志。日志里包含了主题的创建和修改操作、broker状态的变更,以及集群的活动,比如默认的副本选举和分区的移动。
另一个日志是kafka.server.ClientQuotaManager,也可以将它设置为INFO级别。这个日志用于记录与生产和消费配额活动相关的信息。因为这些信息很有用,所以最好不要把它们记录在broker的主日志文件里。
在调试问题时,还有一些日志也很有用,比如kafka.request.Logger,可以将它设置为DEBUG或TRACE级别。这个日志包含了发送给broker的每一个请求的详细信息。如果日志级别被设置为DEBUG,那么它将包含连接端点、请求时间和概要信息。如果日志级别被设置为TRACE,那么它将包含主题和分区的信息,以及除消息体之外的所有与请求相关的信息。不管被设置成什么级别,这个日志会产生大量的数据,所以如果不是出于调试的目的,不建议启用这个日志。
日志压缩线程的运行状态也是一个有用的信息。
不过,这些线程并没有单独的度量指标,一个分区的压缩失败有可能造成压缩线程的整体崩溃,而且是悄然发生的。
启用 kafka.log.LogCleaner, kafka.log.Cleaner 和 kafka.log.LogCleanerManager 这些日志, 并把他们的级别设置为DEBUG级别,就可以输出日志压缩线程的运行状态。这些日志包含了每个被压缩分区的大小和消息个数。
一般情况下,这些日志的数量不会很大。也就是说,默认启用这些日志并不会带来什么麻烦。
客户端监控
所有的应用程序都需要监控,包括那些使用了Kafka客户端的应用程序。不管是生产者还是消费者,它们都有特定的度量指标需要监控。
本节将主要介绍如何监控官方的Java客户端,其他第三方的客户端应该也有自己的度量指标。
生产者度量指标
新版本Kafka生产者客户端的度量指标经过调整变得更加简洁,只用了少量的MBean。
相反,之前版本的客户端(不再受支持的版本)使用了大量的MBean,而且度量指标包含了大量的细节(提供了大量的百分位和各种移动平均数)。这些度量指标提供了很大的覆盖面,但这样会让跟踪异常情况变得更加困难。
生产者度量指标的MBean名字里都包含了生产者的客户端ID。在下面的示例里,客户端ID使用CLIENTID表示,brokerID使用BROKERID表示,主题的名字使用TOPICNAME表示,如表10-15所示。
- 表10-15:Kafka生产者度量指标MBean
名称 | JMX MBean |
---|---|
Overall producer | kafka.producer : type=producer-netrics,client-td=CLIENTID |
Per-broker | kafka.producer:type=producer-node-netrtcs,client-td=CLIENTID, node-td=node-BROKERID |
Per-topic | kafka.producer:type=producer-toptc-netrics,client-td=CLIENTID, topic=TOPICNAME |
上表中列出的每一个MBean都有多个属性用于描述生产者的状态。
下面列出了用处最大的几个属性。
在继续了解这些属性之前,建议先通过阅读第3章了解生产者的工作原理。
1.生产者整体度量指标
生产者整体度量指标提供的属性描述了生产者各个方面的信息,从消息批次的大小到内存缓冲区的使用情况。虽然这些度量在调试的时候很有用,不过在实际应用中只会用到少数的几个,而在这几个度量里,也只有一部分需要进行监控和告警,下面将讨论一些平均数度量指标(以-avg结尾),它们都有相应的最大值(以-nax结尾),不过这些最大值的用处很有限。
record-error-rate是一个完全有必要对其设置告警的属性。这个指标的值一般情况下都是零,如果它的值比零大,说明生产者正在丢弃无法发送的消息。生产者配置了重试次数和回退策略,如果重试次数达到了上限,消息(记录)就会被丢弃。我们可以跟踪另外一个属性record-retry-rate,不过该属性不如record-error-rate那么重要,因为重试是很正常的行为。
我们可以对request-Latency-avg设置告警,它表示发送一个生产者请求到broker所需要的平均时间。在运维过程中,应该为该指标建立一个基线,并设定告警阈值。
请求延迟的增加说明生产者请求正在变慢。有可能是网络出现了问题,也有可能是broker出现了问题。不管是哪一种情况,都会导致生产者端发生回压,并引发应用程序的其他问题。
除了这些关键性的度量指标外,如果能够知道生产者发送的消息流量就更好了。
有3个属性提供了3个不同的视图:outgoing-byte-rate表示每秒钟消息的字节数,record-send-rate表示每秒钟消息的数量,request-rate表示每秒钟生产者发送给broker的请求数。单个请求可以包含一个或多个批次,单个批次可以包含一个或多个消息,每个消息由多个字节组成。把这些指标显示在仪表盘上,可以跟踪到生产者是如何使用Kafka的。
为什么不使用 ProducerRequestMetrics
ProducerRequestMetricsMBean提供了请求延迟的百分位和请求速率的移动平均数,但为什么不建议使用呢?
问题在于,这个度量指标是为每个生产者线程提供的。
如果应用程序出于性能方面的考虑,使用了多个生产者线程,那么就很难对这些指标进行聚合。
所以,使用生产者整体指标所提供的属性是一种更为有效的方式,
可以借助一些度量指标来更好地理解字节、记录、请求和批次之间的关系,这些指标描述了这些实体的大小。
request-size-avg表示生产者发送请求的平均字节数,batch-size-avg表示单个消息批次(根据定义,批次包含了属于同一个分区的多个消息)的平均字节数,record-size-avg表示单个消息的平均字节数。
对于单主题的生产者来说,它们提供了有关生产消息的有用信息。而对于多主题的生产者来说,比如MirrorMaker,它们提供的信息就不是很有用。
除了这3个指标外,还有另外一个指标records-per-request-avg,它表示在生产者的单个请求里所包含的消息平均个数。
最后一个值得推荐的指标是record-queue-tine-avg,它表示消息在发送给Kafka之前在生产者客户端等待的平均毫秒数。
应用程序在使用生产者客户端发送消息(调用send方法)之后,生产者会一直等待,直到以下任一情况发生。
生产者客户端有足够多的消息来填充批次(根据max.partition.bytes的配置)。
距离上一次发送批次已经有足够长的时间(根据Linger.ms的配置)。
这两种情况都会促使生产者客户端关闭当前批次,然后把它发送给broker。对于繁忙的主题来说,一般会发生第一种情况,而对于比较慢的主题来说,一般会发生第二种情况。record-queue-tine-avg用于度量生产消息所使用的时间,因此,可以通过调优上述两个参数来满足应用程序的延迟需求。
2. Per-broker和Per-topic度量指标
除了生产者整体的度量指标外,还有一些MBean为每个broker连接和每个主题提供了有限的属性集合。
在调试问题时,这些度量会很有用,但不建议对它们进行常规的监控。这些MBean属性的命名与整体度量指标的命名是一样的,所表示的含义也是一样的(只不过它们是作用在特定的broker或特定的主题上)。
在broker实例的度量指标里,request-Latency-avg是比较有用的一个,因为它一般比较稳定(在消息批次比较稳定的情况下),而且能够显示broker的连接问题。
其他的属性,比如 outgoing-byte-rate 和 request-Latency-avg, 他们会因为 broker 所包含的分区不同而有所不同。
也就是说,这些度量会随着时间发生变化,完全取决于集群的状态。
主题实例的度量指标比broker实例的度量指标要有趣得多,不过只有在使用多主题的生产者时,它们才能派上用场。当然,也只有在生产者不会消费过多主题的情况下,才有必要对这些指标进行常规的监控。
例如,MirrorMaker有可能会向成百上千的主题生成消息。我们无法逐个检查这些指标,也几乎不可能为它们设置合理的告警阈值。与broker实例的度量指标一样,主题实例的度量指标一般用于诊断问题。
例如,可以通过record-send-rate和record-error-rate这两个属性将丢弃的消息隔离到特定的主题上。另外,byte-rate表示主题整体的每秒消息字节数。
消费者度量指标
与新版本的生产者客户端类似,新版本的消费者客户端将大量的度量指标属性塞进了少数的几个MBean里,如表10-6所示。
消费者客户端也作出了权衡,去掉了延迟百分位和速率移动平均数。因为消费者读取消息的逻辑比生产者发送消息的逻辑复杂,所以消费者的度量指标也会更多。
具体请参考表10-16。
- 表10-16:Kafka消费者度量指标MBean
名称 | JMX MBean |
---|---|
Overall consumer | kafka.consuner:type=consuner-netrics,client-td=CLIENTID |
Fetch manager | kafka.consuner:type=consuner-fetch-nanager-netrics,client-td=CLIENTID |
Per-topic | kafka.consuner:type=consuner-fetch-nanager-netrics,client-td=CLIENTID, toptc=TOPICNAME |
Per-broker | kafka.consuner:type=consuner-node-netrics,cltent-td=CLIENTID,node-td=node-BROKERID |
Coordinator | kafka.consuner:type=consuner-ccord!nator-netrics,client-id-CLIENTID |
1. FetchManager度量指标
在消费者客户端,消费者整体度量指标MBean的用处不是很大,因为有用的指标都聚集在FetchManagerMBean里。
消费者MBean包含了与网络底层运行情况有关的指标,而FetchManagerMBean则包含了与字节、请求和消息速率有关的指标。与生产者客户端不同的是,用户可以查看消费者所提供的度量指标,但对它们设置告警是没有意义的。
对于FetchManager来说,fetch-Latency-avg可能是一个需要对其进行监控和设置告警的指标。
与生产者的request-latency-avg类似,该指标表示从消费者向broker发送请求所需要的时间。
请求的延迟通过消费者的fetch.min.bytes和fetch.max.wait.ms这两个参数进行控制。一个缓慢的主题会出现不稳定的延迟,有时候broker响应很快(有可用消息的时候),有时候甚至无法在fetch.nax.wait.ns规定的时间内完成响应(没有可用消息的时候)。如果主题有相对稳定和足够的消息流量,那么查看这个指标或许会更有意义。
为什么不用延时(Lag)
我们建议对所有消费者的延时情况进行监控,但为什么不建议对FetchManager的records-lag-max属性进行监控呢?该属性表示落后最多的分区的延时情况(落后broker的消息数量)。
这里有两方面的原因:一方面是因为它只显示了单个分区的延时,另一方面是因为它依赖消费者的某些特定功能。
如果没有其他的选择,那么可以考虑将该属性作为度量延时的指标,并为其设置告警。
不过,最佳实践应该是使用外部的延时监控,稍后会介绍更多的内容。
要想知道消费者客户端处理了多少消息流量,可以使用bytes-consuned-rate或records-consured-rate,或者同时使用它们两个。
它们分别表示客户端每秒读取的消息字节数和每秒读取的消息个数。有些人为它们设置了最小值告警阂值,当消费者工作负载不足时,他们就会收到告警。不过需要注意的是,消费者和生产者之间是没有耦合的,因此不能从消费者端去推测生产者端的行为模式。
FetchManager也提供了一些度量指标,有助于理解字节、消息和请求之间的关系。
fetch-rate表示消费者每秒发出请求的数量,fetch-size-avg表示这些请求的平均字节数,records-per-request-avg表示每个请求的平均消息个数。
要注意的是,消费者并没有提供与生产者相对应的record-size-avg,所以无法知道消息的平均大小。
如果这个很重要,那么可以参考其他指标,或者在应用程序接收到消息之后计算出消息的平均大小。
2.Per-broker和Per-topic度量指标
与生产者客户端类似,消费者客户端也为每个broker连接和每个主题提供了很多度量指标,它们可以用于诊断问题,但不建议对它们进行常规的监控。
与FetchManager一样,broker的request-latency-avg属性用处也很有限,它取决于主题的消息流量。
incoming.byte-rate和request-rate分别表示broker每秒读取的消息字节数和每秒请求数。它们可以用于诊断消费者与broker之间的连接问题。
在读取多个主题时,消费者客户端所提供的主题实例的度量指标会很有用。
如果只是读取单个主题,那么这些指标就与FetchManager的指标一样,没有必要去收集它们。
但如果客户端读取了大量的主题,比如MirrorMaker,那么查看这些指标就会变得很困难。如果打算收集这些指标,可以考虑收集最重要的3个:bytes-consuned-rate、records-consuned-rate 和 fetch-size-avg.
bytes-consuned-rate 表示每秒读取的消息字节数,records-consuned-rate 表示每秒读取的消息个数,fetch-size-avg表示每个请求的消息平均字节数。
3.Coordinator度量指标
正如第4章所述,消费者客户端以群组的方式运行。群组里会发生一些需要协调的活动,比如新成员的加人或者向broker发送心跳来保持群组的成员关系。消费者协调器负责处理这些协调工作,作为消费者客户端的组成部分,它也维护着自己的一组度量指标。与其他度量指标一样,Coordinator度量指标也提供了很多数字,但是其中只有关键的一小部分需要进行常规的监控。
消费者群组在进行同步时,可能会造成消费者的停顿。当群组里的消费者在协商哪些分区应该由哪些消费者来读取时,就会发生这种情况。停顿的时间长短取决于分区的数量。协调器提供了sync-tine-avg属性,用于表示同步活动所使用的平均毫秒数。sync-rate属性也很有用,表示每秒钟群组发生的同步次数。对于一个稳定的消费者群组来说,这个数字在多数时候都是零。
消费者需要通过提交偏移量来作为读取进度的检查点,消费者可以基于固定时间间隔自动提交偏移量,也可以通过应用程序代码手动提交偏移量。
提交偏移量也是一种生成消息的请求(不过它们有自己的请求类型),提交的偏移量就是消息,并被生成到一个特定的主题上。协调器提供了comnit-Latency-avg属性,表示提交偏移量所需要的平均时间。与生产者里的请求延时一样,我们也需要监控该指标,为它设定一个预期的基线,并设置合理的告警阈值。
Coordinator度量指标的最后一个属性是asstgned-partitions,表示分配给消费者客户端(群组里的单个实例)的分区数量。该属性之所以有用,是因为可以通过在整个群组内比较各个实例的值,从而知道群组的负载是否均衡。我们可以使用该属性来识别因协调器的分区分配算法所导致的负载不均衡问题。
配额
Kafka可以对客户端的请求进行限流,防止客户端拖垮整个集群。
对于消费者和生产者客户端来说,这都是可配的,可以使用每秒钟允许单个客户端访问单个broker的流量字节数来表示。
它有一个broker级别的默认值,客户端可以对其进行覆盖。当broker发现客户端的流量已经超出配额时,它就会暂缓向客户端返回响应,等待足够长的时间,直到客户端流量降到配额以下。
broker并不会在响应消息里提供客户端被限流的错误码,也就是说,对于应用程序来说,如果不监控这些指标,可能就不知道发生了限流。
需要监控的指标如表10-17所示。
- 表10-17:需要监控的度量指标
客户端 | MBean |
---|---|
消费者 | kafka.consuner:type=consumer-fetch-nanager-netrics,client-td=CLIENTID 的属性 fetch-throttle-tine-avg |
生产者 | kafka.producer:type=producer-metrics,client-id=CLIENTID 的属性 produce-throttle-tine-avg |
默认情况下,broker不会开启配额功能。不过不管有没有使用配额,监控这些指标总是没有问题的。
况且,它们有可能在未来某个时刻被启用,而且从一开始就监控它们要比在后期添加更加容易。
延时监控
对于消费者来说,最需要被监控的指标是消费者的延时。
它表示分区最后一个消息和消费者最后读取的消息之间相差的消息个数。
在之前的小节里已经说过,在这里,使用外部监控要比使用客户端自己的监控好得多。
虽然消费者提供了延时指标,但该指标存在一个间题,它只表示单个分区的延时,也就是具有最大延时的那个分区,所以它不能准确地表示消费者的延时。另外,它需要消费者做一些额外的操作,因为该指标是由消费者对每个发出的请求进行计算得出的。如果消费者发生崩溃或者离线,那么该指标要么不准确,要么不可用。
监控消费者延时最好的办法是使用外部进程,它能够观察broker的分区状态,跟踪最近消息的偏移量,也能观察消费者的状态,跟踪消费者提交的最新偏移量。
这种方式提供了一种持续更新的客观视图,而且不依赖消费者的状态。我们需要在每一个分区上进行这种检查。对于大型消费者来说,比如MirrorMaker,可能意味着要监控成千上万个分区。
第9章介绍过如何使用命令行工具获取消费者群组的信息,包括提交的偏移量和延时。如果直接监控由工具提供的延时信息,会存在一些问题。
首先,需要为每个分区定义合理的延时。每小时接收100个消息的主题和每秒钟接收10万个消息的主题,它们的阈值是不一样的。
其次,必须能够将延时指标导人到监控系统,并为它们设置告警。如果有一个消费者群组读取了1500个主题,这些主题的分区数量超过了10万个,那将是一项令人望而生畏的任务。
可以使用Burrow来完成这项工作,Burrow是一个开源的应用程序,最初由LinkedIn开发。
它收集集群消费者群组的信息,并为每个群组计算出一个单独的状态,告诉我们群组是否运行正常、是否落后、速度是否变慢或者是否已经停止工作,以此来完成对消费者状态的监控。
它不需要通过监控群组的进度来获得阈值,不过用户仍然可以从中获得消息的延时数量。LinkedIn工程博客上记录了有关Burrow工作原理的讨论。
Burrow可以用于监控集群所有的消费者,也可以用于监控多个集群,而且可以很容易被集成到现有的监控和告警系统里。
如果没有其他选择,消费者客户端的records-lag-max指标提供了有关消费者状态的部分视图,不过,仍然强烈建议使用像Burrow这样的外部监控系统。
端到端监控
我们推荐使用的另一种外部监控系统是端到端的监控系统,它为Kafka集群的健康状态提供了一种客户端视图。
消费者和生产者客户端有一些度量指标能够说明集群可能出现了问题,但这里有猜想的成分,因为延时的增加有可能是由客户端、网络或Kafka本身引起的。另外,用户原本的工作可能只是管理Kafka集群,但现在也需要监控客户端。现在只需要回答以下两个简单的问题。
可以向Kafka集群生成消息吗?
可以从Kafka集群读取消息吗?
理想情况下,用户可能会希望每一个主题都允许这些操作,但要为此向每一个主题注入人为的流量是不合理的。
所以,可以考虑是否每个broker都允许这些操作,而这正是KafkaMonitor要做的事情。
该工具由LinkedIn的Kafka团队开发并开源,它持续地向一个横跨集群所有broker的主题生成消息,并读取这些消息。
它对每个broker的生产请求和读取请求的可用性进行度量,包括从生产到读取的整体延时。
这种类型的监控对于验证Kafka集群的运行状态来说是非常有价值的,因为Kafkabroker本身无法告知客户端是否能够正常使用集群。
总结
监控是运行Kafka的一个重要组成部分,这也是为什么有那么多的团队在这上面花费了那么多时间。
很多组织使用Kafka处理千万亿字节级别的数据流。确保数据的持续性和不丢失消息是一个关键性的业务需求。作为Kafka集群的运维人员,我们的目标是成为最了解集群状态的人,同时,要协助用户监控他们的应用程序。
本章介绍了如何监控Java应用程序,特别是Kafka应用程序。
首先介绍了broker的一些度量指标,接着介绍了Java和操作系统的监控以及日志,然后详细地介绍了Kafka客户端的监控,包括配额的监控,最后讨论了如何使用外部监控系统进行消费者延时监控以及如何进行端到端的集群可用性监控。
本章虽然没有列出所有可用的度量指标,但已经涵盖了最为关键的部分。
参考资料
《kafka 权威指南》
- amy list
{:toc}