前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于ZooKeeper,Spring设计实现的参数系统

基于ZooKeeper,Spring设计实现的参数系统

作者头像
烂猪皮
发布2018-10-18 11:29:27
9350
发布2018-10-18 11:29:27
举报
文章被收录于专栏:JAVA烂猪皮JAVA烂猪皮

简介

基于ZooKeeper服务端、ZooKeeper Java客户端以及Spring框架设计的用于系统内部进行参数维护的系统。


设计背景

在我们日常开发的系统内部,开发过程中最常见的一项工作便是常用参数的维护,从我学习Java以来,参数的配置多样化,最常见的方式是properties配置文件或者是xml配置文件,高深点的用法是JMX MBean进行参数管理以及数据库参数配置。我们对现有的参数配置方式进行分析,详见下表:

基于上述各类参数配置分析,一番思考设想,设计出如下结构的[参数中心系统](详细设计链接),设计说明查看下一节:


系统设计说明

参数中心系统,顾名思义,主要是将参数集中化,在实际开发中,一个业务的实现需要几个甚至数十个模块联合完成,每个模块都需要进行参数的更新维护,一个模块的参数更新设计缺陷,在进行参数维护时,就可能导致某个业务的中断,故需要将多参数管理统一化管理;统一化的参数管理方式,便可能涉及到了参数数据的统一存储,统一之后便出现了性能瓶颈需求,不然所有鸡蛋装一个篮子里,一出问题全部碎掉;在集中化后,各个模块有自己的参数,有些参数可能仅限单个系统访问,便需要安全的参数访问方式;在参数使用过程中,常见的功能之一便是参数的实时维护;在项目投产过程中,经常因为参数配置问题比如配置错误等情况导致业务中断,故需要一个参数检查表来确认参数的正确性;参数管理整合后,需要方便的操作来实现管理功能。概括一下,参数中心系统需要满足以下技术需求:

  • 多系统、多模式、安全、动态维护的参数配置
  • 个性化话参数配置(普通字符窜,JSON字符窜,数组窜)
  • 低侵入
  • 快捷的参数导入导出功能
  • 便捷的管理方式
  • 上线参数检查表,用于上线时各类参数的检查,防止出错
  • 高可用
  • 安全控制

根据上述分析,设计之初,思考如何实现多系统多模式的参数存储,虽然一直知道ZooKeeper这个东西,但从未详细了解过,偶然机会大致学习了一下ZooKeeper,发现ZooKeeper的各类机制与参数中心系统设计相吻合,比如:多系统多模式的参数存储与ZooKeeper的目录型存储方式相似,查看下面图3-1展示;参数的安全方式认证与ZooKeeper的ACL机制吻合;参数实时维护可以借鉴ZooKeeper的Watcher机制;参数中心系统的高性能高可用设计与ZooKeeper的集群方式相吻合。这样下来,参数中心系统最大的问题参数存储模块服务端得到了完美的解决。接下来的便是基于ZooKeeper设计出对应的客户端,管理端。

图3-1 基于ZooKeeper的参数存储

Java应用端常用的技术之一便是Spring框架,也符合低侵入的设计原则,在使用Spring开发过程中,常用的功能之一便是使用${}引用properties配置文件内的参数,如此方便的参数配置方式,我决定使用类似的方式,配置方式为zk{}(zk表示ZooKeeper参数),故客户端的设计是基于Spring的设计。


系统技术组合

ZooKeeper集群 + ZooKeeper Java客户端 + Spring BeanFactoryPostProcessor扩展点 + JSON字符窜解析 + Spring SpEL表达式


设计实现(重点)

根据上述设计说明等信息,最后得出这样一个系统,基于ZooKeeper参数存储,Spring客户端使用zk{}进行参数配置的参数中心系统。

  • 服务端

服务端设计如3-1图所示(在实际开发过程中可能稍有变动)

  • 客户端(重点)

在进行参数中心系统客户端实现之前,我们先了解一点Spring框架的基础知识。

在Spring框架开发过程中,最常用的配置是<bean/>标签的使用,在工作中,最常听的一种说法是,在xml里配置上就可以使用bean了,就有对象了,这种理解潜在一层含义xml直接配置成了java bean,而实际上,Spring中bean的定义最终表现为BeanDefinition对象,个人理解为xml实际配置的是bean的说明信息,Spring将这些说明信息转换为了BeanDefinition对象,再由BeanDefinition生成了我们最终看到的bean,实际流程为[xml配置->BeanDefinition->Bean]而一般开发者不知道BeanDefinition,故理解含义成了[xml配置->Bean],中间缺少了重要的环节。在BeanDefinition到Bean这个过程中,Spring由BeanFactory生成实际的bean,在实际bean产生前,Spring提供了BeanFactoryPostProcessor扩展点(类似还有BeanPostProcessor),通过该扩展点可以获取到配置的BeanDefinition信息,用于自定义扩展对bean定义变更修改,实现自由控制。

Spring允许开发者实现自定义的扩展点,实现特定的接口,使用通用的配置即可注册一个扩展点到Spring容器内。详细学习参考https://docs.spring.io/spring/docs/4.3.19.RELEASE/spring-framework-reference/htmlsingle/#beans-factory-nature。

参数中心系统参数的配置实现参考了Spring的${}参数配置,我们对${}的实现做简单学习。${}的实现便使用了Spring扩展点BeanFactoryPostProcessor,开发中常见配置如下:

上图中采用了context:property-placeholder标签配置,根据Spring context的xsd说明文件,我们知道了property-placeholder对应的实际类为org.springframework.context.support.PropertySourcesPlaceholderConfigurer,context:property-placeholder配置实际为在spring容器内注册一个扩展点,实现${}表达式的解析。实现类图以及调用流程大致如下,再详细过程查看源码,(有句话叫做师傅领进门,修行在个人):

参数中心系统客户端的实现代码与上述实现类似,不同的是properties配置文件变成了ZooKeeper参数存储,${}变成了zk{}。

客户端项目名称:itwatertop-pczk-client

  • 管理端

基于H5的管理页面设计,详细情况还未设想(先实现了主要的服务端客户端,管理端暂时可以使用ZooKeeper的客户端)。


客户端设计源码

客户端程序结构如下:

文件说明:

  • BaseLoader.java 数据加载基类
  • ZookeeperDataLoader.java Java ZooKeeper客户端实现数据加载,参数更新回调。
  • PlaceholderMsg.java zk{zkexp} zk配置表达式解析结果,以及使用该表达式的bean属性获取SpEL表达式。
  • ParamCenterStore.java 对ZooKeeper参数服务端获取的参数信息做缓存,并且将对应的使用该参数的Bean属性表达式统计,方便ZooKeeper参数变更时回调使用。
  • PczkConstants.java 系统内常量字符窜整合。
  • PczkStringValueResolver.java 表达式解析统一接口
  • PczkPropertyPlaceholderConfiguer.java 实现Spring扩展点BeanFactoryPostProcessor,通过该扩展点对BeanDefinition配置元信息做解析以及变更。
  • PropertyPlaceholderHelper.java 具体实现zk{}表达式解析规则。
  • PczkBeanDefinitionVisitor.java 对Spring IoC容器内的BeanDefinition属性配置信息做解析,主要结合PczkPropertyPlaceholderConfiguer.java使用。
  • test目录下包含一部分测试代码,可以自行查看

客户端代码实现简介:

根据上述需求,客户端代码需要具备的能力包括:

  1. 与ZooKeeper服务器的连通,并获取参数信息
  2. Spring xml中zk{}表达式的解析
  3. 多样化的参数配置,支持字符窜,对象,数组
  4. ZooKeeper参数变更回调,维护参数信息

针对上面4种要求,在开发时使用以下解决办法:

  1. 使用ZooKeeper Java客户端;
  2. 结合Spring的扩展点BeanFactoryPostProcessor;
  3. 在ZooKeeper服务端节点内设置数据时设置字符窜/JSON对象字符窜或者是JSON数组字符窜,客户端使用数据时分别配置为zk{param},zk{param.key},zk{param[i]},通过对zk{}表达式解析判断ZooKeeper参数格式,若为JSON字符窜使用FastJSON对字符窜做解析,访问对应属性值;
  4. 针对参数变更回调,在解析zk{}表达式时拼接出了可以访问到对应bean属性的SpEL表达式,通过SpEL表达式访问bean属性调用setter方法,因此属性操作也受到SpEL表达式的限制。在个别情况下,由于参数的变更可能需要别的一下操作处理,比如重新建立连接,这个可以自行扩展代码,比如比较上一次的值和当前值是否一致,不一致做出新的操作(现在也在设想怎么可以自动识别进行额外操作)。

客户端详细实现源码下载:访问GitHub项目(注释还是比较清晰的)


说明

本人技术有限,上述有错误的理解欢迎指出,共同交流学习,若对上述说明不了解,建议先学习一点Spring IoC设计,学习地址:https://docs.spring.io/spring/docs/4.3.19.RELEASE/spring-framework-reference/htmlsingle,若对于客户端的设计有好的建议可以提出来,共同讨论。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA烂猪皮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档