MetadataCache更新
MetadataCache什么时候更新
updateCache方法用来更新缓存的。
发起线程 controller-event-thread
controller选举的时候
| CLASS_NAME | METHOD_NAME | LINE_NUM |
| kafka/controller/KafkaController | sendUpdateMetadataRequest | 1043 |
| kafka/controller/KafkaController | onControllerFailover | 288 |
| kafka/controller/KafkaController | elect | 1658 |
| kafka/controller/KafkaController$Startup$ | process | 1581 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply$mcV$sp | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/metrics/KafkaTimer | time | 32 |
| kafka/controller/ControllerEventManager$ControllerEventThread | doWork | 64 |
| kafka/utils/ShutdownableThread | run | 70 |
启动的时候选举,启动这个动作也是个事件
// KafkaController.scala
case object Startup extends ControllerEvent {
def state = ControllerState.ControllerChange
override def process(): Unit = {
registerSessionExpirationListener()
registerControllerChangeListener()
elect()
}
}
broker启动的时候
| CLASS_NAME | METHOD_NAME | LINE_NUM |
| kafka/controller/KafkaController | sendUpdateMetadataRequest | 1043 |
| kafka/controller/KafkaController | onBrokerStartup | 387 |
| kafka/controller/KafkaController$BrokerChange | process | 1208 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply$mcV$sp | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/metrics/KafkaTimer | time | 32 |
| kafka/controller/ControllerEventManager$ControllerEventThread | doWork | 64 |
| kafka/utils/ShutdownableThread | run | 70 |
topic删除的时候
| CLASS_NAME | METHOD_NAME | LINE_NUM |
| kafka/controller/KafkaController | sendUpdateMetadataRequest | 1043 |
| kafka/controller/TopicDeletionManager | kafka$controller$TopicDeletionManager$$onTopicDeletion | 268 |
| kafka/controller/TopicDeletionManager$$anonfun$resumeDeletions$2 | apply | 333 |
| kafka/controller/TopicDeletionManager$$anonfun$resumeDeletions$2 | apply | 333 |
| scala/collection/immutable/Set$Set1 | foreach | 94 |
| kafka/controller/TopicDeletionManager | resumeDeletions | 333 |
| kafka/controller/TopicDeletionManager | enqueueTopicsForDeletion | 110 |
| kafka/controller/KafkaController$TopicDeletion | process | 1280 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply$mcV$sp | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/metrics/KafkaTimer | time | 32 |
| kafka/controller/ControllerEventManager$ControllerEventThread | doWork | 64 |
| kafka/utils/ShutdownableThread | run | 70 |
topic创建或者修改的时候
| CLASS_NAME | METHOD_NAME | LINE_NUM |
| kafka/controller/ControllerBrokerRequestBatch | updateMetadataRequestBrokerSet | 291 |
| kafka/controller/ControllerBrokerRequestBatch | newBatch | 294 |
| kafka/controller/PartitionStateMachine | handleStateChanges | 105 |
| kafka/controller/KafkaController | onNewPartitionCreation | 499 |
| kafka/controller/KafkaController | onNewTopicCreation | 485 |
| kafka/controller/KafkaController$TopicChange | process | 1237 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply$mcV$sp | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/metrics/KafkaTimer | time | 32 |
| kafka/controller/ControllerEventManager$ControllerEventThread | doWork | 64 |
| kafka/utils/ShutdownableThread | run | 70 |
topic创建这个是从队列中拿到事件再处理的方式
队列是kafka.controller.ControllerEventManager.queue
放入过程如下,本质还是监听zk的path的child的变化:
| CLASS_NAME | METHOD_NAME | LINE_NUM |
| kafka/controller/ControllerEventManager | put | 44 |
| kafka/controller/TopicChangeListener | handleChildChange | 1712 |
| org/I0Itec/zkclient/ZkClient$10 | run | 848 |
| org/I0Itec/zkclient/ZkEventThread | run | 85 |
注册监听器的代码如下:
// class KafkaController
private def registerTopicChangeListener() = {
zkUtils.subscribeChildChanges(BrokerTopicsPath, topicChangeListener)
}
顺带说一下有6个地方订阅了zk的子节点的变化:
- DynamicConfigManager.startup
- registerTopicChangeListener
- registerIsrChangeNotificationListener
- registerTopicDeletionListener
- registerBrokerChangeListener
- registerLogDirEventNotificationListener
处理创建topic事件:
// ControllerChannelManager.scala class ControllerBrokerRequestBatch
def sendRequestsToBrokers(controllerEpoch: Int) {
// .......
val updateMetadataRequest = {
val liveBrokers = if (updateMetadataRequestVersion == 0) {
// .......
} else {
controllerContext.liveOrShuttingDownBrokers.map { broker =>
val endPoints = broker.endPoints.map { endPoint =>
new UpdateMetadataRequest.EndPoint(endPoint.host, endPoint.port, endPoint.securityProtocol, endPoint.listenerName)
}
new UpdateMetadataRequest.Broker(broker.id, endPoints.asJava, broker.rack.orNull)
}
}
new UpdateMetadataRequest.Builder(updateMetadataRequestVersion, controllerId, controllerEpoch, partitionStates.asJava,
liveBrokers.asJava)
}
updateMetadataRequestBrokerSet.foreach { broker =>
controller.sendRequest(broker, ApiKeys.UPDATE_METADATA, updateMetadataRequest, null)
}
// .......
}
topic创建时更新metadata再进一步的过程
构建发送请求事件放入发送队列等待发送线程发送
构建发送请求事件代码如下:
// ControllerChannelManager
def sendRequest(brokerId: Int, apiKey: ApiKeys, request: AbstractRequest.Builder[_ <: AbstractRequest],
callback: AbstractResponse => Unit = null) {
brokerLock synchronized {
val stateInfoOpt = brokerStateInfo.get(brokerId)
stateInfoOpt match {
case Some(stateInfo) =>
stateInfo.messageQueue.put(QueueItem(apiKey, request, callback))
case None =>
warn("Not sending request %s to broker %d, since it is offline.".format(request, brokerId))
}
}
}
调用栈:
| CLASS_NAME | METHOD_NAME | LINE_NUM |
| kafka/controller/ControllerChannelManager | sendRequest | 81 |
| kafka/controller/KafkaController | sendRequest | 662 |
| kafka/controller/ControllerBrokerRequestBatch$$anonfun$sendRequestsToBrokers$2 | apply | 405 |
| kafka/controller/ControllerBrokerRequestBatch$$anonfun$sendRequestsToBrokers$2 | apply | 405 |
| scala/collection/mutable/HashMap$$anonfun$foreach$1 | apply | 130 |
| scala/collection/mutable/HashMap$$anonfun$foreach$1 | apply | 130 |
| scala/collection/mutable/HashTable$class | foreachEntry | 241 |
| scala/collection/mutable/HashMap | foreachEntry | 40 |
| scala/collection/mutable/HashMap | foreach | 130 |
| kafka/controller/ControllerBrokerRequestBatch | sendRequestsToBrokers | 502 |
| kafka/controller/PartitionStateMachine | handleStateChanges | 105 |
| kafka/controller/KafkaController | onNewPartitionCreation | 499 |
| kafka/controller/KafkaController | onNewTopicCreation | 485 |
| kafka/controller/KafkaController$TopicChange | process | 1237 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply$mcV$sp | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/controller/ControllerEventManager$ControllerEventThread$$anonfun$doWork$1 | apply | 53 |
| kafka/metrics/KafkaTimer | time | 32 |
| kafka/controller/ControllerEventManager$ControllerEventThread | doWork | 64 |
| kafka/utils/ShutdownableThread | run | 70 |
发送线程发送请求:
代码如下:
// ControllerChannelManager.scala class RequestSendThread
override def doWork(): Unit = {
def backoff(): Unit = CoreUtils.swallowTrace(Thread.sleep(100))
val QueueItem(apiKey, requestBuilder, callback) = queue.take()
//...
while (isRunning.get() && !isSendSuccessful) {
// if a broker goes down for a long time, then at some point the controller's zookeeper listener will trigger a
// removeBroker which will invoke shutdown() on this thread. At that point, we will stop retrying.
try {
if (!brokerReady()) {
isSendSuccessful = false
backoff()
}
else {
val clientRequest = networkClient.newClientRequest(brokerNode.idString, requestBuilder,
time.milliseconds(), true)
clientResponse = NetworkClientUtils.sendAndReceive(networkClient, clientRequest, time)
isSendSuccessful = true
}
} catch {
case e: Throwable => // if the send was not successful, reconnect to broker and resend the message
warn(("Controller %d epoch %d fails to send request %s to broker %s. " +
"Reconnecting to broker.").format(controllerId, controllerContext.epoch,
requestBuilder.toString, brokerNode.toString), e)
networkClient.close(brokerNode.idString)
isSendSuccessful = false
backoff()
}
}
// ......
}
响应线程
| CLASS_NAME | METHOD_NAME | LINE_NUM |
| kafka/server/MetadataCache | kafka$server$MetadataCache$$addOrUpdatePartitionInfo | 150 |
| kafka/utils/CoreUtils$ | inLock | 219 |
| kafka/utils/CoreUtils$ | inWriteLock | 225 |
| kafka/server/MetadataCache | updateCache | 184 |
| kafka/server/ReplicaManager | maybeUpdateMetadataCache | 988 |
| kafka/server/KafkaApis | handleUpdateMetadataRequest | 212 |
| kafka/server/KafkaApis | handle | 142 |
| kafka/server/KafkaRequestHandler | run | 72 |
线程信息: kafka-request-handler-5
靠 partitionMetadataLock读写锁控制cache数据的读取与写入的线程安全。元数据信息在发送请求中已经构造好了。此处还涉live broker的更新等。
应该还要补充:leader切换和isr变化等
MetadataCache更新的更多相关文章
- kafka-clients 1.0 高阶API消费消息(未完)
消费消息的请求(按序) org/apache/kafka/common/requests/RequestHeader org/apache/kafka/common/requests/ApiVersi ...
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- 使用TSQL查询和更新 JSON 数据
JSON是一个非常流行的,用于数据交换的文本数据(textual data)格式,主要用于Web和移动应用程序中.JSON 使用“键/值对”(Key:Value pair)存储数据,能够表示嵌套键值对 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新
因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...
- iOS热更新-8种实现方式
一.JSPatch 热更新时,从服务器拉去js脚本.理论上可以修改和新建所有的模块,但是不建议这样做. 建议 用来做紧急的小需求和 修复严重的线上bug. 二.lua脚本 比如: wax.热更新时,从 ...
- 【.net 深呼吸】程序集的热更新
当一个程序集被加载使用的时候,出于数据的完整性和安全性考虑,程序集文件(在99.9998%的情况下是.dll文件)会被锁定,如果此时你想更新程序集(实际上是替换dll文件),是不可以操作的,这时你得把 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)
开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 任务调度系统界面 http: ...
随机推荐
- 【Floyd算法+贪心】 travel 计蒜客 - 45275
题目: 有 n 个景点,从一个景点 i 旅行到另一个景点 j 要花费 Ai,j=Aj,i(n≤100),现在给出由 m(≤1e5) 个景点的组成序列 A,求:在所有 "有子序列 A 的序列中 ...
- 我在 GitHub 上发现了一款骚气满满的字体!
本文转自量子位,作者栗体,如有侵权,则可删除. github字体 这个字体叫 Leon Sans,表面看去平平无奇. 但事实上,它并不是普通的字体,体内蕴藏着魔力. github字体1 Leon Sa ...
- w10查看wifi密码
1.选择网络和Internet设置 右键单击网络连接图标,选择“打开网络和Internet设置”. 2.选择网络和共享中心
- Java环境变量设置:Path、CLASSPATH、JAVA_HOME的作用分别是什么?
1.Path 作用是指定命令搜索路径,在i命令行下面执行命令如javac编译java程序时,它会到PATH变量所指定的路径中查找百看是否能找到相应的命令程序. 需要把jdk安装目录下的b ...
- HTML学习汇总
HTML学习大汇总 (1)HTML概述 Html(超文本标记语言): 用文字来描述的标签语言,用文字来描述网页的一种语言. HTML是 HyperText Mark-up Language 的首字母简 ...
- 算法数据结构 | 只要30行代码,实现快速匹配字符串的KMP算法
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法数据结构专题的第29篇文章,我们来聊一个新的字符串匹配算法--KMP. KMP这个名字不是视频播放器,更不是看毛片,它其实是由Kn ...
- PHP md5_file() 函数
实例 计算文本文件 "test.txt" 的 MD5 散列: <?php高佣联盟 www.cgewang.com$filename = "test.txt" ...
- 畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 畅购商城(一):环境搭建 畅购商 ...
- 从入门到熟悉HTTPS的9个问题
原文:bestswifter https://juejin.im/post/58c5268a61ff4b005d99652a Q1: 什么是 HTTPS? BS: HTTPS 是安全的 HTTP ...
- C++ 中可调用的且有函数功能的东东
第一个:函数 其实函数在声明的时候都有个名字: 这个名字可以看作是是指针,将其直接赋值给函数指针 也可以看作是可取指的对其& 再赋值给函数指针 第二个:函数指针 通过其被赋值的方式 ...