kafka总结
近期在做kafka metrics. 参考了几个开源的项目,诸如kafka manager, Burrow, kafkaOffsetMonitor,东西都很不错,可惜没有一个是用java编写的,最终自己去仿照kafka源码写了个java版的adminclient,拿到了自己需要的metrics数据。这个功能开发完,也对kafka有了些许的了解。遂记录如下。
基本概念:
producer:数据发送方。producer可以把消息以K-V的格式发送到某个topic。K是任意的表示,可string,可int;V可string,可byte[]。
consumer:数据接收方,或使用方。一个consumer可订阅一个或多个topic。每个consumer都属于一个consumer group.
group:某一类consumer的集合,有一个groupId,一个group中可以有多个consumer,发送到topic中的消息,只会被一个group中的某一个consumer消费。
Topic:一类消息的总称。Topic可以被分成多个partition存放在kafka集群的不同server上。发到topic中的数据以append的形式存储在log文件中,每条数据有一个唯一标示(offset)。
Partition:实际存储data的分区。一个topic的数据可以分布在多个分区,每个分区也可以定义备份的个数。每个分区有一个leader partition,在别的broker上有对应的多个follow partitions。Topic只从leader partition消费消息。当leader partition坏掉之后,kafka会自动从follow partitions中选出重新选出一个leader partition。
logSize:某个parition上log的总长度。
offset:数据在parition中的偏移量。这个offset不是该数据在partition文件中的实际偏移量,而是一个逻辑值用于确定一条message数据。比如有100条数据,offset为0~99,根据数据内容的大小,物理上可能分成5个segment文件,offset分别为0~15,16~20,21~55,55~80,81~99,每个segment的名字以最小offset命名,分别为0,16,21,55,81,这样根据某个offset定位数据的时候,就比较容易了。为了进一步方便定位,kafka还为每个segment建立了index,index包含两个部分:offset和position,position代表数据再segment文件中的绝对位置。
Lags: logSize - currentOffset.
kafka使用方式:
kafka可以有多种使用方法,比如作为常规的message bus, log日志集中通道,网站访问信息收集通道等等。特殊一点的,可以作为一个分布式的多线程库,消息分发到同一个group的不同的consumer上,进行并行处理。
kafka工作机制
kafka的消息传送机制:
- at most once: 消费者fetch消息,然后保存offset,然后处理消息。当client保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理.那么此后”未处理”的消息将不能被fetch到。
- at least once: 消费者fetch消息,然后处理消息,然后保存offset。如果消息处理成功之后,但是在保存offset阶段zookeeper异常导致保存操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息。
通常情况下,选用at least once。
Kafka复制备份机制:
kafka把每个parition的消息复制到多个broker上,任何一个parition都有一个leader和多个follow,备份个数可以在创建topic的时候指定。leader负责处理所有read/write请求,follower像consumer一样从leader接收消息并把消息存储在log文件中。leader还负责跟踪所有的follower状态,如果follower“落后”太多或失效,leader将会把它从replicas同步列表中删除。当所有的follower都将一条消息保存成功,此消息才被认为是“committed”。
Kafka与Zookeeper的交互机制:
当一个kafka broker启动后,会向zookeeper注册自己的节点信息,当broker和zookeeper断开链接时,zookeeper也会删除该节点的信息。除了自身的信息,broker也会向zookeeper注册自己持有的topic和partitions信息。
当一个consumer被创建时,会向zookeeper注册自己的信息,此作用主要是为了“负载均衡”。一个group中的多个consumer可以交错的消费一个topic的所有partitions。简而言之,保证此topic的所有partitions都能被此group所消费,且消费时为了性能的考虑,让partition相对均衡的分撒到每个consumer上。每一个consumer都有一个唯一的ID(host:uuid,可以通过配置文件指定,也可以由系统生成),此ID用来标记消费者信息,主要是topic+partition信息。
Producer端使用zookeeper用来”发现”broker列表,以及和Topic下每个partition leader建立socket连接并发送消息。
zookeeper上还存放partition被哪个consumer所消费的信息,以及每个consumer目前所消费的partition中的最大offset。
在kafka 0.9版本之后,kafka为了减少与zookeeper的交互,减少network data transfer,也自己实现了在kafka server上存储consumer,topic,partitions,offset信息。
kafka metrics:
对kafka的metrics主要是对lags的分析,lags是topic/partition的logSize与consumer消费到的offset之间的差值,即producer产生数据的量与consumer消费数据的量的差值,差值越来越大,说明消费数据的速度小于产生数据的速度。一般可以认定是consumer出了问题。当然也不能只看某一点的lags大小,更重要的是关注lags的变化的趋势,当趋势越来越大时,可推断consumer的performance越来越差。
在kafka 0.8.1版本之后,可以通过配置选择把topic/partition的logsize,offset等信息存储在zookeeper上或存储在kafka server上。在做metrics时,注意可能需要分别从两边获取数据。
获取zookeeper上的kafka数据比较简单,可以通过SimpleConsumer配合zookeeper.getChildren方法获取consumerGroup, topic, paritions信息,然后通过SimpleConsumer的getOffsetsBefore方法获取logSize,fetchOffsets获取topic parition的currentOffsets。
获取kafka server上的数据比较麻烦,目前kafka 0.10提供的kafkaConsumer类主要还是关注topic消费,对consumerGroup及Group和topic关系的获取,还没有提供API。不过我们知道可以通过kafka-consumer-groups.sh得到group,topic等信息的,这个shell文件里面调用了kafka.admin.ConsumerGroupCommand类,这个类确实提供了一个listGroup方法,可惜这个方法的返回值是void,shell文件的输出是打印到控制台的,并没有返回值。再去研究ConsumerGroupCommand是怎么拿到group的,发现它通过AdminClient对象的listAllConsumerGroup获取的group list,所以只要new出来一个AdminClient就能解决问题。
Java实现AdminClient(for kafka 0.9)
private static AdminClient getAdminClient(){
if(null != adminClient){
return adminClient;
}else{
Time time = new SystemTime();
Metrics metrics = new Metrics(time);
Metadata metadata = new Metadata();
ConfigDef configs = new ConfigDef();
configs.define(
CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG,
Type.LIST,
Importance.HIGH,
CommonClientConfigs.BOOSTRAP_SERVERS_DOC)
.define(
CommonClientConfigs.SECURITY_PROTOCOL_CONFIG,
ConfigDef.Type.STRING,
CommonClientConfigs.DEFAULT_SECURITY_PROTOCOL,
ConfigDef.Importance.MEDIUM,
CommonClientConfigs.SECURITY_PROTOCOL_DOC)
.withClientSslSupport()
.withClientSaslSupport();
HashMap<String, String> originals = new HashMap<String, String>();
originals.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, KAFKA_METRICS_BOOTSTRAP_SERVERS);
AbstractConfig abstractConfig = new AbstractConfig(configs, originals);
ChannelBuilder channelBuilder = org.apache.kafka.clients.ClientUtils.createChannelBuilder(abstractConfig.values());
List<String> brokerUrls = abstractConfig.getList(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG);
List<InetSocketAddress> brokerAddresses = org.apache.kafka.clients.ClientUtils.parseAndValidateAddresses(brokerUrls);
Cluster bootstrapCluster = Cluster.bootstrap(brokerAddresses);
metadata.update(bootstrapCluster, 0); Long DefaultConnectionMaxIdleMs = 9 * 60 * 1000L;
int DefaultRequestTimeoutMs = 5000;
int DefaultMaxInFlightRequestsPerConnection = 100;
Long DefaultReconnectBackoffMs = 50L;
int DefaultSendBufferBytes = 128 * 1024;
int DefaultReceiveBufferBytes = 32 * 1024;
Long DefaultRetryBackoffMs = 100L;
String metricGrpPrefix = "admin";
Map<String, String> metricTags = new LinkedHashMap<String, String>();
//Selector selector = new Selector(DefaultConnectionMaxIdleMs, metrics, time, metricGrpPrefix, channelBuilder);
Selector selector = new Selector(DefaultConnectionMaxIdleMs, metrics, time, metricGrpPrefix, metricTags, channelBuilder);
AtomicInteger AdminClientIdSequence = new AtomicInteger(1);
NetworkClient client = new NetworkClient(selector,
metadata,
"admin-" + AdminClientIdSequence.getAndIncrement(),
DefaultMaxInFlightRequestsPerConnection,
DefaultReconnectBackoffMs,
DefaultSendBufferBytes,
DefaultReceiveBufferBytes,
DefaultReceiveBufferBytes,
time);
ConsumerNetworkClient highLevelClient = new ConsumerNetworkClient(client, metadata, time, DefaultRetryBackoffMs);
//ConsumerNetworkClient highLevelClient = new ConsumerNetworkClient(client, metadata, time, DefaultRetryBackoffMs, DefaultRequestTimeoutMs);
scala.collection.immutable.List<Node> nList = scala.collection.JavaConverters.asScalaBufferConverter(bootstrapCluster.nodes()).asScala().toList();
adminClient = new AdminClient(time, DefaultRequestTimeoutMs, highLevelClient, nList);
return adminClient;
}
}
kafka总结的更多相关文章
- Spark踩坑记——Spark Streaming+Kafka
[TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...
- 消息队列 Kafka 的基本知识及 .NET Core 客户端
前言 最新项目中要用到消息队列来做消息的传输,之所以选着 Kafka 是因为要配合其他 java 项目中,所以就对 Kafka 了解了一下,也算是做个笔记吧. 本篇不谈论 Kafka 和其他的一些消息 ...
- kafka学习笔记:知识点整理
一.为什么需要消息系统 1.解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余: 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险. ...
- .net windows Kafka 安装与使用入门(入门笔记)
完整解决方案请参考: Setting Up and Running Apache Kafka on Windows OS 在环境搭建过程中遇到两个问题,在这里先列出来,以方便查询: 1. \Jav ...
- kafka配置与使用实例
kafka作为消息队列,在与netty.多线程配合使用时,可以达到高效的消息队列
- kafka源码分析之一server启动分析
0. 关键概念 关键概念 Concepts Function Topic 用于划分Message的逻辑概念,一个Topic可以分布在多个Broker上. Partition 是Kafka中横向扩展和一 ...
- Kafka副本管理—— 为何去掉replica.lag.max.messages参数
今天查看Kafka 0.10.0的官方文档,发现了这样一句话:Configuration parameter replica.lag.max.messages was removed. Partiti ...
- Kafka:主要参数详解(转)
原文地址:http://kafka.apache.org/documentation.html ############################# System ############### ...
- kafka
2016-11-13 20:48:43 简单说明什么是kafka? Apache kafka是消息中间件的一种,我发现很多人不知道消息中间件是什么,在开始学习之前,我这边就先简单的解释一下什么是消息 ...
- Spark Streaming+Kafka
Spark Streaming+Kafka 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端, ...
随机推荐
- React学习笔记-2-什么是jsx?如何使用jsx?
什么是jsx? JSX是JavaScript XML 这两个单词的缩写,xml和html非常类似,简单来说可以把它理解成使用各种各样的标签,大家可以自行 百度.所以jsx就是在javascri ...
- quartz.net插件类库封装(含源码)
1.前言 目录: 1.quartz.net任务调度:源码及使用文档 2.quartz.net插件类库封装 最近项目需要做一写任务作业调度的工作,最终选择了quartz.net这个插件,它提供了巨大的灵 ...
- 决策树的python实现
决策树 算法优缺点: 优点:计算复杂度不高,输出结果易于理解,对中间值缺失不敏感,可以处理不相关的特征数据 缺点:可能会产生过度匹配的问题 适用数据类型:数值型和标称型 算法思想: 1.决策树构造的整 ...
- HDU 1907 John nim博弈变形
John Problem Description Little John is playing very funny game with his younger brother. There is ...
- react native中对props和state的理解
最近使用react native这个新的技术做完一个项目,所以赶紧写个博客巩固一下. 今天我想说的是props和state,当然这是我个人的理解,如果有什么不对的地方,望指正. 首先我先说说props ...
- Linux学习笔记(3)-常用命令
江湖传言,Linux和Windows不同,他主要的用途是在一些服务器,或者片内系统上,所以人机交互界面自然就没有Windows那么漂亮,其实也没有那个必要. 所以,学习Linux的第一步,就是学习他那 ...
- linux 查找文件或者内容常用命令
whereis <程序名称> find [路径] <表达式> locate <文件名称> 从文件内容查找匹配指定字符串的行: $ grep "被查找的字符 ...
- sublime text3点击ctrl+B无法运行Python程序?
1.打开sublime text 3 ,选择 tools-->Build System-->New Build System.... 2.将下面代码块复制进新文件中,并命名为Python. ...
- CodeForces 518B. Tanya and Postcard
B. Tanya and Postcard time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken
在前面的学习中,配置文件中的<http>...</http>都是采用的auto-config="true"这种自动配置模式,根据Spring Securit ...