MirrorMakerWorker分析

是整个同步机制的主入口,主要组织的逻辑有:

  • 配置数据的传入与处理,ConsumerConfig对象的构建
  • 度量对象的准备,定时上报的度量数据收集线程的定义与启动
  • CompactConsumerFetcherManager实例的创建与startConnections
  • 根据fetchNum创建KafkaConnector实例,KafkaConnector实例中会关联CompactConsumerFetcherManager实例
  • 添加Helix Controller
  • 添加优雅关闭的钩子
  • 构造producer的config producerProps
  • 根据维护KafkaConnector实例的connectorMap来创建MirrorMakerThread实例并启动
  • 通过shutdownLatch: CountDownLatch来等待关闭退出main方法

与Helix关联的地方

实现HelixWorkerOnlineOfflineStateModelFactory和OnlineOfflineStateModel,OnlineOfflineStateModel可以理解成是一个监听器。实例在上下线切换时可以监听到。

helixZkManager = HelixManagerFactory.getZKHelixManager(helixClusterName, instanceId, InstanceType.PARTICIPANT, zkServer)
val stateMachineEngine: StateMachineEngine = helixZkManager.getStateMachineEngine()
// register the MirrorMaker worker
val stateModelFactory = new HelixWorkerOnlineOfflineStateModelFactory(instanceId, fetchNum, connectorMap)
stateMachineEngine.registerStateModelFactory("OnlineOffline", stateModelFactory)
helixZkManager.connect()
helixAdmin = helixZkManager.getClusterManagmentTool
class HelixWorkerOnlineOfflineStateModelFactory(final val instanceId: String, final val fetchNum: Int,
final val connectorMap: ConcurrentHashMap[String, KafkaConnector]) extends StateModelFactory[StateModel] { override def createNewStateModel(partitionName: String) = new OnlineOfflineStateModel(instanceId, connectorMap) // register mm instance
class OnlineOfflineStateModel(final val instanceId: String, final val connectors: ConcurrentHashMap[String, KafkaConnector]) extends StateModel { def onBecomeOnlineFromOffline(message: Message, context: NotificationContext) = {
// add topic partition on the instance
connectorMap.get(getFetcherId(message.getResourceName, message.getPartitionName.toInt)).addTopicPartition(message.getResourceName, message.getPartitionName.toInt)
} def onBecomeOfflineFromOnline(message: Message, context: NotificationContext) = {
// delete topic partition on the instance
connectorMap.get(getFetcherId(message.getResourceName, message.getPartitionName.toInt)).deleteTopicPartition(message.getResourceName, message.getPartitionName.toInt)
} def onBecomeDroppedFromOffline(message: Message, context: NotificationContext) = {
// do nothing
} private def getFetcherId(topic: String, partitionId: Int): String = {
"" + Utils.abs(31 * topic.hashCode() + partitionId) % fetchNum
}
} }

run方法逻辑

  • 通过KafkaConnector拿到KafkaStream,通过KafkaStream拿到ConsumerIterator
  • 在没有关闭时,一直迭代ConsumerIterator
  • 拿到迭代器中的数据,就是取到的消息(为什么迭代器中能一直有消息,因为这样反推iter-->KafkaStream-->KafkaConnector+Queue-->PartitionTopicInfo-->fetcherManager.partitionAddMap-->fetcherManager.partitionInfoMap-->fetcherManager.createFetcherThread-->CompactConsumerFetcherThread.partitionInfoMap-->CompactConsumerFetcherThread.processPartitionData-->CompactConsumerFetcherThread.doWork-->ShutdownableThread.run//spin)
  • 经过MirrorMakerMessageHandler处理消息形成ProducerRecord数组实例,主要是分区对齐
  • 用producer发到目标集群
  • 用maybeFlushAndCommitOffsets方法flush并提交offset
  • 真正commit offset的动作由自行实现的KafkaConnector完成,记录在ZK上,提交是定时提交

CompactConsumerFetcherThread分析

概述

CompactConsumerFetcherThread是继承自Kafka提供的ShutdownableThreadShutdownableThread内部会在isRunning标志位ok的情况下以spin的形式一直调用doWork方法。

  override def run(): Unit = {
info("Starting ")
try{
while(isRunning.get()){
doWork()
}
} catch{
case e: Throwable =>
if(isRunning.get())
error("Error due to ", e)
}
shutdownLatch.countDown()
info("Stopped ")
}

doWork方法分析

  • 锁定partitionMapLock
  • 锁定updateMapLock
  • 将partitionAddMap中的数据放到partitionMap,然后清空partitionAddMap
  • 将partitionDeleteMap中的数据从partitionMap中移除并移除fetcherLagStats中对应的stat,然后清空partitionDeleteMap
  • 迭代partitionMap将需要拉取的topic、partition、fetchoffset、fetchsize等信息加入fetchRequestBuilder
  • 用fetchRequestBuilder构造出FetchRequest实例
  • 如果fetchRequest.requestInfo.isEmpty是空的,那么等待fetchBackOffMs
  • 对于两次拉取间隔是否过大做日志输出(DUMP_INTERVAL_MS = 5 * 60 * 1000)
  • processFetchRequest 处理拉的请求

processFetchRequest方法分析

当doWork方法准备好了FetchRequest实例就要靠processFetchRequest方法来拉数据给partitionInfoMap中的PartitionTopicInfo实例中的队列了。简单过程如下:

  • 迭代响应中的每条数据,按每个分区维度处理
  • 拿到消息
  • 根据拿到的消息算出下一次的new offset,并更新到partitionMap中
  • 更新度量信息,计算堆积
  • 将取到的消息在PartitionTopicInfo实例中放入队列。 PartitionTopicInfo实例的队列来自Connect中的构造KafkaStream实例时传递的同一个队列。 这样能打通连接器和stream

uReplicator实现分析的更多相关文章

  1. 消息中间件选型分析——从Kafka与RabbitMQ的对比来看全局

    一.前言 消息队列中间件(简称消息中间件)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成.通过提供消息传递和消息排队模型,它可以在分布式环境下提供应用解耦 ...

  2. 消息中间件选型分析:从 Kafka 与 RabbitMQ 的对比看全局

    本文转载自消息中间件选型分析:从 Kafka 与 RabbitMQ 的对比看全局 前言 消息队列中间件(简称消息中间件)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布 ...

  3. alias导致virtualenv异常的分析和解法

    title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...

  4. 火焰图分析openresty性能瓶颈

    注:本文操作基于CentOS 系统 准备工作 用wget从https://sourceware.org/systemtap/ftp/releases/下载最新版的systemtap.tar.gz压缩包 ...

  5. 一起来玩echarts系列(一)------箱线图的分析与绘制

    一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...

  6. 应用工具 .NET Portability Analyzer 分析迁移dotnet core

    大多数开发人员更喜欢一次性编写好业务逻辑代码,以后再重用这些代码.与构建不同的应用以面向多个平台相比,这种方法更加容易.如果您创建与 .NET Core 兼容的.NET 标准库,那么现在比以往任何时候 ...

  7. UWP中新加的数据绑定方式x:Bind分析总结

    UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...

  8. 查看w3wp进程占用的内存及.NET内存泄露,死锁分析

    一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...

  9. ZIP压缩算法详细分析及解压实例解释

    最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...

随机推荐

  1. MeshLab中插件的添加过程

    MeshLab中主要插件类型有 filter plugins, i/o plugins, edit plugins,这些插件实现了MeshLab的大部分功能.新加入的插件命名规则最好也遵循规范,可命名 ...

  2. tcpick

    tcpick 是一款基于文本的嗅探器,能追踪,重组和重排tcp流.

  3. ADO数据库编程详解(C++)----初级入门篇

    一.概述 ADO即Microsoft ActiveXData Object,是Microsoft继ODBC之后,基于OLE DB技术的一种数据库操作技术,使您能够编写通过 OLE DB提供者对在数据库 ...

  4. MVC下c#对接微信公众平台开发者模式

    在ashx文件中进行HttpContext的处理: using System; using System.Collections.Generic; using System.Linq; using S ...

  5. cms-最近更新

    在这一讲中有几个很重要的地方需要注意: 1.在查询帖子的时候需要把帖子类型id带到帖子类型表中把类型查询出来 2.在字帖子查询语句中用limt限制查询那个阶段的帖子 3.在界面显示的时候需要用到字符串 ...

  6. 一、Web 如何工作的

    平常我们在浏览器中输入一个网址,随即看到一个页面,这个过程是怎样实现的呢?下面用一幅图来说明: 整个流程如下: 1.域名解析  浏览器会解析域名对应的IP地址 PS:DNS服务器的知识 2.建立TCP ...

  7. 毛毛虫组【Beta】Scrum Meeting 2

    第二天 日期:2019/6/24 前言 第二次会议: 时间:6月24日 地点:教10-503 内容:此次会议主要是进一步完善系统,分配进行文档的准备工作. 1.1 今日完成任务情况以及遇到的问题. 今 ...

  8. 高阶函数 -------JavaScript

    高阶函数 本文摘要:http://www.liaoxuefeng.com/ JavaScript的函数其实都指向某个变量.既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作 ...

  9. Java异常处理的9个最佳实践

    无论你是新手还是资深程序员,复习下异常处理的实践总是一件好事,因为这能确保你与你的团队在遇到问题时能够处理得了它. 在 Java 中处理异常并不是一件易事.新手觉得处理异常难以理解,甚至是资深开发者也 ...

  10. c++中的结构化语句 判断语句if 分支语句switch 循环语句 while 和 do while 循环语句for的使用

    作业1: 使用if语句,根据1~7的数字,输出今天是星期几?的程序. 方法一,直接使用单独的if语句 #include <iostream> using namespace std; in ...