这个 Kafka 的专题,我会从系统整体架构,设计到代码落地。和大家一起杠源码,学技巧,涨知识。希望大家持续关注一起见证成长!

我相信:技术的道路,十年如一日!十年磨一剑!

往期文章

Kafka 探险 - 架构简介

Kafka 探险 - 源码环境搭建

Kafka 探险 - Kafka 探险 -  生产者源码分析: 核心组件

前言

首先还是看一眼 Kafka 生产者中的方法,核心分为三类:构造器,消息发送,其他。

我们今天要探讨的是在构造器中初始化配置时用到的配置类,看起来是构造方法中一个不起眼的参数,但是代码中暗藏了很多技巧。而这些技巧应用于平时的开发,也能让我们在写业务代码的时享受到写底层中间件的感觉,让代码看起来简洁,健壮,易扩展,有层次。

四个构造方法,其余三个构造器最终都调用到 :KafkaProducer(ProducerConfig, Serializer<K>, Serializer<V>)

第一个参数是 生产者配置类,他继承了 AbstractConfig  , 这个配置类中大部分内容为 : 配置项的 key 和 配置项代表的含义 doc ,例如

但是还有一个非常重要的字段: ConfigDef CONFIG  , ConfigDef 这个类定义了一份配置的元数据,并且提供了: 继承,分组,存储的能力。分别对应 ConfigDef 的以下三个字段:

配置定义

配置存储

配置存储即通过 ConfigKey 来完成,他定义了配置的元数据,包括 数据类型,key,分组,优先级,校验器。通过一个抽象的 Validator  接口实现添加配置时的校验逻辑

为每个字段设置校验器,各个字段校验器有各自的实现类,这一点可以借鉴下,对于字段的校验 自定义校验器,将校验逻辑集中封装,而不是散落在代码的各个位置

配置继承

配置的继承实现非常简单,直接传递一个配置类,将里面存储的配置和分组拷贝过来

配置分组

一方面通过 ConfigKey 中定义的 group 字段,另外在定义配置项的时候将 key 与 group 的关系存放到 Map 中。

配置操作

看完了配置元数据的定义后,继续回到构造方法 KafkaProducer(ProducerConfig, Serializer<K>, Serializer<V>) ,可以看到需要传递一个 ProducerConfig ,他其实就是Kafka 的配置类,而这个配置类恰巧就对应了 producer.properties 这个配置文件。看到这里是不是发现这与 Spring 中的 JavaConfig 同 Xml 有异曲同工之妙?事实正是如此大多数框架都会有一套配置文件与 Java 类的映射关系,方便默认配置加载,或者配置的动态加载,网络加载等等...

生产者的配置类为 ProducerConfig 消费者为 ConsumerConfig  他们都继承了 AbstractConfig  从下面的图看一看到,Kafka 中所有的配置都是由这个基类来驱动的。

我们需要关注的方法主要为: 构造器、取配置值、其他

构造方法

整体代码相对比较简单,将传入的原始 Map 配置解析到当前类的 values 成员变量中,此时 values 也是一个 Map ,只不过他的 value 不是简单的字符串了而是解析后的对象类型。

这里需要注意的一点在于他的 postProcessParsedConfig()  方法,这个方法在当前类是一个空实现,具体的实现是在子类实现的。在有类的继承关系的时候某些通用的前置后置操作,但是这些操作根据不同的子类需要不同的实现的时候我们经常会这么处理,这种方法也叫做模板方法或者称作 模板设计模式 。

取值方法

这些方法比较简单,但是非常有必要。我经常在很多项目里面看到这样的代码

我相信大家都不陌生,在很多工程中都会见到这样的代码,某个类中定义了一个 Map  或者一个 JSONObject  但是并没有封装对应值的方法,而是在使用到的时候直接 get 一个字符串,然后类型强转。

这样的代码显然是低质量的代码,缺点很明显我们并不知道这个 Map 都会有哪些 key,每次取数据的时候只能使用魔法字符串。另外取出来的值有可能是空,直接强壮很有可能 NPE 。需要做判空操作,强制类型转换,这些非常常用的基础代码会散落在项目的各个文件中。

一般来说我们最好直接定义类,少定义 Map 或者 JSON 。那么万一使用了我们又该如何让他变得 易懂,易维护,易使用呢?

首先针对使用魔法值 get 的问题,我们需要针对这个 Map 定义一个常量,定义 Map 中所有会存储和取出的 Key 每次如果需要往这个 Map 中写入新的 Key 需要修改下这个常量类。

而对于每次根据 key 取数据,并强转的问题我们可以定义一些基础方法,例如 getIntExtVal()  getLongExtVal()  等等一系列的方法,将判空和强转一并解决了甚至还可以配置默认值。简化下大概长下面这样,是不是代码瞬间清晰了很多,调用起来也变得方便了。

尾声(唠叨)

过完春节的第一个周末,终于也是写完这篇文章了。只是好久没有锻炼身体了,上周打完羽毛球胳膊简直废了,后面要好好运动!

另外:大家也可以关注下我的微信公众号哦~【 徐笔笔 】

读 Kafka 源码写优雅业务代码:配置类的更多相关文章

  1. Spring5源码解析2-register方法注册配置类

    接上回已经讲完了this()方法,现在来看register(annotatedClasses);方法. // new AnnotationConfigApplicationContext(AppCon ...

  2. 【Kafka源码】Kafka代码模块

    Kafka源码依赖于Scala环境,首先需要安装scala,这块请自行百度进行安装. 传送门 当然,我们要分析源码,需要下载源码,请自行从github上面下载. 说明:本文使用的kafka版本为0.1 ...

  3. Kafka源码分析(二) - 生产者

    系列文章目录 https://zhuanlan.zhihu.com/p/367683572 目录 系列文章目录 一. 使用方式 step 1: 设置必要参数 step 2: 创建KafkaProduc ...

  4. kafka源码分析之一server启动分析

    0. 关键概念 关键概念 Concepts Function Topic 用于划分Message的逻辑概念,一个Topic可以分布在多个Broker上. Partition 是Kafka中横向扩展和一 ...

  5. 读 Zepto 源码系列

    虽然最近工作中没有怎么用 zepto ,但是据说 zepto 的源码比较简单,而且网上的资料也比较多,所以我就挑了 zepto 下手,希望能为以后阅读其他框架的源码打下基础吧. 源码版本 本文阅读的源 ...

  6. Kafka源码分析(三) - Server端 - 消息存储

    系列文章目录 https://zhuanlan.zhihu.com/p/367683572 目录 系列文章目录 一. 业务模型 1.1 概念梳理 1.2 文件分析 1.2.1 数据目录 1.2.2 . ...

  7. 开始读 Go 源码了

    原文链接: 开始读 Go 源码了 学完 Go 的基础知识已经有一段时间了,那么接下来应该学什么呢?有几个方向可以考虑,比如说 Web 开发,网络编程等. 在下一阶段的学习之前,写了一个开源项目|Go ...

  8. 【读fastclick源码有感】彻底解决tap“点透”,提升移动端点击响应速度

    申明!!!最后发现判断有误,各位读读就好,正在研究中.....尼玛水太深了 前言 近期使用tap事件为老夫带来了这样那样的问题,其中一个问题是解决了点透还需要将原来一个个click变为tap,这样的话 ...

  9. 读jQuery源码 - Deferred

    Deferred首次出现在jQuery 1.5中,在jQuery 1.8之后被改写,它的出现抹平了javascript中的大量回调产生的金字塔,提供了异步编程的能力,它主要服役于jQuery.ajax ...

随机推荐

  1. 大数据开发-Spark Join原理详解

    数据分析中将两个数据集进行 Join 操作是很常见的场景.在 Spark 的物理计划阶段,Spark 的 Join Selection 类会根 据 Join hints 策略.Join 表的大小. J ...

  2. 在Blazor Server 项目中使用 EF Core Sqlite

    按照教程创建了一个 Blazor Server 项目 教程地址: https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/build-a-blaz ...

  3. Kubernets二进制安装(13)之部署Flannel

    Flannel简介 ​ Flannel是CoreDNS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址 ...

  4. eclispe中解决OOM问题

     -Xms256M -Xmx512M -XX:PermSize=256m -XX:MaxPermSize=512m 

  5. 字节笔试题 leetcode 69. x 的平方根

    更多精彩文章请关注公众号:TanLiuYi00 题目 解题思路 题目要求非负整数 x 的平方根,相当于求函数 y = √x 中 y 的值. 函数 y = √x  图像如下: 从上图中,可以看出函数是单 ...

  6. Leetcode(7)-反转整数

    给定一个 32 位有符号整数,将整数中的数字进行反转. 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: 21 注意: 假 ...

  7. 深入剖析JavaScript中的对象与原始值之间的转换机制

    我们都知道原始值之间是可以互相转换的,但是如果对象转原始值呢? 所有的对象在布尔上下文(context)中均为 true .所以对于对象,不存在 to-boolean 转换, 只有字符串和数值转换. ...

  8. Keep Fitness

    Keep Fitness 健身 keep health 训练流程 Part 1 热身 5-10分钟 Part 2 肌肉力量训练 30分钟 大肌群包括:胸.背.腿.臀: 小肌群包括:肩.二头肌.三头肌. ...

  9. GitHub user language statistics

    GitHub user language statistics 2020 https://madnight.github.io/githut/#/pull_requests/2020/2 2011 ~ ...

  10. webpack async load modules & dynamic code splitting

    webpack async load modules & dynamic code splitting webpack 按需/异步加载/Code Splitting webpack loade ...