Kafka详解六:Kafka如何通过源码实现监控
问题导读:
1.kafka的消费者组的消费偏移存储,kafka支持两个版本?
2.ConsumerOffsetChecker类的作用是什么?
3.Kafka如何通过源码实现监控?
val topicList = topics match { case Some(x) => x.split(",").view.toList case None => ZkUtils.getChildren(zkClient, groupDirs.consumerGroupDir + "/owners").toList} |
接着是建立到Broker链接,然后从kafka获取消费者偏移
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
val topicPartitions = topicPidMap.flatMap { case(topic, partitionSeq) => partitionSeq.map(TopicAndPartition(topic, _)) }.toSeqval channel = ClientUtils.channelToOffsetManager(group, zkClient, channelSocketTimeoutMs, channelRetryBackoffMs)debug("Sending offset fetch request to coordinator %s:%d.".format(channel.host, channel.port))channel.send(OffsetFetchRequest(group, topicPartitions))val offsetFetchResponse = OffsetFetchResponse.readFrom(channel.receive().buffer)debug("Received offset fetch response %s.".format(offsetFetchResponse))offsetFetchResponse.requestInfo.foreach { case (topicAndPartition, offsetAndMetadata) => if (offsetAndMetadata == OffsetMetadataAndError.NoOffset) { val topicDirs = new ZKGroupTopicDirs(group, topicAndPartition.topic) // this group may not have migrated off zookeeper for offsets storage (we don't expose the dual-commit option in this tool // (meaning the lag may be off until all the consumers in the group have the same setting for offsets storage) try { val offset = ZkUtils.readData(zkClient, topicDirs.consumerOffsetDir + "/%d".format(topicAndPartition.partition))._1.toLong offsetMap.put(topicAndPartition, offset) } catch { case z: ZkNoNodeException => if(ZkUtils.pathExists(zkClient,topicDirs.consumerOffsetDir)) offsetMap.put(topicAndPartition,-1) else throw z } } else if (offsetAndMetadata.error == ErrorMapping.NoError) offsetMap.put(topicAndPartition, offsetAndMetadata.offset) else { println("Could not fetch offset for %s due to %s.".format(topicAndPartition, ErrorMapping.exceptionFor(offsetAndMetadata.error))) }} |
假如,获得的偏移信息为空,那么就从Zookeeper获取消费者偏移。
解决获取topic的分区的最大偏移,实际思路是构建simpleConsumer,然后由其 去请求偏移,再跟获取的消费者偏移做差就得到消费者最大偏移。
|
01
02
03
04
05
06
07
08
09
10
|
topicList.sorted.foreach { topic => processTopic(zkClient, group, topic)}topicPidMap.get(topic) match { case Some(pids) => pids.sorted.foreach { pid => processPartition(zkClient, group, topic, pid) } case None => // ignore} |
在processPartition中
|
01
02
03
04
05
06
07
08
09
10
11
12
|
val offsetOpt = offsetMap.get(topicPartition)val groupDirs = new ZKGroupTopicDirs(group, topic)val owner = ZkUtils.readDataMaybeNull(zkClient, groupDirs.consumerOwnerDir + "/%s".format(pid))._1ZkUtils.getLeaderForPartition(zkClient, topic, pid) match { case Some(bid) => val consumerOpt = consumerMap.getOrElseUpdate(bid, getConsumer(zkClient, bid)) consumerOpt match { case Some(consumer) => val topicAndPartition = TopicAndPartition(topic, pid) val request = OffsetRequest(immutable.Map(topicAndPartition -> PartitionOffsetRequestInfo(OffsetRequest.LatestTime, 1))) val logSize = consumer.getOffsetsBefore(request).partitionErrorAndOffsets(topicAndPartition).offsets.head |
然后做差得到LagSize
|
1
2
3
|
val lagString = offsetOpt.map(o => if (o == -1) "unknown" else (logSize - o).toString)println("%-15s %-30s %-3s %-15s %-15s %-15s %s".format(group, topic, pid, offsetOpt.getOrElse("unknown"), logSize, lagString.getOrElse("unknown"), owner match {case Some(ownerStr) => ownerStr case None => "none"})) |
getConsumer方法中
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
private def getConsumer(zkClient: ZkClient, bid: Int): Option[SimpleConsumer] = { try { ZkUtils.readDataMaybeNull(zkClient, ZkUtils.BrokerIdsPath + "/" + bid)._1 match { case Some(brokerInfoString) => Json.parseFull(brokerInfoString) match { case Some(m) => val brokerInfo = m.asInstanceOf[Map[String, Any]] val host = brokerInfo.get("host").get.asInstanceOf[String] val port = brokerInfo.get("port").get.asInstanceOf[Int] Some(new SimpleConsumer(host, port, 10000, 100000, "ConsumerOffsetChecker")) case None => throw new BrokerNotAvailableException("Broker id %d does not exist".format(bid)) } case None => throw new BrokerNotAvailableException("Broker id %d does not exist".format(bid)) } } catch { case t: Throwable => println("Could not parse broker info due to " + t.getCause) None }} |
四,总结
该工具类的使用
|
1
|
bin/kafka-consumer-offset-checker.sh --group yourgroup -topic yourtopic --zookeeper localhost:2181 |
输出结果
Offset是消费者消费到的偏移,logsize是kafka数据的最大偏移,Lag是二者的差。也即
LagSize = LogSize - Offset
得到我们消费组的滞后情况后,我们就可以根据需求(比如,设定滞后多少消息后给出告警),给出相应的告警。
转自:http://www.aboutyun.com/forum.php?mod=viewthread&tid=22215&extra=page%3D1&page=1&
Kafka详解六:Kafka如何通过源码实现监控的更多相关文章
- kafka详解(一)--kafka是什么及怎么用
kafka是什么 在回答这个问题之前,我们需要先了解另一个东西--event streaming. 什么是event streaming 我觉得,event streaming 是一个动态的概念,它描 ...
- kafka详解(二)--kafka为什么快
前言 Kafka 有多快呢?我们可以使用 OpenMessaging Benchmark Framework 测试框架方便地对 RocketMQ.Pulsar.Kafka.RabbitMQ 等消息系统 ...
- Linux下通过源码编译安装程序
本文简单的记录了下,在linux下如何通过源码安装程序,以及相关的知识.(大神勿喷^_^) 一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件: ...
- 通过源码了解ASP.NET MVC 几种Filter的执行过程
一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神的工作,而且很多人觉得平时根本不需要知道这些,会用就行了.其实阅读源 ...
- 大数据入门第七天——MapReduce详解(二)切片源码浅析与自定义patition
一.mapTask并行度的决定机制 1.概述 一个job的map阶段并行度由客户端在提交job时决定 而客户端对map阶段并行度的规划的基本逻辑为: 将待处理数据执行逻辑切片(即按照一个特定切片大小, ...
- 通过源码了解ASP.NET MVC 几种Filter的执行过程 在Winform中菜单动态添加“最近使用文件”
通过源码了解ASP.NET MVC 几种Filter的执行过程 一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神 ...
- 在centos6.7通过源码安装python3.6.7报错“zipimport.ZipImportError: can't decompress data; zlib not available”
在centos6.7通过源码安装python3.6.7报错: zipimport.ZipImportError: can't decompress data; zlib not available 从 ...
- 通过源码编译安装VIM
开发中使用的是Ubuntu 12.04 LTS,通过sudo apt-get install vim安装的版本较低,不支持YCM,所以,用源码编译并安装最新的Vim. 卸载旧版本的Vim: sudo ...
- echarts 通过源码方法 传入对应data数据获取分割步长值
通过源码方法获取这里的分割数字长度 /** * Quantity of a number. e.g. 0.1, 1, 10, 100 * * @param {number} val * @return ...
随机推荐
- Unity3d 创建线程 子线程与主线程通信
创建子线程 一,不带参数 Thread resourcesLoadThread=new Thread (this.resourceLoadTxt); resourcesLoadThread.Sta ...
- jQuery倒计时实例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 【转】哈希(Hash)与加密(Encrypt)的基本原理、区别及工程应用
0.摘要 今天看到吉日嘎拉的一篇关于管理软件中信息加密和安全的文章,感觉非常有实际意义.文中作者从实践经验出发,讨论了信息管理软件中如何通过哈希和加密进行数据保护.但是从文章评论中也可以看出很多朋友对 ...
- C#快速整理代码格式
删除最后一个大括号,再添加.vs自动整理代码结构.
- 如何生成动态库 .dll 的符号 .lib 文件?
在知道拥有动态库和头文件的情况下,但没有动态库符号文件的情况下,如何静态链接动态库? 1.使用 Microsoft Visual Studio Tools 命令行命令生成 xxx.def 文件,进而使 ...
- ORACLE中RECORD、VARRAY、TABLE的使用具体解释
1 说明 1.1 RECORD 定义记录数据类型. 它类似于C语言中的结构数据类型(STRUCTURE).PL/SQL提供了将几个相关的.分离的.基本数据类型的变量组成一个总 ...
- 0102-使用 API 网关构建微服务
一.移动客户端如何访问这些服务 1.1.客户端与微服务直接通信[很少使用] 从理论上讲,客户端可以直接向每个微服务发送请求.每个微服务都有一个公开的端点(https ://.api.company.n ...
- 2.1 使用ARDUINO控制MC20打电话
需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...
- JAVA抠取Excel中的图片
EXCEL中扔了一堆的图片,老大让对应到数据库中的数据上.思路先把图片抠出存成单个图片.然后上传到服务器,取下路径更新到数据库中. 注释掉的部分为有多个Excel时使用. package com.** ...
- HDF及HDF-EOS数据格式简介
HDF-EOS数据格式介绍 HDF(Hierarchy Data Format )数据格式是美国伊利诺伊大学国家超级计算应用中心(NCSA ,National Central for Super co ...