Jafka源代码分析——Processor

Jafka Acceptor接收到客户端请求并建立连接后,Acceptor会将Socket连接交给Processor进行处理。Processor通过以下的处理步骤进行客户端请求的处理:

1. 读取客户端请求。

2. 根据客户端请求类型的不同,调用相应的处理函数进行处理。

Processor读取客户端请求是一个比较有意思的事情,需要考虑两个方面的事情:第一,请求规则(Processor需要按照一定的规则进行请求的解析);第二,如何确定一次请求的读取已经结束(因为是非阻塞连接,非常有可能第一次读操作读取了请求的一部分数据,第二次到第N次读取才能把整个客户端请求读取完整)。下面我们详细解析一下客户端请求的格式。客户端请求首先包含一个int,该int指明本次客户端请求的大小(size)。随后,请求包含一个两个byte(short)的请求类型(请求类型包括:CreaterRequest、DeleterRequest、FetchRequest、MultiFetchRequest、MultiProducerRequest、OffsetRequest和ProducerRequest。然后每种请求类型有固定的格式。下图具体说明了ProducerRequest的格式:

知道了上面的格式之后,问题二(如何确定一次请求已经读取完成)就很容易解决了。首先为“请求长度”分配一个4byte的ByteBuffer,直到该Buffer读满,否则说明长度一直没有读取完成。“请求长度”读取完成后,为请求分配一个“请求长度”大小的ByteBuffer,直到该Buffer读满则说明一次请求读取完成。读取完成后,根据“请求类型”调用相应的处理函数(Handler)进行处理。在jafka中,上述的两个Buffer在类BoundedByteBufferReceive中进行声明和管理。Processor接收到Acceptor分配的socket连接后,会为socke连接建立一个BoundedByteBufferReceive并将其与socket连接进行绑定。每当该socket连接“可读”时,将BoundedByteBufferReceive拿出来从上次读取的基础上继续读取,直到一次请求彻底读取完成,具体过程如下面代码(Processor.read)所示:

private void read(SelectionKey key) throws IOException {
SocketChannel socketChannel = channelFor(key);
Receive request = null;
request = new BoundedByteBufferReceive(maxRequestSize);
key.attach(request);
} else {
request = (Receive) key.attachment();
}
int read = request.readFrom(socketChannel);
stats.recordBytesRead(read);
if (read < 0) {
close(key);
} else if (request.complete()) {
Send maybeResponse = handle(key, request);
key.attach(null);
// if there is a response, send it, otherwise do nothing
if (maybeResponse != null) {
key.attach(maybeResponse);
key.interestOps(SelectionKey.OP_WRITE);
}
} else {
// more reading to be done
key.interestOps(SelectionKey.OP_READ);
getSelector().wakeup();
if (logger.isTraceEnabled()) {
logger.trace("reading request not been done. " + request);
}
}
}

BoundedByteBufferReceive.readFrom的实现具体如下:主要是申请两个Buffer并不断的读取数据。

public int readFrom(ReadableByteChannel channel) throws IOException {
        expectIncomplete();
        int read = 0;
        if (sizeBuffer.remaining() > 0) {
            read += Utils.read(channel, sizeBuffer);
        }
        if (contentBuffer == null && !sizeBuffer.hasRemaining()) {
            sizeBuffer.rewind();
            int size = sizeBuffer.getInt();
            if (size <= 0) {
                throw new InvalidRequestException(...);
            }
            if (size > maxRequestSize) {
                final String msg = "Request of length %d is not valid, it is larger than the maximum size of %d bytes.";
                throw new InvalidRequestException(format(msg, size, maxRequestSize));
            }
            contentBuffer = byteBufferAllocate(size);
        }
        //
        if (contentBuffer != null) {
            read = Utils.read(channel, contentBuffer);
            //
            if (!contentBuffer.hasRemaining()) {
                contentBuffer.rewind();
                setCompleted();
            }
        }
        return read;
    }

读取完成后,Processor会解析“请求类型”,根据请求类型的不同调用不同的Handler进行相应请求的处理。

Jafka源代码分析——Processor,布布扣,bubuko.com

时间: 2024-10-06 01:52:34

Jafka源代码分析——Processor的相关文章

Jafka源代码分析——网络架构

在kafka中,每一个broker都是一个服务器.按照一般理解,服务器就是一个SocketServer,其不断接收用户的请求并进行处理.在Java中进行网络连接有两种方式一种为阻塞模式一种为非阻塞模式.Jafka采用非阻塞模式进行网络通讯.在Java的非阻塞模式中,建立socket server的一般流程如下: 1.启动ServerSocketChannel并将其绑定到特定的端口. 2.将ServerSocketChannel以及其感兴趣的操作注册到Selector,在这里感兴趣的操作是Acce

Jafka源代码分析——随笔

Kafka是一个分布式的消息中间件,可以粗略的将其划分为三部分:Producer.Broker和Consumer.其中,Producer负责产生消息并负责将消息发送给Kafka:Broker可以简单的理解为Kafka集群中的每一台机器,其负责完成消息队列的主要功能(接收消息.消息的持久化存储.为Consumer提供消息.消息清理.....):Consumer从Broker获取消息并进行后续的操作.每个broker会有一个ID标识,该标识由人工在配置文件中配置. Kafka中的消息隶属于topic

Jafka源代码分析——LogManager

在Kafka中,LogManager负责管理broker上所有的Log(每一个topic-partition为一个Log).通过阅读源代码可知其具体完成的功能如下: 1. 按照预设规则对消息队列进行清理. 2. 按照预设规则对消息队列进行持久化(flush操作). 3. 连接ZooKeeper进行broker.topic.partition相关的ZooKeeper操作. 4. 管理broker上所有的Log. 下面一一对这些功能的实现进行详细的解析. 一.对于Log的管理 LogManager包

Jafka来源分析——Processor

Jafka Acceptor接受client而建立后的连接请求,Acceptor会将Socket连接交给Processor进行处理.Processor通过下面的处理步骤进行client请求的处理: 1. 读取client请求. 2. 依据client请求类型的不同,调用对应的处理函数进行处理. Processor读取client请求是一个比較有意思的事情,须要考虑两个方面的事情:第一,请求规则(Processor须要依照一定的规则进行请求的解析).第二,怎样确定一次请求的读取已经结束(由于是非堵

Kafka SocketServer源代码分析

Kafka SocketServer源代码分析 标签: kafka 本文将详细分析Kafka SocketServer的相关源码. 总体设计 Kafka SocketServer是基于Java NIO来开发的,采用了Reactor的模式,其中包含了1个Acceptor负责接受客户端请求,N个Processor负责读写数据,M个Handler来处理业务逻辑.在Acceptor和Processor,Processor和Handler之间都有队列来缓冲请求. kafka.network.Accepto

Android init源代码分析(1)概要分析

功能概述 init进程是Android内核启动的第一个进程,其进程号(pid)为1,是Android系统所有进程的祖先,因此它肩负着系统启动的重要责任.Android的init源代码位于system/core/init/目录下,伴随Android系统多个版本的迭代,init源代码也几经重构. 目前Android4.4源代码中,init目录编译后生成如下Android系统的三个文件,分别是 /init /sbin/ueventd-->/init /sbin/watchdogd-->/init 其

Java中arraylist和linkedlist源代码分析与性能比較

Java中arraylist和linkedlist源代码分析与性能比較 1,简单介绍 在java开发中比較经常使用的数据结构是arraylist和linkedlist,本文主要从源代码角度分析arraylist和linkedlist的性能. 2,arraylist源代码分析 Arraylist底层的数据结构是一个对象数组.有一个size的成员变量标记数组中元素的个数,例如以下图: * The array buffer into which the elements of the ArrayLis

转:RTMPDump源代码分析

0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://.也提供 Android 版本. 最近研究了一下它内部函数调用的关系. 下面列出几个主要的函数的调用关系. RTMPDump用于下载RTMP流媒体的函数Download: 用于建立网络连接(NetConnect)的函数Connect: 用于建立网络流(NetStream)的函数 rtmpdump源代码

pomelo源代码分析(一)

千里之行始于足下,一直说想了解pomelo,对pomelo有兴趣,但一直迟迟没有去碰,尽管对pomelo进行源代码分析,在网络上肯定不止我一个,已经有非常优秀的前辈走在前面,如http://golanger.cn/,在阅读Pomelo代码的时候,已经连载到了11篇了,在我的源代码分析參考了该博客,当然,也会添?我对pomelo的理解,借此希望能提高一下自己对node.js的了解和学习一些优秀的设计. 开发环境:win7 调试环境:webstorm5.0 node.js版本号:v0.8.21 源代