1.4 监控告警
关于Kafka的监控有一些开源的工具可用使用,比如下面这几种:
Kafka Manager;Kafka Eagle;Kafka Monitor;KafkaOffsetMonitor;
我们已经把Kafka Manager作为我们查看一些基本指标的工具嵌入平台,然而这些开源工具不能很好的融入到我们自己的业务系统或者平台上。所以,我们需要自己去实现一套粒度更细、监控更智能、告警更精准的系统。其监控覆盖范围应该包括基础硬件、操作系统(操作系统偶尔出现系统进程hang住情况,导致broker假死,无法正常提供服务)、Kafka的broker服务、Kafka客户端应用程序、zookeeper集群、上下游全链路监控。
1.4.1 硬件监控
网络监控:核心指标包括网络入流量、网络出流量、网络丢包、网络重传、处于TIME.WAIT的TCP连接数、交换机、机房带宽、DNS服务器监控(如果DNS服务器异常,可能出现流量黑洞,引起大面积业务故障)等。
磁盘监控:核心指标包括监控磁盘write、磁盘read(如果消费时没有延时,或者只有少量延时,一般都没有磁盘read操作)、磁盘ioutil、磁盘iowait(这个指标如果过高说明磁盘负载较大)、磁盘存储空间、磁盘坏盘、磁盘坏块/坏道(坏道或者坏块将导致broker处于半死不活状态,由于有crc校验,消费者将被卡住)等。
CPU监控:监控CPU空闲率/负载,主板故障等,通常CPU使用率比较低不是Kafka的瓶颈。
内存/交换区监控:内存使用率,内存故障。一般情况下,服务器上除了启动Kafka的broker时分配的堆内存以外,其他内存基本全部被用来做PageCache。
缓存命中率监控:由于是否读磁盘对Kafka的性能影响很大,所以我们需要监控Linux的PageCache缓存命中率,如果缓存命中率高,则说明消费者基本命中缓存。
详细内容请阅读文章:《Linux Page Cache调优在Kafka中的应用》。
系统日志:我们需要对操作系统的错误日志进行监控告警,及时发现一些硬件故障。
1.4.2 broker服务监控
broker服务的监控,主要是通过在broker服务启动时指定JMX端口,然后通过实现一套指标采集程序去采集JMX指标。(服务端指标官网地址)
broker级监控:broker进程、broker入流量字节大小/记录数、broker出流量字节大小/记录数、副本同步入流量、副本同步出流量、broker间流量偏差、broker连接数、broker请求队列数、broker网络空闲率、broker生产延时、broker消费延时、broker生产请求数、broker消费请求数、broker上分布leader个数、broker上分布副本个数、broker上各磁盘流量、broker GC等。
topic级监控:topic入流量字节大小/记录数、topic出流量字节大小/记录数、无流量topic、topic流量突变(突增/突降)、topic消费延时。
partition级监控:分区入流量字节大小/记录数、分区出流量字节大小/记录数、topic分区副本缺失、分区消费延迟记录、分区leader切换、分区数据倾斜(生产消息时,如果指定了消息的key容易造成数据倾斜,这严重影响Kafka的服务性能)、分区存储大小(可以治理单分区过大的topic)。
用户级监控:用户出/入流量字节大小、用户出/入流量被限制时间、用户流量突变(突增/突降)。
broker服务日志监控:对server端打印的错误日志进行监控告警,及时发现服务异常。
1.4.3.客户端监控
客户端监控主要是自己实现一套指标上报程序,这个程序需要实现 org.apache.kafka.common.metrics.MetricsReporter 接口。然后在生产者或者消费者的配置中加入配置项 metric.reporters,如下所示:
客户端指标官网地址:http://kafka.apache.org/21/documentation.html#selector_monitoring
http://kafka.apache.org/21/documentation.html#common_node_monitoring
http://kafka.apache.org/21/documentation.html#producer_monitoring
http://kafka.apache.org/21/documentation.html#producer_sender_monitoring
http://kafka.apache.org/21/documentation.html#consumer_monitoring
http://kafka.apache.org/21/documentation.html#consumer_fetch_monitoring
客户端监控流程架构如下图所示:
1.4.3.1 生产者客户端监控
维度:用户名称、客户端ID、客户端IP、topic名称、集群名称、brokerIP;指标:连接数、IO等待时间、生产流量大小、生产记录数、请求次数、请求延时、发送错误/重试次数等。
1.4.3.2 消费者客户端监控
维度:用户名称、客户端ID、客户端IP、topic名称、集群名称、消费组、brokerIP、topic分区;指标:连接数、io等待时间、消费流量大小、消费记录数、消费延时、topic分区消费延迟记录等。
1.4.4 Zookeeper监控
1) Zookeeper进程监控;
2) Zookeeper的leader切换监控;
3) Zookeeper服务的错误日志监控;
1.4.5 全链路监控
当数据链路非常长的时候(比如:业务应用->埋点SDk->数据采集->Kafka->实时计算->业务应用),我们定位问题通常需要经过多个团队反复沟通与排查才能发现问题到底出现在哪个环节,这样排查问题效率比较低下。在这种情况下,我们就需要与上下游一起梳理整个链路的监控。出现问题时,第一时间定位问题出现在哪个环节,缩短问题定位与故障恢复时间。
1.5 资源隔离
1.5.1 相同集群不同业务资源物理隔离
我们对所有集群中不同对业务进行资源组物理隔离,避免各业务之间相互影响。在这里,我们假设集群有4个broker节点(Broker1/Broker2/Broker3/Broker4),2个业务(业务A/业务B),他们分别拥有topic分区分布如下图所示,两个业务topic都分散在集群的各个broker上,并且在磁盘层面也存在交叉。
试想一下,如果我们其中一个业务异常,比如流量突增,导致broker节点异常或者被打挂。那么这时候另外一个业务也将受到影响,这样将大大的影响了我们服务的可用性,造成故障,扩大了故障影响范围。
针对这些痛点,我们可以对集群中的业务进行物理资源隔离,各业务独享资源,进行资源组划分(这里把4个broker划分为Group1和Group2两个资源组)如下图所示,不同业务的topic分布在自己的资源组内,当其中一个业务异常时,不会波及另外一个业务,这样就可以有效的缩小我们的故障范围,提高服务可用性。
1.6 集群归类
我们把集群根据业务特点进行拆分为日志集群、监控集群、计费集群、搜索集群、离线集群、在线集群等,不同场景业务放在不同集群,避免不同业务相互影响。
1.7 扩容/缩容
1.7.1 topic扩容分区
随着topic数据量增长,我们最初创建的topic指定的分区个数可能已经无法满足数量流量要求,所以我们需要对topic的分区进行扩展。扩容分区时需要考虑以下几点:
必须保证topic分区leader与follower轮询的分布在资源组内所有broker上,让流量分布更加均衡,同时需要考虑相同分区不同副本跨机架分布以提高容灾能力;当topic分区leader个数除以资源组节点个数有余数时,需要把余数分区leader优先考虑放入流量较低的broker。
1.7.2 broker上线
随着业务量增多,数据量不断增大,我们的集群也需要进行broker节点扩容。关于扩容,我们需要实现以下几点:
扩容智能评估:根据集群负载,把是否需要扩容评估程序化、智能化;智能扩容:当评估需要扩容后,把扩容流程以及流量均衡平台化。
1.7.3 broker下线
某些场景下,我们需要下线我们的broker,主要包括以下几个场景:
一些老化的服务器需要下线,实现节点下线平台化;服务器故障,broker故障无法恢复,我们需要下线故障服务器,实现节点下线平台化;有更优配置的服务器替换已有broker节点,实现下线节点平台化。
1.8 负载均衡
我们为什么需要负载均衡呢?首先,我们来看第一张图,下图是我们集群某个资源组刚扩容后的流量分布情况,流量无法自动的分摊到我们新扩容后的节点上。那么这个时候需要我们手动去触发数据迁移,把部分副本迁移至新节点上才能实现流量均衡。
下面,我们来看一下第二张图。这张图我们可以看出流量分布非常不均衡,最低和最高流量偏差数倍以上。这和Kafka的架构特点有关,当集群规模与数据量达到一定量后,必然出现问题。这种情况下,我们也需要进行负载均衡。
我们再来看看第三张图。这里我们可以看出出流量只有部分节点突增,这就是topic分区在集群内部不够分散,集中分布到了某几个broker导致,这种情况我们也需要进行扩容分区和均衡。
我们比较理想的流量分布应该如下图所示,各节点间流量偏差非常小,这种情况下,既可以增强集群扛住流量异常突增的能力又可以提升集群整体资源利用率和服务稳定性,降低成本。
负载均衡我们需要实现以下效果:
1)生成副本迁移计划以及执行迁移任务平台化、自动化、智能化;2)执行均衡后broker间流量比较均匀,且单个topic分区均匀分布在所有broker节点上;3)执行均衡后broker内部多块磁盘间流量比较均衡;
要实现这个效果,我们需要开发一套自己的负载均衡工具,如对开源的 cruise control进行二次开发;此工具的核心主要在生成迁移计划的策略,迁移计划的生成方案直接影响到最后集群负载均衡的效果。参考内容:
1. linkedIn/cruise-control
2. Introduction to Kafka Cruise Control
3. Cloudera Cruise Control REST API Reference
cruise control架构图如下:
在生成迁移计划时,我们需要考虑以下几点:
1)选择核心指标作为生成迁移计划的依据,比如出流量、入流量、机架、单topic分区分散性等;2)优化用来生成迁移计划的指标样本,比如过滤流量突增/突降/掉零等异常样本;3)各资源组的迁移计划需要使用的样本全部为资源组内部样本,不涉及其他资源组,无交叉;4)治理单分区过大topic,让topic分区分布更分散,流量不集中在部分broker,让topic单分区数据量更小,这样可以减少迁移的数据量,提升迁移速度;
5)已经均匀分散在资源组内的topic,加入迁移黑名单,不做迁移,这样可以减少迁移的数据量,提升迁移速度;6)做topic治理,排除长期无流量topic对均衡的干扰;7)新建topic或者topic分区扩容时,应让所有分区轮询分布在所有broker节点,轮询后余数分区优先分布流量较低的broker;8)扩容broker节点后开启负载均衡时,优先把同一broker分配了同一大流量(流量大而不是存储空间大,这里可以认为是每秒的吞吐量)topic多个分区leader的,迁移一部分到新broker节点;9)提交迁移任务时,同一批迁移计划中的分区数据大小偏差应该尽可能小,这样可以避免迁移任务中小分区迁移完成后长时间等待大分区的迁移,造成任务倾斜;