思考

前面提到 Kafka 帮我们实现了各个版本的生产者代码,其实他也可以完全不提供这份代码,因为核心的队列的功能已经实现了,这些客户端的代码也可以完全交由用户自己实现。

那么假如没有官方代码,我们又该实现一些什么功能,有哪些接口,哪些方法,以及如何组织这些代码呢。带着这样的问题我们一起来思考一下!一般对于这种带有数据流转的设计,我会从 由谁产生? 什么数据? 通往哪去? 如何保证通路可靠? 这几个方面来考虑。

消息自然是通过应用程序构造出来并提供给生产者,生产者首先要知道需要将消息发送到哪个 Broker 的哪个 Topic,以及 Topic 的具体 Partition 。那么必然需要配置客户端的 Broker集群地址 ,需要发送的 Topic 名称 ,以及 消息的分区策略 ,是指定到具体的分区还是通过某个 key hash 到不同的分区。

知道了消息要通往哪,还需要知道发送的是什么格式的消息,是字符串还是数字或是被序列化的二进制对象。 消息序列化 将需要消息序列化成字节数组才方便在网络上传输,所以要配置生产者的消息序列化策略,最好是可以通过传递枚举或者类名的方式自动构造序列化器,便于后续序列化过程的扩展。

消息队列常常用于多个系统之间的异步调用,那么这种调用关系就没有强实时依赖。由于发消息到 Kafka 会产生 网络 I/O ,相对来说比较耗时,那么消息发送这一动作除了同步调用, 是否也可以设置为异步,提高生产者的吞吐呢? 。并且大量消息发送场景, 我们可以设置一个窗口,窗口可以是时间维度也可以是消息数量维度,将消息积攒起来批次发送,减少网络 I/O 次数,提高吞吐量。

最后呢为了保证消息可以最大程度的成功发送到 Broker ,我们还需要一些 失败重试机制 ,例如失败后放到重试队列中,隔一段时间尝试再次发送。

理清思路

通过上面的分析,我们会有一个大致的认识,应该会有哪些方法,以及底层的大致的设计会分为哪几个部分。但是不够清楚,不够明晰。

首先总结一下实现客户端的几个要点在于:

  1. 配置 Broker 基础信息:集群地址、Topic、Partition

  2. 消息序列化,通过可扩展的序列化器实现

  3. 消息异步写入缓冲区,网络 I/O 线程实现消息发送

  4. 消息发送的失败重试机制

话不多说,用一张图画出各个核心模块以及他们之间的交互顺序:

用户设定 Kafka 集群信息,生产者从 Kafka Broker 上拉取 可用 Kafka 节点、Topic 以及 Partition 对应关系。缓存到生产者成员变量中,如果 Broker 集群有扩容,或者有机器下线需要重新获取这些服务信息。

客户端根据用户设置的序列化器,对消息进行序列化,之后异步的将消息写入到客户端缓冲区。缓冲区内的消息到达一定的数量或者到达一个时间窗口后,网络 I/O 线程将消息从缓冲区取走,发送到 Broker 。

以上就是我对于一个 Kafka 生产者实现的思考,接下来看看官方的代码设计与我们的思路有何差别,他又是为什么这么设计。

官方设计

其实经过上面的思考和整理,我们的设计已经非常接近 Kafka 的官方设计了,官方的模块拆分的更加细致,功能更加独立。

核心组件

首先看一眼 KafkaProducer 类中有哪些成员变量,这些变量就是 Producer 的核心组件。

其中核心字段的解释如下:

clinetId :标识发送者Id

metric :统计指标

partitioner :分区器作用是决定消息发到哪个分区。有 key 则按照 key 的 hash ,否则使用 roundrobin

key/value Serializer :消息 key/value 序列化器

interceptors :发送之前/后对消息的统一处理

maxRequestSize :可以发送的最大消息,默认值是1M,即影响一个消息 Record 的大小,此值在服务端也是有限制的。

maxBlockTimeMs :buffer满了或者等待metadata信息的,超时的补偿机制

accumulator :累积缓冲器

networkClient :包装的网络层

sender :网络 I/O 线程

发送流程

发送一条消息的时候,数据又是怎样在这些组件之间进行流转的呢?

Producer调用 send 方法后,在从 Broker 获取的 Metadata 有效情况下,经过拦截器和序列化后,被分区器放到了一个缓冲区的特定位置,缓冲区由一个 ConcurrentHashMap 构成,key 为主题分区,value 是一个 deque 存放消息缓存块。从客户端角度来看如果无需关心发送结果,发送流程就已经结束了。

接下来是独立的Sender线程负责从缓冲中获取足量的数据调用 Network Client 封装层去真正发送数据,这里使用了 Java8 的 NIO 网络模型发送数据。

可以看到整个逻辑的关键点在于 RecordAccumulator 如何进行消息缓存,一般的成熟框架和中间件中都会有一套自己的内存管理机制,比如 Netty 也有一套复杂而又精妙的内存管理抽象层,这里的缓冲区也是一样的道理,主要需要去看看 Kafka 如何去做内存管理。

另外需要关注 Sender 从缓冲里以什么样的逻辑获取数据,来达到尽量少的网络交互发送尽量多的数据。还有网络失败又是如何保证数据的可靠性的。这个地方也是我们的设计和官方实现的差距,对于网络 I/O 的精心优化。

目前的篇幅已经比较长了,为了大家方便阅读理解,本篇主要从和大家一起思考如何设计一个 Kafka Producer 以及官方是如何实现的,我们之间的差距是什么,更需要关注的点是什么。通过自己的思考和对比更加能认识到不足学习到新的点!

最后

送大家一个小福利,点击领取Java全套进阶资料

2dB)**

[外链图片转存中…(img-4OHhsAV4-1624508382019)]

[外链图片转存中…(img-Ucv70RoU-1624508382020)]

java后端面试通过邮件范本,成功入职阿里相关推荐

  1. 疯狂java讲义pdf百度云,成功入职阿里

    主要内容 本文是从大型互联网系统的应用角度探讨分布式缓存的.本文站在原理.框架.架构.案例等多个视角对分布式缓存进行了探讨. 互联网系统随着容量需求的陡增,许多看似简单的存储类场景都面临着巨大的容量问 ...

  2. Java校招面试经验汇总,最终入职阿里

    一面 自我介绍 项目中的监控:那个监控指标常见的有哪些? 微服务涉及到的技术以及需要注意的问题有哪些? 注册中心你了解了哪些? consul 的可靠性你了解吗? consul 的机制你有没有具体深入过 ...

  3. Java周末兼职培训讲师,成功入职阿里

    一.先来解读:23种设计模式要点 1.单例模式(Singleton Pattern) 2.工厂模式 3.抽象工厂模式(Abstract Factory Pattern) 4.模板方法模式(Templa ...

  4. 面试了10几家公司后被怼,逼的我把源码都吃透了,最终成功入职阿里

    从三月底开始投递简历,甭管是什么公司,只要薪资待遇跟之前差不多我都投了.最气人的一次面试经历是一个小公司的HR约我面试,我过去了,填完表格,还没到技术面呢,她看到我的期望薪资是15k+,直接来了一句: ...

  5. 成功入职阿里后,我总结了这3大求职经验

    一.找工作之--简历 想要找工作,简历是第一关,其分为两个方面,一个是写简历,另一个是投简历. 1. 写简历 写简历,原则上是遵循简洁扼要,突出自己的工作经验,篇幅限制在两页 A4 纸张以内. 作为设 ...

  6. 开发者必备的顶级Android开发工具,成功入职阿里

    前言 近日,字节跳动正式启动了2021届秋季校园招聘,为应届毕业生开放超过6000个工作岗位.这一数字超过了该公司往年秋招规模,并与其今年春招规模持平.全年校招人数共计超过1万2千人,远高于同类型互联 ...

  7. android培训课程!不同层级的Android开发者的不同行为,成功入职阿里

    前言 找工作还是需要大家不要紧张,有我们干这一行的接触人本来就不多 难免看到面试官会紧张,主要是因为怕面试官问的问题到不上来,那时候不要着急 ,答不上了的千万不然胡扯一些,直接就给面试官说这块我还没接 ...

  8. java程序员必备软件,最终入职阿里

    1. CAP 的由来 要理解 CAP,首先我们要清楚,为何会有人提出 CAP?他提出 CAP 是为了解决什么问题? 时间回到 1985 年,彼时,后来证明了 CAP 理论的 Lynch 教授此时给当时 ...

  9. apk开发语言!程序员如何自我学习和成长?成功入职阿里

    **新技术层出不穷,去年kotlin到如今Flutter,技术迭代,你是否会变得固步自封?**那么看本篇文章帮你解决问题,让你知道怎么样学习,学习那些技术点才能不被时代的迭代快速淘汰! 首先,先说一下 ...

最新文章

  1. poj12月其他题解(未完)
  2. 服务器系统策略功能,设置服务器系统口令复杂度策略
  3. 五种境界之 二进制转换为十进制(C语言版)
  4. Python基础知识梳理(一)
  5. 小波变换学习~语音端点检测
  6. Android应用开发 led 驱动层 hal硬件抽象层 应用层 详细教程记录(含源码)
  7. html标签缺省(自带)样式大全
  8. OpenVR——驱动接口之IServerTrackedDeviceProvider简介
  9. matlab 最大熵谱估计,基于Burg算法的最大熵谱估计
  10. PyTorch 深度学习:36分钟快速入门——GAN
  11. 信号与槽QVariant传递结构体指针
  12. 如何知道是哪个进程造成死锁?如何把这个进程杀掉?
  13. R数据分析:二分类因变量的混合效应,多水平logistics模型介绍
  14. 隐藏Ubuntu引导,直接进入系统——变色龙引导Linux,Windows,Mac OS(苹果系统)攻略之二
  15. R750 H750 H755 阵列卡磁盘次序
  16. 2021绍兴市大学生程序设计竞赛邀请赛题解
  17. 笔记本键盘按键拆卸教程
  18. 解决问题:Something's wrong--perhaps a missing \item. \end{thebibliography}
  19. HTML学习第十二章------布局和排版
  20. eclipse 项目中搜索资源(类方法,文件名,文件中的字符串)

热门文章

  1. 游侠我的世界显示java_我的世界怎么用命令方块在屏幕上显示字
  2. python怎么设置画布大小_在Matplotlib中设置绘图画布的大小
  3. Java四舍五入及保留小数点位数
  4. jest测试具体方法
  5. 图片识别表格的方法有哪些?试试这几个好用的表格识别软件
  6. 两电平apf和三电平apf的区别
  7. 如何配置web3.js和连接MetaMask
  8. 由你定义吃鸡风格!CycleGAN,你的自定义风格转换大师[楚才国科]
  9. 利用TSN满足关键应用需求 ——以航空航天、汽车、铁路三大应用场景为例
  10. 如何给CSDN博客添加个人微信公众号二维码或自定义栏目