关于Kafka区分请求处理优先级的讨论
所有的讨论都是基于KIP-291展开的。抱歉,这又是一篇没有图的文字。
目前Kafka broker对所有发过来的请求都是一视同仁的,不会区别对待。不管是用于生产消费的PRODUCE和FETCH请求,还是controller端发送的LeaderAndIsr/StopReplica/UpdateMetadata请求,亦或是其他类型的请求也是一样。通常我们这里把PRODUCE/FETCH请求称为数据类请求;把controller发送的那3种请求称为控制类请求或controller类请求——在源码中前者被称为data plane request,后者称为controller plane request。
这种公平处理原则在很多场合下都是不合理的。为什么?简单来说控制类请求具有直接令数据类请求失效的能力。举个例子,如果我有个topic,单分区双副本,其中broker0上保存leader副本,broker1上保存follower副本。当broker0上积压了大量的PRODUCE请求时,此时用户执行了重分区或preferred分区选举将broker1变更成了leader,那么controller会向broker0发送LeaderAndIsr请求告诉它现在是一个follower了,而broker1上的follower已经停止向leader拉取数据(因为它要成为leader了)——此时一个比较尴尬的情形出现了:如果producer的acks设置的是all,那么这些在LeaderAndIsr请求之前积压的PRODUCE请求就无法正常完成——要么一直缓存在purtagory中要么请求超时返回给client。设想一下,如果Kafka能够及时地处理LeaderAndIsr请求,那么这些积压的PRODUCE请求就能立即失败(NOT_LEADER_FOR_PARTITION),马上返回给client。Client不用等到 purgatory中的请求超时,降低了请求的处理时间。即使acks不是all,纵然积压的PRODUCE请求写入本地日志后成功返回,但处理过LeaderAndIsr请求后broker0上副本变为follower,还要执行截断(truncation),因此在client看来这些消息就丢失了。
再举一个例子,同样是在积压大量数据类请求的broker上,如果用户删除了topic,那么StopReplica请求无法及时处理,导致topic无法真正删除,增加了删除topic的延时。
最后还可以举个例子说明对UpdateMetadata的影响。如果UpdateMetadata不能及时处理,broker上保存的就是过期的元数据,当client获取到这些数据时,不管是producer还是consumer都可能无法正常工作,直到获取到最新的元数据信息。
通过上面3个例子可以看出通常情况下我们希望controller类请求的处理优先级要高于数据类请求,这也是社区做KIP-291的初衷 。可喜的是Kafka 2.2正式实现了这个功能,下面我们来看看社区是怎么做的:
其实在KIP-291之前,我也思考过这个问题。当时我提出的想法是这样的:在broker的KafkaRequestHandlerPool中实现一个优先级队列,当controller类请求到达时,它能够”抢占式“地排在处理队列的最前部——这是很自然的想法,所以我本以为KIP-291也是这么实现的,但通篇看下来我尴尬地发现我这个解决思路记录在“Rejected Alternatives"中。这个方案最大的问题在于它无法处理队列已满的情形,即当处理队列已经无法容纳任何新的请求时该如何支持优先处理controller类请求?纵然有优先级队列也无法解决这个问题。
KIP-291是怎么解决的呢?很简单,Kafka重新为controller类请求做了专属的监听器+请求队列+acceptor+processor线程。监听器通过Kafka的listeners和advertised.listeners设置,新的请求队列则专门保存controller类请求,而acceptor和processor线程负责接收网络发送过来的以及处理队列中的controller类请求。我们一个一个说吧。
当前,用户可以在listeners中指定多套监听器,比如PLAINTEXT://kafka1:9092, SSL://kafka1:9093。你其实也可以自定义你的监听器,比如INTERNAL://kafka1:9094。用户可以指定broker端参数inter.broker.listener.name或security.inter.broker.protocol(两个不能同时指定)来设定,同时你还需要在listener.security.protocol.map中指定这个自定义listener使用的安全协议,比如: listener.security.protocol.map=INTERNAL:PLAINTEXT。KIP-291复用了这个设计,如果你设置了inter.broker.listener.name或security.inter.broker.protocol,Kafka会默认使用这个listener专属服务controller类请求。同时社区还引入了一个新的参数:control.plane.listener.name,用来专门让你设置服务controller类请求的监听器名称。这个参数的优先级要高于前面那两个参数,因此还是推荐用户直接设置此参数,比如设置control.plane.listener.name=CONTROLLER,同时更新listener.security.protocol.map,增加CONTROLLER:PLAINTEXT匹配对(假设你用的是PLAINTEXT)。这就是为controller类请求创建监听器的方法。
下面说请求队列和acceptor、processor线程。 其实也不用细说,和现有的设计一模一样,只是默认的队列大小不再是500,而是20,默认的线程数不再是8而是2,因为我们假设controller类请求通常不应该有积压。具体的实现原理有兴趣的话直接读KafkaRequestHandlerPool.scala、RequestChannel.scala和SocketServer.scala源码吧。还需要修改的地方是controller代码,特别是在ControllerChannelManager.scala中增加新的broker时一定要使用controller类请求专属的监听器。
除了以上这些,该KIP也引入了很多监控controller类请求处理的JMX指标,如队列请求数、线程空闲程度等,这些和之前的指标都是一样的,只是仅监控controller plane监听器之用。再说一点,当前Kafka支持动态地调整请求处理线程数。在对请求进行区分处理后,我估计后续也要支持对controller类请求线程数的动态调整吧。
总体来说,将请求做区分处理后对于繁忙Kafka集群将能够更迅速地处理控制类请求,表现为状态的更新更加及时,集群不一致状态窗口将会缩小,同时还提升了整体可用性。目前该KIP还只是对请求做两类处理,也许日后会做一些更加细粒度的区分——比如Metadata请求是否也应该享有更高的优先级处理。
最后还想提一句,KIP-291是我认为近期社区改动影响比较大的两个KIP之一。另一个则是KIP-392——还记得Kafka不能从follower副本读数据的限制吧?这个KIP要打破这个限制!只是目前该KIP还在讨论中,我们后面拭目以待吧。
关于Kafka区分请求处理优先级的讨论的更多相关文章
- kafka学习笔记(五)kafka的请求处理模块
		
概述 现在介绍学习一下kafka的请求处理模块,请求处理模块就是网络请求处理和api处理,这是kafka无论是对客户端还是集群内部都是非常重要的模块.现在我们对他进行源码深入探讨.当我们说到 Kafk ...
 - Kafka设计解析(二十一)关于Kafka幂等producer的讨论
		
转载自 huxihx,原文链接 关于Kafka幂等producer的讨论 众所周知,Kafka 0.11.0.0版本正式支持精确一次处理语义(exactly once semantics,下称EOS) ...
 - 关于Kafka日志留存策略的讨论
		
关于Kafka日志留存(log retention)策略的介绍,网上已有很多文章.不过目前其策略已然发生了一些变化,故本文针对较新版本的Kafka做一次统一的讨论.如果没有显式说明,本文一律以Kafk ...
 - 关于Kafka幂等producer的讨论
		
众所周知,Kafka 0.11.0.0版本正式支持精确一次处理语义(exactly once semantics,下称EOS).Kafka的EOS主要体现在3个方面: 幂等producer:保证发送单 ...
 - Kafka Streams | 流,实时处理和功能
		
1.目标 在我们之前的Kafka教程中,我们讨论了Kafka中的ZooKeeper.今天,在这个Kafka Streams教程中,我们将学习Kafka中Streams的实际含义.此外,我们将看到Kaf ...
 - Kafka处理请求的全流程分析
		
大家好,我是 yes. 这是我的第三篇Kafka源码分析文章,前两篇讲了日志段的读写和二分算法在kafka索引上的应用 今天来讲讲 Kafka Broker端处理请求的全流程,剖析下底层的网络通信是如 ...
 - Kafka资源汇总
		
终于下定决心写一点普及类的东西.很多同学对Kafka的使用很感兴趣.如果你想参与到Kafka的项目开发中,很多资源是你必须要提前准备好的.本文罗列了一些常用的Kafka资源,希望对这些develope ...
 - 【转】apache kafka技术分享系列(目录索引)
		
转自: http://blog.csdn.net/lizhitao/article/details/39499283 估计大神会不定期更新,所以还是访问这个链接看最新的目录list比较好 apa ...
 - kafka的高可用和一致性探究
		
一.kafka基础 本篇文章讨论的kafka版本是目前最新版 0.10.1.0. 1.1 kafka种的KafkaController 所有broker会通过ZooKeeper选举出一个作为Kafka ...
 
随机推荐
- 【翻译】Spark 调优 (Tuning Spark) 中文版
			
由于Spark自己的调优guidance已经覆盖了很多很有价值的点,因此这里直接翻译一份过来.也作为一个积累. Spark 调优 (Tuning Spark) 由于大多数Spark计算任务是在内存中运 ...
 - python 新手常见问题
			
1.python 三元运算符 无,用 if else 2.python 设置代码缩进 全选..然后按tab 3.记录程序运行时间 import time time_start=time.time() ...
 - Spring 拦截器postHandle无法修改Response的原因
			
如果controller跳转至页面,postHandle是没问题的. 如果@ResponseBody注释 或者返回 ResponseEntity,在postHandle拦截器中修改请求头,是无效的. ...
 - gitbook安装与使用,并使用docker部署
			
本文简单介绍如何安装并使用gitbook,最后如何使用docker构建书籍镜像. 1. 前置条件 需要Nodejs环境,安装npm,国内用户再安装cnpm npm install -g cnpm -- ...
 - ES6 与 React
			
Node和NPM/*安装npm*/npm installnpm install <package>npm install -g <package> /*更新安装包*/npm u ...
 - C# string 是不可变的,指什么不可变
			
String 表示文本,即一系列 Unicode 字符.字符串是 Unicode 字符的有序集合,用于表示文本.String 对象是 System.Char 对象的有序集合,用于表示字符串.Strin ...
 - PHP-问题处理验证码无法显示出来
			
1.问题 今天重新安装了ubuntu,PHP,MySQL,Apache,到测试CMS项目时发生一个错误: 验证码无法显示出来. 2.解决: 2.1 使用 phpinfo检查: phpinfo(); 在 ...
 - Android研发中对String的思考(源代码分析)
			
1.经常使用创建方式思考: String text = "this is a test text "; 上面这一句话实际上是运行了三件事 1.声明变量 String text; ...
 - Atitit 酷奇的押金危机  遇到资金链断裂作为创始人应该怎么办
			
Atitit 酷奇的押金危机 遇到资金链断裂作为创始人应该怎么办 遇到对方确实经营不善,资产已经还不了用户的押金怎么办?? 1. 一些重要原则 1 1.1. 二次分配原则 公平原则 1 1.2. ...
 - [C++]Qt程式异常崩溃处理技巧(Win)
			
文章转载来自 http://www.cnblogs.com/lcchuguo/p/5177715.html 作者 lcchuguo https://blog.csdn.net/baid ...