Kafka network Processor

SocketServer.Processor

override def run() {
startupComplete()
try {
while (isRunning) {
try {
// 从connetions queue 中取出 New connection 配置相关信息(register OP_READ),初始化配置
configureNewConnections()
//处理所有响应client的 io write
//(request -> process -> response queue -> queue poll -> record metrics
// -> write NetworkInterface)
processNewResponses()
//查询就绪的Channel OP_READ 事件
poll()
//处理客户端请求,添加到request task 到queue
processCompletedReceives()
//处理已经完成的发送
processCompletedSends()
//处理client 断开
processDisconnected()
} catch {
case e: Throwable => processException("Processor got uncaught exception.", e)
}
}
} finally {
debug("Closing selector - processor " + id)
swallowError(closeAll())
shutdownComplete()
}
}
client request process
class KafkaRequestHandler(id: Int,
brokerId: Int,
val aggregateIdleMeter: Meter,
val totalHandlerThreads: Int,
val requestChannel: RequestChannel,
apis: KafkaApis,
time: Time) extends Runnable with Logging {
this.logIdent = "[Kafka Request Handler " + id + " on Broker " + brokerId + "], "
private val latch = new CountDownLatch() def run() {
while(true) {
val startSelectTime = time.nanoseconds
//从request queue 取出 task
val req = requestChannel.receiveRequest()
val endTime = time.nanoseconds
val idleTime = endTime - startSelectTime
aggregateIdleMeter.mark(idleTime / totalHandlerThreads) req match {
case RequestChannel.ShutdownRequest =>
debug(s"Kafka request handler $id on broker $brokerId received shut down command")
latch.countDown()
return //client reqeust
case request: RequestChannel.Request =>
try {
request.requestDequeueTimeNanos = endTime
trace(s"Kafka request handler $id on broker $brokerId handling request $request")
//KafkaApis api handle, client 请求处理逻辑
apis.handle(request)
} catch {
case e: FatalExitError =>
latch.countDown()
Exit.exit(e.statusCode)
case e: Throwable => error("Exception when handling request", e)
} finally {
request.releaseBuffer()
} case null => // continue
}
}
}

index file

文件i/o的读操作,会先向文件设备发起读请求,然后驱动把请求要读的数据读取到文件的缓冲区中,这个缓冲区位于内核,然后再把这个缓冲区中的数据复制到程序虚拟地址空间中的一块区域中。

文件i/o的写操作,会向文件设备发起写请求,驱动把要写入的数据复制到程序的缓冲区中,位于用户空间,然后再把这个缓冲区的数据复制到文件的缓冲区中。

内存映射文件,是把位于硬盘中的文件看做是程序地址空间中一块区域对应的物理存储器,文件的数据就是这块区域内存中对应的数据,读写文件中的数据,直接对这块区域的地址操作,就可以,减少了内存复制的环节。

内存映射文件比起文件I/O操作,效率要高,而且文件越大,体现出来的差距越大。

index file 采用 mmap 提升效率:

abstract class AbstractIndex[K, V](@volatile var file: File, val baseOffset: Long,
val maxIndexSize: Int = -, val writable: Boolean) extends Logging {
@volatile
protected var mmap: MappedByteBuffer = {
val newlyCreated = file.createNewFile()
val raf = if (writable) new RandomAccessFile(file, "rw") else new RandomAccessFile(file, "r")
try {
/* 是否预先分配 memeory */
if(newlyCreated) {
if(maxIndexSize < entrySize)
throw new IllegalArgumentException("Invalid max index size: " + maxIndexSize)
raf.setLength(roundDownToExactMultiple(maxIndexSize, entrySize))
} /* 内存映射文件 */
val len = raf.length()
val idx = {
if (writable)
raf.getChannel.map(FileChannel.MapMode.READ_WRITE, , len)
else
raf.getChannel.map(FileChannel.MapMode.READ_ONLY, , len)
}
/* 设置 position 位置 */
if(newlyCreated)
idx.position()
else
idx.position(roundDownToExactMultiple(idx.limit(), entrySize))
idx
} finally {
CoreUtils.swallow(raf.close())
}
}
}

index采用稀疏索引,减少占用空间:

@nonthreadsafe
class LogSegment(val log: FileRecords,
val index: OffsetIndex,
val timeIndex: TimeIndex,
val txnIndex: TransactionIndex,
val baseOffset: Long,
val indexIntervalBytes: Int,
val rollJitterMs: Long,
time: Time) extends Logging {
@nonthreadsafe
def append(firstOffset: Long,
largestOffset: Long,
largestTimestamp: Long,
shallowOffsetOfMaxTimestamp: Long,
records: MemoryRecords): Unit = {
 ...
// 计算是否将索引写入index文件
if(bytesSinceLastIndexEntry > indexIntervalBytes) {
index.append(firstOffset, physicalPosition)
timeIndex.maybeAppend(maxTimestampSoFar, offsetOfMaxTimestamp)
bytesSinceLastIndexEntry =
}
bytesSinceLastIndexEntry += records.sizeInBytes
}
}
}

kafka Network的更多相关文章

  1. kafka.network.AbstractServerThread中的线程协作机制

    这个虚类是kafka.network.Acceptor和kafka.network.Processor的父类,提供了一个抽象的Sever线程. 它的有趣之处在于为子类的启动和停止提供了线程间的协作机制 ...

  2. Kafka Network层解析,还是有人把它说清楚了

    我们知道kafka是基于TCP连接的.其并没有像很多中间件使用netty作为TCP服务器.而是自己基于Java NIO写了一套. 几个重要类 先看下Kafka Client的网络层架构. 本文主要分析 ...

  3. kafka.network.SocketServer分析

    当Kafka启动时,会启动这个SocketServer来接收客户端的连接,处理客户端请求,发送响应. 这个类的注释说明了这个socket server的结构 /** * An NIO socket s ...

  4. kafka集群安装部署

    kafka集群安装 使用的版本 系统:centos6.5 centos6.7 jdk:1.7.0_79 zookeeper:3.4.9 kafka:2.10-0.10.1.0 一.环境准备[只列,不具 ...

  5. Kafka设计解析(三)- Kafka High Availability (下)

    本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/06/08/KafkaColumn3 摘要 本文在上篇文章基础上,更加深入讲解了Kafka的HA机 ...

  6. 【原创】Kakfa network包源代码分析

    kafka.network包主要为kafka提供网络服务,通常不包含具体的逻辑,都是一些最基本的网络服务组件.其中比较重要的是Receive.Send和Handler.Receive和Send封装了底 ...

  7. Flume+Kafka+Strom基于伪分布式环境的结合使用

    目录: 一.Flume.Kafka.Storm是什么,如何安装? 二.Flume.Kafka.Storm如何结合使用? 1) 原理是什么? 2) Flume和Kafka的整合  3) Kafka和St ...

  8. kafka监控系统

    Metrics-Java版的指标度量工具之一 Metrics-Java版的指标度量工具之二 JAVA Metrics 度量工具使用介绍1 JAVA Metrics度量工具 - Metrics Core ...

  9. kafka单节点部署无法访问问题解决

    场景:在笔记本安装了一台虚拟机, 在本地的虚拟机上部署了一个kafka服务: 写了一个测试程序,在笔记本上运行测试程序,访问虚拟机上的kafka,报如下异常: 2015-01-15 09:33:26 ...

随机推荐

  1. 起步wex5 谷歌浏览器兼容性问题,CheckBox不显示

  2. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  3. vue 使用v-html指令渲染的富文本无法修改样式的解决方法

    最近的vue项目中遇到的问题:v-html渲染的富文本,无法在样式表中修改样式 解决方法: 把需要添加或重置的样式单独放在一个style标签里, 定义为全局样式,代码如下: <style> ...

  4. Spring WebFlux 要革了谁的命?

    Spring WebFlux 要革了谁的命?  mp.weixin.qq.com 托梦 Java国王昨晚做了一个梦. 梦中有个白胡子老头儿,颇有仙风道骨, 告诉他说:“你们Java啊,实在是太弱了,连 ...

  5. [Sdoi2017]新生舞会(分数规划+费用流)

    题解:二分答案mid,然后将每个位置看成a-b*mid,然后由于是n个男生和n个女生匹配,每个人搭配一个cp,于是有点类似于https://www.lydsy.com/JudgeOnline/prob ...

  6. showdoc app接口文档编写利器

    通过朋友介绍,才知道有这么好的一个在线接口编写文档开源项目,非常感谢原作者的贡献 ShowDoc介绍 关于ShowDoc的介绍,请访问:http://blog.star7th.com/2015/11/ ...

  7. palacehoder的自定义样式【输入框input /文本域textarea】

    7.palacehoder的自定义样式[输入框input /文本域textarea] 因为每个浏览器的CSS选择器都有所差异,所以需要针对每个浏览器做单独的设定(可以在冒号前面写input和texta ...

  8. codeforces-1142 (div1)

    div1真难,现在就是后悔, 非常后悔 A.显然如果我们知道起点和终点是哪两个点,我们可以算出距离通过b / gcd(a,b)的方式求出需要走几步的. 并且数据范围似乎也允许我们这么做,所以直接枚举取 ...

  9. kubernetes 核心技术概念(二)之 volume namespace annoation

    volume k8s通过数据卷来提供pod数据的持久化,k8s的数据卷是对docker数据卷的扩展,k8s的数据卷是pod级别的,用来实现pod中容器的文件共享 volume是pod中能被多个容器访问 ...

  10. C语言的函数指针数组(好绕啊~看完这篇估计就通关了)

    转自https://www.cnblogs.com/chr-wonder/p/5168858.html int *(*p(int))[3] 今天有人问这个是啥?我一看直接就懵逼了…… 下面做一些简单的 ...