笔者所在的项目,需要往kafka内推送消息,供多方消费者使用。由于实际的Kafka服务端版本不一,且kafka不同版本的消息格式不同,因此java客户端(发送消息/接收消息方,以下简称“客户端”)的package下需要同时支持多个版本的Kafka。
Kafka消息格式
目前Kafka有三种消息格式,由于各个消息格式有不同的功能及性能特点,不同版本之间进行通信可能会导致发送或接受失败,且会造成性能上的损失,因此服务端和客户端的消息格式需要保持一致。
这里依据消息格式(magic),将具体支持的kafka版本大致分为三类:
消息格式 | 对应Kafka版本 | 描述 |
---|---|---|
v0 | 0.8~0.9 | 最早的消息格式 |
v1 | 0.10.0.0~0.10.2.2 | 从0.10.0.0版本开始,增加了时间索引文件(0.10.1.0版KafkaConsumer开始提供offsetsForTimes接口,可根据时间戳消费数据 |
v2 | 0.11.0.0~2.0+ | 0.11.0.0版本及以上的消息格式(magic)为v2;此范围内的版本可以通过只配置Broker地址,实现topic的创建/删除/修改。从2.0.0版本开始,后续的kafka版本放弃了对Java7的支持。因此,为了支持高版本kafka client,java的jdk版本需要升至1.8(0.9及后续版本均支持Java 8) |
客户端版本划分
想要支持0.9以上的所有版本的kafka服务端,只需要在客户端引入三类消息格式的kafka包即可。
大专栏 Kafka消息格式及多版本支持 - 边边大神的博客在0.10.1.0版本之前,Kafka服务器端和客户端版本之间的兼容性是“单向”的,即高版本的broker可以处理低版本client的请求;
反过来,低版本的broker不能处理高版本client的请求。
0.10.1.0之前的v0和v1选择当前范围最小的版本,v2则随机选择任一版本即可。最终引入的三个客户端版本为:0.9.0.0,0.10.0.0,2.1.0。 不过,这三个版本的包名及大部分类名是相同的,若直接在pom中引入,则java运行时将仅使用最高版本的包。 那么,如何解决同时支持多个版本的kafka客户端呢?
java支持同名package的方法
同一java项目包内引入不同版本kafka client jar包的方法(此方法可引申至其他依赖包,不限于Kafka):
- 为每个kafka 依赖包创建一个maven项目,在pom文件中引入maven-shade-plugin插件,通过relocation将项目包名更改为新的名称:
<relocation>
<pattern>org.apache.kafka</pattern>
<shadedPattern>test.kafka09</shadedPattern>
</relocation>
这样,可以将0.9版本的org.apache.kafka重命名为ndc.kafka09,0.10版本的org.apache.kafka重命名为ndc.kafka10,以此类推。
- java项目使用时,在pom文件中,将org.apache.kafka替换为test.kafka09;当java代码中调用同一kafka接口时,可以通过不同的包名区分不同的实现版本。