kafka
文章平均质量分 78
kafka
water___Wang
不断学习
展开
-
前传(1):Kafka 的前生今世
不错的文章,转发下Kafka只是消息引擎系统吗?要搞清楚这个问题,我们不可避免地要了解一下 Apache Kafka 的发展历程。有的时候我们会觉得说了解一个系统或框架的前世今生似乎没什么必要,直接开始学具体的技术不是更快更好吗?其实,不论是学习哪种技术,直接扎到具体的细节中,亦或是从一个很小的点开始学习,你很快就会感到厌烦。为什么呢?因为你虽然快速地搞定了某个技术细节,但无法建立全局的认知观,这会导致你只是在单个的点上有所进展,却没法将其串联成一条线进而扩展成一个面,从而实现系统地学习。我这么.转载 2021-03-17 14:55:58 · 482 阅读 · 0 评论 -
前传(2):如何选择Kafka发行版?
我们谈了 Kafka 当前的定位问题,Kafka 不再是一个单纯的消息引擎系统,而是能够实现精确一次(Exactly-once)处理语义的实时流处理平台。你可能听说过 Apache Storm、Apache Spark Streaming 亦或是 Apache Flink,它们在大规模流处理领域可都是响当当的名字。令人高兴的是,Kafka 经过这么长时间不断的迭代,现在已经能够稍稍比肩这些框架了。我在这里使用了“稍稍”这个字眼,一方面想表达Kafka 社区对于这些框架心存敬意;另一方面也想表达目前国内鲜有转载 2021-03-17 15:10:46 · 1752 阅读 · 0 评论 -
前传(3):Kafka的版本号
版本号实在是太重要了,我觉得它甚至是你日后能否用好 Kafka 的关键。上一期我介绍了目前流行的几种 Kafka 发行版,其实不论是哪种 Kafka,本质上都内嵌了最核心的 Apache Kafka,也就是社区版 Kafka,那今天我们就来说说 Apache Kafka 版本号的问题。在开始之前,我想强调一下后面出现的所有“版本”这个词均表示 Kafka 具体的版本号,而非上一篇中的 Kafka 种类,这一点切记切记!那么现在你可能会有这样的疑问:我为什么需要关心版本号的问题呢?直接使用最新版本.转载 2021-03-17 15:20:48 · 353 阅读 · 0 评论 -
1.1 Kafka 的基本概念
开始kafka之路在0.10版本之前, Kafka仅仅作为一个消息系统,主要用来解决应用解祸 、 异步消息 、 流量削峰等问题。 不过在0 .10版本之后, Kafka提供了连接器与流处理的能力,它也从分布式的消息系统逐渐成为一个流式的数据平台 。 先介绍Kafka流式数据-平台的基本组成,然后分析它的一些架构设计和基本概念,最后通过几个示例快速理解它的一些重要特性。1.1 kafka流式数据平台作为一个流式数据平台,最重要的是要具备下面3个特点 。类似消息系统,提供事件流的发布和订阅,.原创 2021-03-20 10:50:37 · 259 阅读 · 1 评论 -
1.2 Kafka 的设计与实现
下面我们会从3个角度分析Kafka的一些设计思路,并尝试回答下面3个问题。- 如何利用操作系统的优化技术来高效地持久化日志文件和加快数据传输效率?- Kafka的生产者如何批量地发送消息,消费者采用拉取模型带来的优点都有哪些?- Kafka的副本机制如何工作,当故障发生时,怎么确保数据不会丢失?原创 2021-03-24 21:36:18 · 302 阅读 · 0 评论 -
1.3 win下Kafka源码环境搭建
本文目的:1 搭建win下kafka调试环境,2,看kafka源码1 本文环境win10专业版JDK 1.8scala 2.13.4gradle 3.5kafka 1.0.0 源码2 前置软件准备2.1 JDK安装省略(如果有本地有多个jdk环境,可以参考这里进行配置切换),检查版本如下2.2 scala安装省略,检查版本如下2.3 gradle安装看这里(注意最好设置好远程私服地址+本地仓库地址),检查版本如下2.4 kafka源码直接从官网下载,我下载.原创 2021-03-22 12:01:12 · 26512 阅读 · 0 评论 -
1.4 源码阅读顺序
重点关注的目录:core :Broker 端工程,保存 Broker 代码。clients :Client 端工程,保存所有 Client 代码以及所有代码都会用到的一些公共代码。streams :Streams 端工程,保存 Kafka Streams 代码。connect :Connect 端工程,保存 Kafka Connect 框架代码以及 File Connector 代码。源码阅读顺序log 包 : log 包中定义了 Broker 底层消息和索引保存机制以及物理格式。 .原创 2021-03-23 11:09:53 · 266 阅读 · 0 评论 -
2.1.1 同步和异步发送消息
紧接着上篇2.2 服务端网络连接服务端网络连接KafkaServer是Kafka服务端的主类,KafkaServer中和网络层有关的服务组件包括SocketServer、KafkaApis和KafkaRequestHandlerPool。后两者都使用了SocketServer暴露出来的请求通道(requestChannel)来处理网络请求。KafkaServer中和服务端相关的组件还有很多,不过由于本章主要关注网络层,所以暂时不关注其他功能组件。相关代码如下:def startup() {.原创 2021-03-25 10:24:51 · 805 阅读 · 0 评论 -
2.1.2 客户端消息发送线程
2.1.2 客户端消息发送线程追加消息到记录收集器时按照分区进行分组,并放到 batches集合中,每个分区的队列都保存了即将发送到这个分区对应节点上的批记录,客户端的发送线程可 以只使用一个 Sende「线程迭代batches的每个分区,获取分区对应的主剧本节点,取出分区对应的队列中的批记录就可以发送消息了 。消息发送线程有两种消息发送方式 : 按照分区直接发送 、 按照分区的目标节点发迭 。 假设有两台服务器, 主题有6个分区,那么每台服务器就有3个分区 。 如图2-7 (左)所示,消息发送.原创 2021-04-15 00:12:31 · 2967 阅读 · 0 评论 -
2.1.3 客户端网络连接对象
客户端网络连接对象(NetworkClient )管理了客户端和服务端之间的 网络通信,包括连接的建立、发送客户端请求 、 读取客户端响应。回顾下2 . 1.2节中第 1小节“从记录收集器获取数据”部分,发送线程的run()方法中会调用 NetworkClient的3个方法原创 2021-04-15 12:21:15 · 3039 阅读 · 1 评论 -
2.1.4 选择器处理网络请求
2.1.4 选择器处理网络请求生产者客户端会按照节点对消息进行分组,每个节点对应一个客户端请求,那么一个生产者客户端需要管理到多个服务端节点的网络连接。 涉及网络通信时, 一般使用选择器模式 。 选择器使用JavaNIO异步非阻塞方式管理连接和读写请求,它用单个线程就可以管理多个网络连接通道 。 使用选择器的好处是:生产者客户端只需要使用一个选择器,就可以同时和Kafka集群的多个服务端进行网络通信。 为了更好地理解Kafka的网络层通信方式,我们先来复习下Java NIO的一些重要概念。Socket原创 2021-04-15 16:55:23 · 3060 阅读 · 0 评论 -
2.2.1 服务端使用接收器接受客户端的连接
紧接着上篇2.2 服务端网络连接服务端网络连接KafkaServer是Kafka服务端的主类,KafkaServer中和网络层有关的服务组件包括SocketServer、KafkaApis和KafkaRequestHandlerPool。后两者都使用了SocketServer暴露出来的请求通道(requestChannel)来处理网络请求。KafkaServer中和服务端相关的组件还有很多,不过由于本章主要关注网络层,所以暂时不关注其他功能组件。相关代码如下:def startup() {.原创 2021-03-25 14:16:34 · 309 阅读 · 0 评论 -
2.2.2 处理器使用选择器的轮询处理网络请求
2.2.2 处理器使用选择器的轮询处理网络请求接收器采用Round-Robin的方式分配客户端的SocketChannel给多个处理器,每个处理器都会有多个SocketChannel,对应多个客户端连接。就像NetworkClient中用一个选择器管理多个服务端的连接,服务端的每个处理器也都使用一个选择器管理多个客户端连接。处理器接受一个新的SocketChannel通道连接时,先将其放入阻塞队列,然后唤醒选择器线程开始工作。回顾客户端连接服务端时会创建Kafka通道,这里服务端的处理器也会为Socke原创 2021-04-15 17:50:46 · 3068 阅读 · 0 评论 -
2.2.3 请求通道的请求队列和响应队列
2.2.3 请求通道的请求队列和响应队列创建SocketServer也会创建一个请求通道(RequestChannel),在KafkaServer中,会将SocketServer的请求通道传给Kafka请求处理线程(KafkaRequestHandler,下文简称“请求处理线程”)和KafkaApis。在上一节中客户端的请求已经到达服务端的处理器(processor),那么请求通道就是处理器与请求处理线程和KafkaApis交换数据的地方:如果处理器往请求通道添加请求,请求处理线程和KafkaApis都.原创 2021-04-15 18:51:54 · 3672 阅读 · 1 评论 -
2.2.4 Kafka请求处理线程
2.2.4 Kafka请求处理线程KafkaServer会创建请求处理线程池(KafkaRequestHandlerPool),在请求处理钱程池中会创建并启动多个请求处理线程(KafkaRequestHandler)。SocketServer中全局的请求通道会传递给每个请求处理线程。这样每个请求处理线程共同消费同一个请求通道中的所有客户端请求。每个请求处理线程获取到请求后,都交给统一的KafkaApis处理。注意:一个KafkaServer有多个请求处理线程,但是只有一个KafkaApis。相关代码如下:原创 2021-04-15 19:09:07 · 3101 阅读 · 0 评论 -
2.2.5 服务端的请求处理入口
2.2.5 服务端的请求处理入口现在请求通道上请求的发送(由处理器执行)和接收(由请求处理线程执行),以及响应的接收(由处理器执行)都有了,只剩下响应的发送由rKafkaApis负责。r客户端请求通过请求处理器交给负责具体业务逻辑处理的rKafkaApisr,rKafkaApis收到请求执行完业务逻辑,r将请求对应的响应结果发送到请求通道的响应队歹ljr中r。r因为rKafkaApis类持有请求通道的引用,所以它可以把响应发送到请求通道中。现在,请求和响应的发送和接收四个步骤就都齐了 。KafkaAp"原创 2021-04-15 20:00:59 · 3001 阅读 · 0 评论 -
3.1.1创建并初始化消费者连接器
消息系统通常由生产者「producer )、 消费者( consumer )和消息代理( broker ) 三大部分组成,生产者会将消息写入消息代理,消费者会从消息代理中读取消息 。 对于消息代理而育,生产者和消费者都属于客户端:生产者和消费者会发送客户端请求给服务端,服务端的处理分别是存储消息和获取消息,最后服务端返回响应结果给客户端。客户端和服务端的通信涉及网络中不同的节点,客户端和服务端都会有一个连接对象,负责数据的发送和接收:比如客户端会发送请求 、接收响应,服务端会接收请求 、 发送响应 。.原创 2021-03-25 21:59:05 · 396 阅读 · 0 评论 -
3.1.2 消费者客户端的线程模型
3.1.2 消费者客户端的线程模型消费者连接器的createMessageStreams()方法会调用consume()方法,但consume()方法并不真正消费数据,而只是为消费消息做准备工作,具体步骤如下。(1)根据客户端传入的topicCountMap构造对应的队列和消息流,消息流引用了队列。(2)在ZK的消费组父节点下注册消费者子节点。(3)执行初始化工作,触发再平衡,为消费者分配分区,拉取线程会拉取消息放到队列中。(4)返回消息流列表,队列中有数据时,客户端就可以从消息流中迭代读取消息。原创 2021-04-15 22:38:30 · 3047 阅读 · 0 评论 -
3.1.3 重新初始化消费者
3.1.3 重新初始化消费者消费者连接器的consume()方法在注册消费者至UZK后,调用reinitializeConsumer()方法执行重新初始化。消费者启动时希望被加入消费组,必须执行一次初始化方法,并触发消费组内所有消费者成员(当然也包括自己)的再平衡。如图3-12所示,触发消费者连接器执行再平衡操作有两种方式:外部事件和直接触发。直接触发会在消费者启动时执行,即重新初始化消费者时,直接调用syncedRebalance()方法强制触发一次再平衡。外部事件会通过下面3种监昕器和线程检查的.原创 2021-04-15 23:05:11 · 3038 阅读 · 2 评论 -
3.2.1 分区的所有权
3.2 消费者再平衡操作消费者连接器的核心处理逻辑是ZKRebalanceListener的再平衡操作,它起了承上启下的作用上一节初始化消费者连接器只是“创建了队列和消息流”,再平衡操作会“为消费者重新分配分区”。只有为消费者分配了分区,拉取线程才会开始拉取分区的消息。因为分区要被重新分配,分区的所有者都会发生变化,所以在还没有重新分配分区之前,所有消费者都要停止已有的拉取钱程。同时,分区分配给消费者都会在ZK中记录所有者信息,所以也要先删除ZK上的节点数据。只有和分区相关的ZK所有者、拉取线程原创 2021-03-26 10:32:09 · 131 阅读 · 0 评论 -
3.2.2 为消费者分配分区
3.2.2 为消费者分配分区每一个消费者都需要分配到分区才能拉取信息,当发生再平衡时,消费组中的所有消费者都会重新分配分区。 为了让每个消费者都能被分配到分区,需要从ZK中查询出所有的分区以及所有的消费者成员歹lj表 。 当然,分区要限定主题范围,消费者要限定消费组范围 。 对于触发再平衡的消费者而言,它所属的消费组是确定的,而且订阅的主题和分区也是确定的,所以从ZK中获取订阅相同主题的消费者成员列表、包含相同主题的分区都没有问题。如图3-13所示,消费者l订阅了主题1和主题2,消费者2订阅了主题1和.原创 2021-04-15 23:36:24 · 2990 阅读 · 0 评论 -
3.2.3 创建分区信息对象
3.2.3 创建分区信息对象从ZK中读取出的分区的偏移量,会被用来构造分区信息对象(PartitionTopicinfo)。分区信息对象的主要内容有:分区,表示拉取线程的“目标”;队列,作为消息的“存储”介质;偏移量,作为拉取“状态”。消费者的拉取线程会以最新的“状态”拉取ZK的offsetCounter是这个分区最近一次的消费偏移量,也是最新的拉取偏移量。消费者向服务端发起拉取数据请求时,拉取偏移量(fetchOffset)表示要从哪里开始拉取。消费者从服务端拉取消息写到本地后,消费偏移量(cons.原创 2021-04-16 00:37:30 · 2962 阅读 · 0 评论 -
3.2.4 关闭和更新拉取线程管理器
3.2.4 关闭和更新拉取线程管理器再平衡操作中我们已经分析了分区的所有权、分区的分配,剩下和l拉取线程(Consul’lerFetcherThread)相关的是:关闭和更新消费者的拉取线程管理器(Consul’lerFetcherManager,下文简称“拉取管理器”)。再平衡操作前,closeFetchersForQueues()方法关闭拉取管理器时,也要关闭它管理的所有线程。除了拉取线程应该关闭,和拉取线程相关的数据结构也需要清理,比如分区信息对象的队列需要清空。另外,消费者在拉取数据时会周期.原创 2021-04-16 09:14:07 · 2931 阅读 · 0 评论 -
3.2.5分区信息对象的偏移量
3.2.5分区信息对象的偏移量在结束本节之前,我们来看一下分区信息对象的偏移量在拉取钱程中的使用方式。消费者的拉取线程第一次拉取消息时,会从ZK中读取fetchedOffset来决定要从分区的哪个位置开始拉取消息。消费者在读取到消息后,会更新分区的consuMedOffset。同时,消费者也会使用consuMedOffset作为分区的消费进度并定时地提交到ZK中。注意:但并不是说拉取线程每次拉取消息都要读取ZK的偏移量作为fetchedOffset(那样和ZK交互就太频繁了)。因为客户端已经保存了con原创 2021-04-16 12:52:31 · 3015 阅读 · 0 评论 -
3.3.1 拉取线程管理器
3.3 消费者拉取数据消费者连接器通过再平衡操作分配到的分区相当于t作任务,任务需要由工作线程完成。生产者要写消息到服务端的分区,这是通过Sender工作线程完成的,消费者要读服务端分区的消息则通过拉取管理器的拉取线程完成。下面我们来分析消费者客户端拉取消息的具体实现。3.3.1 拉取线程管理器消费者的拉取管理器(ConsumerFetcherManager)管理了当前消费者的所有拉取线程,这些拉取线程会从服务端的分区拉取消息。前面我们知道每个消费者都会分配到分区信息集合,这些分区会被拉取管理器的st原创 2021-03-26 14:04:44 · 177 阅读 · 4 评论 -
3.3.2 抽象拉取线程
3.3.2 抽象拉取线程抽象拉取线程(AbstractFetcherThread)定义了拉取工作的主要流程,不同的实现类通过抽象方法嵌套在主流程中,保证了主流程执行的一致性。拉取线程工作时,首先要确定数据源(即拉取状态),每次拉取到消息还要更新拉取状态,确保下一次拉取请求时获得的拉取状态是最新的。构建拉取请求拉取管理器后台线程调用拉取线程的addPartitians()方法,partitionMap变量保存了每个分区的拉取状态。拉取线程的运行方法会根据拉取状态构建井处理拉取请求。相关代码如下:.原创 2021-04-16 16:35:17 · 3266 阅读 · 0 评论 -
3.3.3 消费者拉取线程
3.3.3 消费者拉取线程消费者拉取管理器在创建拉取线程时,会将表示分区及其分区信息对象的全局partitionMap作为类级别的变量传给每个拉取线程,但每个拉取线程在拉取时实际上只会负责一部分的分区。拉取线程在拉取到分区数据后,需要将拉取结果保存到分区信息的队列中。因为每个拉取线程都持有全局的partitionMap引用,所以processPartitionData()方法在处理拉取结果时,可以获取到分区信息中的队列,并将拉取结果填充到队列中。相关代码如下:注意:拉取线程的抽象类在拉取工作中也有一个原创 2021-04-16 17:55:43 · 2958 阅读 · 0 评论 -
3.4.1 Kafka消息流
3.4 消费者消费消息消费者拉取钱程拉取每个分区的数据,会将分区的消息集包装成一个数据块(FetchedDataChunk)放入分区信息的队列中。而每个队列都对应一个消息流(KafkaStream),消费者客户端选代消息流,实际上是迭代每个数据块中消息集的每条消息。如图3-22所示,一个队列包含多个数据块,每个数据块对应一个分区的消息集,一个消息集包含多条消息。消费者迭代器(ConsumerIterator)封装了迭代获取消息的逻辑,客户端不需要面向数据块、消息集这些内部对象,只需要对消费者迭代器循环获原创 2021-03-26 18:04:11 · 377 阅读 · 7 评论 -
3.4.2 消费者迭代消费消息
3.4.2 消费者迭代消费消息消费者迭代器生成包含消息的迭代器,首先弹出队列的每个数据块,然后获取数据块对应的消息集,最后迭代消息集中的每条消息。客户端迭代的消息是队列的所有数据块,而不是一个数据块。所以在迭代过程中,要确保读取完一个数据块后,接着读取下一个数据块。也就是说,消费者迭代器是:所有数据块通过消息集f!fi成的消息迭代器。下面的伪代码实际上用了两层循环:消费者迭代器实现了Java的Iterator接口,必须重载hasNext()和next()方法。hasNext()方法会用来判断迭代原创 2021-04-16 23:54:58 · 3377 阅读 · 0 评论 -
3.5.1 消费者提交分区偏移量
3.5 消费者提交分区偏移量消费者提交偏移量是为了保存分区的消费进度。因为Kafka保证同一个分区只会分配给消费组中的唯一消费者,所以即使发生再平衡后,分区和消费者的所有权关系发生变化,新消费者也可以接着上一个消费者记录的偏移盘位置继续消费消息。但是消费者即使记录了分区的偏移量,仍然无法解决消息被重复消费的问题。例如,消费者l每隔10秒提交一次偏移量,在10秒时提交的偏移量是100,下一次提交的日们可点是20秒。在20秒之前,消费者l又消费了30条消息,然后消费者l突然挂掉了。由于偏移量现在仍然停留在1原创 2021-03-27 20:57:02 · 224 阅读 · 0 评论 -
3.5.2 提交偏移量到内部主题
3.5.2 提交偏移量到内部主题消费者提交偏移量到Kafka的内部主题,首先要确定连接哪个或者哪些服务端节点。回顾一下,生产者发送消息时会根据分区的主副本分组,和多个节点者rs建立连接;消费者分配多个分区,也要根据分区的主副本分组,和多个节点建立连接。而消费者提交所有分区的偏移量时,实际上只和-个服务端节点建立连接。同样要处理多个分区,为什么普通消息需要多个连接,而偏移量只需要一个连接?如图3-24所示,目标节点指的是分区的主副本节点,我们给出了偏移聋的多种连接方案。(1)如果不同分区的偏移盐写到了不同原创 2021-04-17 09:59:46 · 2974 阅读 · 0 评论 -
3.5.3 连接偏移量管理器
3.5.3 连接偏移量管理器前面我们分析的拉取偏移#方法和提交偏移量’方法,都需要和偏移主-管理器通信。在这之前,消费者需要通过channelToOffsetManager()方法向服务端任意一个节点发送“消费组的协调者请求”(GroupCoordinatorRequest),来获取消费组对应的协调节点,即偏移量管理器(OffsetManager)节点。服务端处理消费组的协调者请求,实际上也是通过查询主题的元数据来完成的。不过和LeaderFinderThread中返回主题元数据,然后还要在客户端继续处理原创 2021-04-17 11:52:44 · 2927 阅读 · 0 评论 -
3.5.4 服务端处理提交偏移量的请求
3.5.4 服务端处理提交偏移量的请求协调节点会将消费者的偏移量提交请交给GroupCoordlnator类的handleCommitOffsets()方法处理,其中参数offsetMetadata表示分配给消费者的所有分区消费进度。相关代码如下:写入偏移消息会调用RepllcaManager.appendMessages()方法,将消息集追加到本地日志文件,并且会把分区和对应的偏移量保存在协调节点的缓存中。目的是:再平衡后如果其他消费者需要读取分区的偏移毡,在连接上协调节点后,可以直接读取缓存,而不原创 2021-04-16 21:32:08 · 2996 阅读 · 2 评论 -
3.5.5 缓存分区的偏移量
3.5.5 缓存分区的偏移量消费者提交自己负责分区的偏移量,除了写入服务端(协调节点)内部主题某个分区的日志文件中,还要把这部分数据保存一份到当前服务端的内存中,这样分区的偏移量保存在了磁盘和内存两个地方。偏移量消息的键由消费组、主题、分区组成(GoupTopicPat1tion),消息的值是分区的偏移盘。查询分区的偏移量时给定GoupTop1cPat1hon,会返回分区对应的偏移盘,即分区当前的消费进度。由于消费者会周期性地提交偏移量,同一个分区在每次提交时都会产生新的偏移盐。比如分区p。在第一次提交原创 2021-04-18 10:51:59 · 3517 阅读 · 2 评论 -
3.6.1 消息消费主流程
3.6 消费者低级API示例上面基于消费者连接器的实现是高级API的使用方法,消费者拉取线程最终通过SiMpleConsul’ler和服务端进行数据传输,底层网络连接采用了同步类型的阻塞通道。虽然SiMpleConsul’ler从名称上看属于“简单”、低级API,但是高级API也会使用这个类。只不过高级API并不会把这个底层的类暴露给消费者客户端应用程序,而低级API则需要直接面对SiMpleConsul’ler类编程。客户端使用低级API消费消息,需要手动指定固定的分区,并且不会利用“消费组向动分配分原创 2021-04-07 20:00:53 · 154 阅读 · 2 评论 -
3.6.2 找出分区的主副本
3.6.2 找出分区的主副本客户端为了获得分区的主副本,可以向任意一个节点发送主题元数据请求(Top"i.cMetadataRequest),因为每个节点都保存了集群所有的主题元数据,而且数据都是一致的。主题元数据包含了多个分区的元数据,而消费者只指定消费特定的分区,所以需要找出对应的分区元数据。第一次获取分区的主副本节点的候选集合是客户端给定的种子节点(a_seedBrokers)。主副本挂掉后,新的候选集合为凡repli.caBrokerS,它来自于第一次调用fi.ndleader()返回分区元数.原创 2021-04-17 07:17:19 · 2981 阅读 · 0 评论 -
3.6.3 获取分区的读取偏移量
3.6.3 获取分区的读取偏移量读取分区的偏移量涉及日志存储,这里我们先给出一些简单的结论(具体细节会在第6章详细分析):一个分区有多个片段文件(Segment),每个片段文件都包含全局有序的片段基准偏移量(segmentBaseOffset)。客户端调用getlastOffset()获取的是每个片段文件的基准偏移量。客户端发送的偏移毡’请求(OffsetRequest)包含的数据是:分区偏移量的请求信息(PartitionOffsetinfo)。这个对象有两个参数:whichTime表示拉取的时间戳.原创 2021-04-17 21:43:54 · 3279 阅读 · 0 评论 -
3.6.4 发送拉取请求并消费消息
3.6.4 发送拉取请求井消费消息消费者使用高级API拉取消息,再平衡后第一次拉取时,从ZK或消费组的协调节点读取一次偏移£10扣,取消息后会更新本地内存partitionMap的拉取状态,后续拉取线程以最新的分区拉取状态构建拉取请求,并不需要再从ZK或协调节点读取偏移量。因为拉取状态每次都会更新,所以新创建的拉取请求也是最新的。低级API也使用类似的方式,第一次读取偏移量通过getlastOffset()从服务端读取,拉取到消息后要更新读取偏移量,下一次拉取时以最近更新的读取偏移量构建拉取请求。低原创 2021-04-18 08:04:15 · 2930 阅读 · 0 评论 -
3.7.1消费者线程模型
3.7小结本意分析了两种消费者API的实现,并重点分析了高级API,下面总结一下高级.API两个重要的概念。####3.7.1消费者线程模型客户端创造基于ZK的消费者连接器,ZK作为共享存储保存了Kafka集群或者客户端的相关信息,比如主题信息、消费者和消费组的关系、分区和消费者的关系、分区的偏移量等。连接器是消费者进程的人口,根据客户端订阅的主题和设置的线程数,从而引入了消费者的线程模型。一个消费者客户端是一个Java进程,消费者可以订阅多个主题,甚至每个主题都可以向定义线程数,消费者实际上是个原创 2021-04-07 20:34:24 · 265 阅读 · 0 评论 -
4.0 新消费者
上一章分析了Scala实现的两种消费者API,新版本的消费者采用Java重新实现。但不管采用什么版本实现,消费者消费消息的主要工作没有太大变化,比如为消费者分配分区、拉取线程拉取消息、客户端消费消息、更新拉取状态、提交偏移量。消息消费相关的基本概念在第3章中已经分析过了,本章首先会比较下面3个概念:消费者API(下文简称“新API”)、旧版本的高级API(下文简称“高级PI”)和新版本的生产者API。消费者的高级API和新API先来复习下旧消费者的高级API示例。客户端创建消费者连接器和消息流列表.原创 2021-04-07 21:50:18 · 150 阅读 · 2 评论