「造个轮子」——cicada 设计一个配置模块

简介: 结合现在大家使用 SpringBoot 的习惯, cicada 默认会读取 classpath 下的 application.properties 配置文件。并且会默认读取其中的应用端口以及初始路由地址。

前言

在前两次的 cicada 版本中其实还不支持读取配置文件,比如对端口、路由的配置。

因此我按照自己的想法创建了一个 issue ,也收集到了一些很不错的建议。

ef7045b2fed080565615882f20a86e91f58c5d99

51578cde89e09c3053cb92f00108765b89d92888

最终其实还是按照我之前的想法来做了这个配置管理。

同时将 cicada 升级到了 v1.0.2

目标

在做之前是要把需求想好,到底怎样的一个配置管理是对开发人员来说比较友好的?

我认为有以下几点:

  • 可以自定义配置,并且支持不同的环境(开发、测试、生产)。

  • 使用灵活。对使用者来说不要有太多的束缚。

理论上来说配置这个东西应当完全独立出来,由一个配置中心来负责管理并且这样可以与应用解耦。

不过这样的实现和当前 cicada 的定义有些冲突,我想尽量小的依赖第三方组件并可以完全独立运行。

因此基于这样的情况便有了以下的实现。

使用

在看实现之前先看看基于目前的配置管理如何在业务中使用起来。

结合现在大家使用 SpringBoot 的习惯, cicada 默认会读取 classpath 下的 application.properties 配置文件。并且会默认读取其中的应用端口以及初始路由地址。

同时也新增了一个 api。

 
 
  1. public class MainStart {

  2.    public static void main(String[] args) throws Exception {

  3.        CicadaServer.start(MainStart.class,"/cicada-example") ;

  4.    }

  5. }

  6. public class MainStart {

  7.    public static void main(String[] args) throws Exception {

  8.        CicadaServer.start(MainStart.class) ;

  9.    }

  10. }

这样在不传默认地址的时候 cicada 会从 application.properties 中读取。

考虑到后面可维护的情况, cicada 也支持配置各种不同的配置文件。

使用也比较简单,只需要继承 cicada 提供的一个抽象类即可。

 
 
  1. public class KafkaConfiguration extends AbstractCicadaConfiguration {

  2.    public KafkaConfiguration() {

  3.        super.setPropertiesName("kafka.properties");

  4.    }

  5. }

  6. public class RedisConfiguration extends AbstractCicadaConfiguration {

  7.    public RedisConfiguration() {

  8.        super.setPropertiesName("redis.properties");

  9.    }

  10. }

5d5e93a83423c4c87cdb3b24508ca391ef9e517a

按照这样的配置也会默认从 classpath 读取这两个配置文件。

当然这里有个前提:代码里配置的文件名必须得和配置文件名称相同。

那如何在业务中读取这两个配置文件的内容呢?

这也简单,代码一看就懂:

efae6a237569b15bf75dccb5d0e2fcff24512068

  • 首先需要通过 ConfigurationHolder 获取各自不同配置的管理对象(需要显式指定类类型)。

  • 通过 get() 方法直接获取配置。

  • 同时也支持获取 application.properties 里的配置。

同时为了支持在不同环境的使用,当配置了启动参数将会优先读取。

 
 
  1. -Dapplication.properties=/xx/application.properties

  2. -Dkafka.properties=/xx/kakfa.properties

  3. -Dredis.properties=/xx/redis.properties

这样算是基本实现了上述的配置要求。

实现

要实现以上的功能有几个核心点:

  1. 加载所有配置文件。

  2. 将不同的配置文件用不同的对象进行管理。

  3. 提供简易的接口使用。

由于 cicada 需要支持多个配置文件,所有需要定义一个抽象类供所有的配置管理实现。

5b209c438a60e974748b4746988fe55717b8c939

定义比较简单,其中有两个重要的成员变量:

  • 文件名称:用于初始化时通过名称加载配置文件。

  • Properties 其实就是一个 Map 结构的缓存,用于存放所有的配置。当然对外提供的查询是基于它的。

接着就是在初始化时需要找出所有继承了 AbstractCicadaConfiguration 的类。

a5ab330c4815d04b55165e62f770e0135d93f5a0

查询出来之后自然是要进行遍历同时反射创建对象。

由于之前已经调用了

super.setPropertiesName("redis.properties");

来赋值配置文件名称,所以还需要在遍历过程中将 Properties 进行赋值。

同时在这里也体现出优先读取的是 VM 启动参数中的配置文件。

d7082d3ce13c50fbb52966ee2edda2f09a4cdcf4

需要额外提一点的是:在查找所有用户自定义的配置管理类时需要手动将 cicada内置的 ApplicationConfiguration 加入其中。

因为使用应用的包名通过反射是查询不出该类的。

保存自定义配置管理

为了方便用户在使用时候可以随意的读取各个配置文件,所以还需要将反射创建的对象保存到一个内部缓存中,核心代码就是上上图中的这段代码:

 
 
  1. // add configuration cache

  2. ConfigurationHolder.addConfiguration(aClass.getName(), conf);

其中 ConfigurationHolder 的定义如下。

cf5b1a0a499f9f67e0425f4d93df548d03b52153

其实也是利用一个 Map 来存放这些对象。

这样在使用时候只需要取出即可。

 
 
  1. KafkaConfiguration configuration = (KafkaConfiguration) getConfiguration(KafkaConfiguration.class);

  2. String brokerList = configuration.get("kafka.broker.list");

重构

本次升级同时还重构了部分代码,比如启动类。

现在看上去要清爽和直接的多:

18de435afba90c4b286041f236a49f6e2ef6a1d7

其中也有一点需要注意的地方。

大家如果查看日志的话会发现应用启动之后会打印本次的耗时,自然就是在启动时候记录一个时间,初始化完毕之后记录一个即可。

f44178575706a575f22a2c4d7faa5c559211f967

在之前的实现中由于都是在一个方法内,所以直接使用就行了。

但现在优化之后跨越了不同的方法和类,难道要把时间作为参数在各个方法之前传递嘛?

那未免太不优雅了。

所以 ThreadLocal 就有了发挥余地。

在初始化的方法中我将当前时间写入:

 
 
  1. ThreadLocalHolder.setLocalTime(System.currentTimeMillis());

在最后记录日志的地方直接取出比较即可:

e2b6a11cb039773b5f28a4e54d322fd3673340c2

这样使用起来就完全不需要管什么参数传递了。

同时 ThreadLocalHolder 的定义:

ab69e4d4ae8695412b17315a54e4e88bad212f42

这里还是有一点需要注意,在这种长生命周期的容器中一定得要记得及时清除

我这里的时间在查询一次之后就不用了,所以完全放心的在 getLocalTime() 方法中删掉。

总结

这就是本次 v1.0.2 中的升级内容,包含了配置支持以及代码重构。其中有些内容我觉得对接触少的同学来说还是挺有帮助的。



原文发布时间为:2018-09-14
本文作者:crossoverJie
本文来自云栖社区合作伙伴“crossoverJie”,了解相关信息可以关注“crossoverJie”。
相关文章
|
网络安全 数据安全/隐私保护
FusionCompute 6.5.1 重置 web 登录的 admin 密码
FusionCompute 6.5.1 重置 web 登录的 admin 密码
3772 0
|
3月前
|
人工智能 运维 监控
OpenClaw与悟空引爆“执行通缩”,AI正将企业竞争从“效率之战”推向“决策之争”
当OpenClaw以开源之势让全球30万开发者一夜之间拥有了“7×24小时数字员工”,当悟空CRM将这种执行力封装进销售、财务与客服的每一条标准作业程序时,资本市场却听到了另一声惊雷。过去两年,几乎所有AI叙事都围绕同一个核心展开:AI将替代人类完成工作,但是,当企业真正开始大规模部署AI系统之后,一个更冷静,也更关键的问题浮现出来:如果AI只是替代执行,企业的竞争优势究竟改变了什么?答案并不乐观:几乎没有。真正正在发生的变化,并不在执行层,而在更隐蔽也更关键的地方——决策层。
391 1
|
3月前
|
存储 安全 算法
ThreadLocal 90% 开发者都踩过的坑:底层原理拆解、内存泄漏根治与架构级用法全解
本文深度解析ThreadLocal底层原理(JDK17源码级),直击多线程上下文串号、线程池OOM、traceId传递失效等高频痛点,详解内存泄漏本质(弱引用实为兜底优化)、根治方案(强制remove)及TTL等生产级实践,涵盖用户/trace/事务/数据源四大上下文场景与七大避坑指南。
400 2
|
3月前
|
人工智能 弹性计算 自然语言处理
阿里云学生专属算力包:AI时代下大学生的“数字装备”新选择
阿里云学生专属算力包,19元享高性价比云端AI资源,含练手/毕设/科创三档套餐。配套“AI简历”个人主页,支持视频、交互Demo与GitHub直链,5分钟自然语言一键部署,助力大学生用作品说话,提升就业竞争力。
554 7
|
7月前
|
JavaScript 前端开发 Java
java医院随访系统源码,项目级,可商用
一套基于Spring Boot的医院随访系统源码,自主版权,支持与HIS、EMR对接,实现门诊、住院、体检患者自动化随访。支持电话、短信多渠道随访,提供随访模板、知识库、三级管理、数据分析等功能
221 3
|
人工智能
如何判断某个视频是深度伪造的?
如何判断某个视频是深度伪造的?
1080 0
|
机器学习/深度学习 数据采集 人工智能
ONE-PEACE:探索通往无限模态的通用表征模型
过去几年里,表征模型在自然语言处理、计算机视觉、语音处理等领域取得了巨大的成功。经过大量数据学习的表征模型,不仅可以在各种下游任务上取得良好的效果,还可以作为大规模语言模型(LLM)的基座模型,为LLM提供多模态理解能力。随着多模态技术的发展,尤其CLIP[1]之后大家都意识到一个好的多模态表征模型在很多单模态任务上都会发挥着至关重要的基础模型的作用。学习了大量模态alignment的数据之后的模型逐渐在学会去理解各个模态和模态间蕴含的知识,甚至通过对大量模态的学习促进对其它模态的理解。
22800 7
|
域名解析 弹性计算 网络协议
阿里云服务器搭建网站完整教程(宝塔面板+wordpress)
阿里云服务器搭建网站完整教程(宝塔面板+wordpress)阿里云轻量应用服务器怎么使用?阿里云轻量应用服务器使用教程:轻量应用服务器购买、重置密码、远程连接、宝塔面板的Web环境搭建、WordPress网站程序安装到网站上线,阿里云服务器网分享轻量应用服务器从购买、配置建站环境、轻量服务器应用服务器远程连接、开端口到网站上线全流程
1102 0
|
Java Linux
linux系统卸载原装openjdk,安装自己的jdk
linux系统卸载原装openjdk,安装自己的jdk
439 0
|
安全 Oracle 关系型数据库
记一次安全漏洞处理过程CVE-2018-3252
记一次安全漏洞处理过程CVE-2018-3252
656 0
记一次安全漏洞处理过程CVE-2018-3252