【网络核心层篇】-KafkaChannel-网络读写底层实现

KafkaChannel作为Kafka的网络通信底层类,封装了SocketChannel和Authenticator,处理网络读写。它使用nio selector模型,通过缓冲区解决TCP粘包拆包问题。在读写操作中,KafkaChannel会分配缓冲区并根据消息长度进行读写。setSend方法设置发送数据,NetworkSend构建消息头和体,write方法实际发送数据,read方法接收数据。虽然提供了maxReceiveSize校验,但在实际使用中未受限。
摘要由CSDN通过智能技术生成
1.KafkaChannel简述

KafkaChannel是对SocketChannel的封装,是Kafka中负责网络读写的最底层类。封装了SocketChannel,还封装了Kafka自己的认证器Authenticator。屏蔽Kafka的上层逻辑,来看KafkaChannel是如何设计的。

KafkaChannel网络读写模型:
在这里插入图片描述
Kafka-client是nio selector模型的网络通信,自然KafkaChannel读写也是面向缓冲区的。KafkaChannel的写之前会向内存池开辟堆外内存,作为写缓冲区,缓冲区承载数据,缓冲区的结构是头部使用4个byte的int类型表示该缓冲区长度,头部后面为写入的实际数据。写的时候,将写缓冲区写入与指定node建立的SocketChannel。

读的之前,同样先回申请开辟一个读缓冲区,然后SocketChanne将读取数据到读缓冲区。

问题:为什么缓冲区需要一个size头部?

为了解决TCP粘包拆包问题。粘包/拆包问题是TCP编程必然解决的问题,TCP这种底层流协议。他根本无法感知上层业务数据边界,所以需要进行粘包拆包设计。主要还是采取使用一个size来表示消息长度,这样在读取的时候,一旦读取到消息的长度,就可以知道应该读取多长的流,就能解决粘包问题。当读取长度不够size,就持续接受。就解决了拆包问题。在一些TCP框架里面还会扩充一些其他分割器方案,比如netty里面提供了定长分割器和分隔符分割器。在Kafka里面,在是4个字节的来表示消息长度,使用的int变量。TCP不是本文分析的重点,就点到为止。下面细细分析KafkaChannel

2:KafkaChannel承担了哪些事情?

通过主要method来看看KafkaChannel有哪些功能承担了哪些事情?

Method 作用
void prepare() 握手认证
KafkaPrincipal principal() 获取认证信息
boolean finishConnect() 是否建立连接完成
boolean isConnected() 是否建立连接
SelectionKey selectionKey() 获取该channel上的SelectionKey
void setSend(Send send) 初始化需要发送的数据
NetworkReceive read() 网络读(读取Kafka服务器数据)
Send write() 网络写(向Kafka服务器发送数据)
void disconnect() 断开连接
void state(ChannelState state) 设置该连接的连接状态
ChannelState state() 获取该连接的连接状态
3.KafkaChannel网络读写的源码分析

3.1setSend(Send send)源码分析

public void setSend(Send send) {
   
    if (this.send != null)
        throw new IllegalStateException("Attempt to begin a send operation with prior send operation still in progress, connection id is " + id);
    this.send = send;
    //添加到interestOps [见下]
    this.transportLayer.addInterestOps(SelectionKey.OP_WRITE);
}
public void addInterestOps(int ops) {
   
    //SelectionKey
    key.interestOps(key.interestOps() | ops);

}

setSend(Send send)就是将需要发送的数据设置到KafkaChannel的send成员中。(是在Kafka的selector的send方法中。关于kafka的selector,还会专门分析)然后给让selector增加写监控事件。Send 就是需要要发送的数据。

主要是来分析Send 是如何构建的。Send 是最上层接口。producer发送消息时候采用的是子类NetworkSend

3.2NetworkSend的构建

public class NetworkSend extends ByteBufferSend {
   

    public NetworkSend(String destination, ByteBuffer buffer) {
   
        //见下段分析
        super(destination, sizeDelimit(buffer));
    }

    /**
     * 组装ByteBuffer[size|data]的结构
     * @param buffer
     * @return
     */
    private static ByteBuffer[] sizeDelimit(ByteBuffer buffer) {
   
        
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值