1. 序列化一条消息

消息有 key 和 value

kafka 提供了基础数据类型的序列化工具,对于业务的自定义类需要自行实现序列化

ProducerRecord 是对象,含 KV 和 headers,此时的 KV 还是对象

在 KafkaProducer#doSend 中会对 KV 进行序列化,得到 KV 的 byte 数组

然后把 byte 数组和 headers 加入到 ProducerBatch 中

代码见:

org.apache.kafka.clients.producer.internals.ProducerBatch#recordsBuilder
org.apache.kafka.common.record.MemoryRecordsBuilder#appendStream

2. kafka 的 tcp 报文

利用 Struct 和 Schema 把 ProducerBatch 的数据转换成符合 kafka 格式的 tcp 报文

以发送消息为例

org.apache.kafka.common.requests.AbstractRequest#toSend
org.apache.kafka.common.requests.AbstractRequest#serialize
org.apache.kafka.common.requests.AbstractRequestResponse#serialize
org.apache.kafka.common.requests.ProduceRequest#toStruct
org.apache.kafka.common.protocol.types.Schema#write

org.apache.kafka.common.requests.RequestHeader#toStruct

public Struct toStruct() {
Schema schema = schema(apiKey.id, apiVersion);
Struct struct = new Struct(schema);
struct.set(API_KEY_FIELD_NAME, apiKey.id);
struct.set(API_VERSION_FIELD_NAME, apiVersion); // only v0 of the controlled shutdown request is missing the clientId
if (struct.hasField(CLIENT_ID_FIELD_NAME))
struct.set(CLIENT_ID_FIELD_NAME, clientId);
struct.set(CORRELATION_ID_FIELD_NAME, correlationId);
return struct;
}

org.apache.kafka.common.requests.ProduceRequest#toStruct

public Struct toStruct() {
// Store it in a local variable to protect against concurrent updates
Map<TopicPartition, MemoryRecords> partitionRecords = partitionRecordsOrFail();
short version = version();
Struct struct = new Struct(ApiKeys.PRODUCE.requestSchema(version));
Map<String, Map<Integer, MemoryRecords>> recordsByTopic = CollectionUtils.groupDataByTopic(partitionRecords);
struct.set(ACKS_KEY_NAME, acks);
struct.set(TIMEOUT_KEY_NAME, timeout);
struct.setIfExists(NULLABLE_TRANSACTIONAL_ID, transactionalId); List<Struct> topicDatas = new ArrayList<>(recordsByTopic.size());
for (Map.Entry<String, Map<Integer, MemoryRecords>> topicEntry : recordsByTopic.entrySet()) {
Struct topicData = struct.instance(TOPIC_DATA_KEY_NAME);
topicData.set(TOPIC_NAME, topicEntry.getKey());
List<Struct> partitionArray = new ArrayList<>();
for (Map.Entry<Integer, MemoryRecords> partitionEntry : topicEntry.getValue().entrySet()) {
MemoryRecords records = partitionEntry.getValue();
Struct part = topicData.instance(PARTITION_DATA_KEY_NAME)
.set(PARTITION_ID, partitionEntry.getKey())
.set(RECORD_SET_KEY_NAME, records);
partitionArray.add(part);
}
topicData.set(PARTITION_DATA_KEY_NAME, partitionArray.toArray());
topicDatas.add(topicData);
}
struct.set(TOPIC_DATA_KEY_NAME, topicDatas.toArray());
return struct;
}

组装报文

public abstract class AbstractRequestResponse {
/**
* Visible for testing.
*/
public static ByteBuffer serialize(Struct headerStruct, Struct bodyStruct) {
ByteBuffer buffer = ByteBuffer.allocate(headerStruct.sizeOf() + bodyStruct.sizeOf());
headerStruct.writeTo(buffer);
bodyStruct.writeTo(buffer);
buffer.rewind();
return buffer;
}
} public class NetworkSend extends ByteBufferSend { public NetworkSend(String destination, ByteBuffer buffer) {
super(destination, sizeDelimit(buffer));
} private static ByteBuffer[] sizeDelimit(ByteBuffer buffer) {
return new ByteBuffer[] {sizeBuffer(buffer.remaining()), buffer};
} private static ByteBuffer sizeBuffer(int size) {
ByteBuffer sizeBuffer = ByteBuffer.allocate(4);
sizeBuffer.putInt(size);
sizeBuffer.rewind();
return sizeBuffer;
} }

所以能推断出,kafka 报文格式:4 字节存储长度,headerStruct,bodyStruct

当然通过 NetworkSend 和 NetworkReceive 的注释也能看出来

kafka 通信报文格式的更多相关文章

  1. HTTP协议报文格式

    HTTP协议报文格式 接下来我们看看HTTP协议(Hypertext Transfer Protocol――超文本传输协议)浏览器端(客户端)向WEB服务器端访问页面的过程和HTTP协议报文的格式. ...

  2. MQTT——控制报文格式

    解控制报文格式是学习MQTT中,笔者认为最为重要的一个知识点.MQTT的所有行为都离不开他.控制报文可以分为三个部分组成,分别为:固定报头.可以变报头.有效载荷部分. 注意:上面的说的报文的类型.是指 ...

  3. 第11章 拾遗4:IPv6(1)_报文格式和地址类型

    1. IPv4和IPv6协议栈的比较 (1)IPv6取代IPv4,支持IPv6的动态路由协议都属于IPv6协议(如RIPng.OSPFv3). (2)Internet控制消息协议IPv6版(ICMPv ...

  4. 总想自己动动手系列·1·本地和外网(Liunx服务器上部署的web项目)按照自定义的报文格式进行交互(准备篇)

    一.准备工作 (1)有一台属于自己的云服务器,并成功部署和发布一个web项目(当然,本质上来说Java-Project也没问题),通过外网IP可以正常访问该web项目. 需要说明的是:任何web项目, ...

  5. 结合Wireshark捕获分组深入理解TCP/IP协议栈之TCP协议(TCP报文格式+三次握手实例)

    摘要:     本文简单介绍了TCP面向连接理论知识,详细讲述了TCP报文各个字段含义,并从Wireshark俘获分组中选取TCP连接建立相关报文段进行分析. 一.概述     TCP是面向连接的可靠 ...

  6. TCP报文格式+UDP报文格式+MAC帧格式

    TCP和UDP的区别: 1)TCP是面向连接的,而UDP是无连接的 2)TCP提供可靠服务,而UDP不提供可靠服务,只是尽最大努力交付报文 3)TCP面向字节流,TCP把数据看成一串无结构的字节流,而 ...

  7. 【转】IP报文格式详解

    下图为常见的IP报文格式表: 上面是IP的报文格式,接下来我们先说明各个字段的意义.然后,用Etheral软件转包分析IP的报文格式. 1.版本:ip报文中,版本占了4位,用来表示该协议采用的是那一个 ...

  8. TCP协议探究(一):报文格式与连接建立终止

    一 TCP:传输控制协议报文格式 1 TCP服务 提供面向连接.可靠的字节流服务 面向连接意味着两方通信,不支持多播和广播 可靠性的支持: 应用数据被分割成TCP认为最适合发送的数据块.由TCP传递给 ...

  9. DNS报文格式(RFC1035)

    一.域名和资源记录的定义 1.Name space definitions 2.资源记录定义(RR definitions)      2.1 格式          后面分析报文的时候详细解释.   ...

随机推荐

  1. jumpserver模块功能介绍

    一.仪表盘二.用户管理1.用户列表2.用户组 三.资产管理 1.资产列表 1.1 管理资产树 资产树节点不能重名, 右击节点可以添加.删除和重命名节点, 以及进行资产相关的操作 1.2 为资产树节点创 ...

  2. 在控制台编译运行java程序详细指导

    控制台编译运行.java文件 首先在cmd中输入java –version确定java环境变量是否已经配好 其次在cmd中输入javac –version 确定javac环境变量是否已经配好 在用cd ...

  3. AIX中磁带设备的使用

    1.AIX中的磁带设备 在UNIX系统中,磁带一般具有如下共同属性. 磁带密度:指磁带使用时采用的低密度方式和高密度方式   回退操作:磁带一次写入操作完成后,是否立刻倒带,回退到磁带头部.   位置 ...

  4. Qualcomm_Mobile_OpenCL.pdf 翻译-5-性能优化的概述

    这章提供了一个OpenCL应用程序优化的总体概述.更多的细节将会在接下来的章节中找到. 注意:OpenCL程序的优化是具有挑战性的.相比初始的程序开发工作,经常需要做更多的工作. 5.1 性能移植性 ...

  5. navicat修改表的主键自增长报错

    这周自己在构思一个项目的表的设计,由于是第一次,所以走了很多弯路,也遇到了几个问题,这里暂时贴上来. 我用PowerDesign设计出一部分关联表的ER图之后,导出了sql文件之后用navicat导入 ...

  6. xavier_uniform/xavier_normal

    import math from torch.autograd import Variable import torch import torch.nn as nn import warnings w ...

  7. cve-2019-1609,Harbor任意管理员注册漏洞复现

    一.Harbor介绍 以Docker为代表的容器技术的出现,改变了传统的交付方式.通过把业务及其依赖的环境打包进Docker镜像,解决了开发环境和生产环境的差异问题,提升了业务交付的效率.如何高效地管 ...

  8. 用jquery控制表单提交

    可以监听表单submit提交事件给form一个id 吧button的type为submit $(form的id).submit(function(){ if(window.confirm('你确定要取 ...

  9. dubbo网关

    https://blog.csdn.net/Paranoia_ZK/article/details/90743432 springcloud 和 dubbo 混用

  10. ORACLE中的TOP-N查询(TOP-N分析)、分页查询

    TOP-N查询(TOP-N分析):就是获取某一数据集合中的前N条记录,实际应用中经常用到. Oracle中不支持SELECT TOP语句(MySQL中也没用此语句),需要借助ROWNUM伪列来实现TO ...