精华内容
下载资源
问答
  • 集团企业一般都为多元化、综合性企业,业务范围涉及多个行业,具有下属单位众多且地理位置...随着市场业务范围的不断拓展业务量的不断增长,对企业的运作和管理提出了更高的要求。对于集团企业来说,在公司业务蓬...

    集团企业一般都为多元化、综合性企业,业务范围涉及多个行业,具有下属单位众多且地理位置分布较广,经营方式多样化等特点。随着市场业务范围的不断拓展和业务量的不断增长,对企业的运作和管理提出了更高的要求。对于集团企业来说,在公司业务蓬勃发展的同时,对管理信息系统建设也提出了较高的要求,需要不断地获取知识、提升创新能力和深化协同工作以获取成功。

      集团企业办公特点

      集团企业存在多级分公司,组织结构复杂,办公人员较多,办事复杂等。

      集团企业内大量信息散落在不同公司、不同部门、人员等处,不便于迅速发现最关键的信息。

      集体企业应满足不断发展的业务流程需要及时调整。

      大型集团企业公司因有大量下属公司,办公系统必须达到上传下达。

      随着集团公司的不断扩大,管理的复杂度不断提高。

      集团企业越来越重视提高办事效率,规范集团公司管理的重要性。

      集团公司及下属公司需跨系统平台办公。

      集团企业通过办公自动化系统,将员工工作的操作规范化,提高事务处理的效率。

      集团企业面临关键问题

      1、下属子(分)公司涉及多个行业,各子(分)公司的经营行为一般由子(分)公司自行确定,母公司基本只负责确定分配各子(分)公司的主营业务和财务核算。这样虽然控制了集团的财物风险,但对各子(分)公司的实际经营管理过程无法进行实时、有效监控。

      2、集团企业下属的多个子(分)公司中,有些未实现信息化管理,即使已经进行信息化管理的子公司所应用的信息化系统各自独立,不能实现信息的共享,由此产生了信息孤岛、应用孤岛和资源孤岛。

      3、随着企业的规模越来越大,管理流程也越来越复杂,同时也会随着业务不断调整而改变。集团中各公司对业务流程管理和执行相对困难,无法使管理流程规范化、标准化,员工对公司管理流程和管理目的无法清晰的理解。

      4、一直以来最令集团公司管理层困惑的一个问题,就是集团内部"信息不对称"的问题如何得以圆满的解决,也就是"分散经营与集中管理"这对矛盾体的融合问题。具体来说,集团企业在早期对下属子(分)公司比较强调集中管理和控制,随着子公司的快速发展,这种方式给各下属公司带来了对经营极为不利的"信息不对称"的问题,不能很好的适应经营的需要。集团企业为了适应经营需要,将部分决策权下放到各个公司,以促进各项业务的健康发展。但情况也正如预料的一样,在保证了"分散经营"的同时,集中管理、监督控制的力度较以前大为削弱。因此,一直以来集团企业的管理层都在寻找一种更为有效的途径,使"分散经营与集中管理"都能得以实现,将矛盾转化为一种良好的制衡关系。

      集团企业经过长期的实践摸索,清楚的认识到只有提高企业信息化程度,加强企业各种资源的统一管理、监督、调度和协同使用,才是集团企业的生存发展之道。为此,如何借助先进的技术手段及先进的管理思想与方法,建设一套分级管理、协同工作、实时监控、功能完善、技术先进的信息化管理系统,改革与完善原有部分子公司已有的信息化系统独立运行、信息不能实时共享的状况,全面把握集团全局信息,实现科学决策,提升企业竞争力,降低经营风险,就成了摆在集团领导层面前的一道课题。

     

    来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22955023/viewspace-626533/,如需转载,请注明出处,否则将追究法律责任。

    转载于:http://blog.itpub.net/22955023/viewspace-626533/

    展开全文
  • 集中管理的优劣 分布管理的优劣 高内聚低耦合 高内聚 低耦合 总结 现如今,在整个项目开发的过程中模块化以他独特的优势引领了一股项目架构潮流。灵活,可复用,后期易维护,代码逻辑清晰,所有的这些都成为了...

    模块化是不可逆转的趋势

    现如今,在整个项目开发的过程中模块化以他独特的优势引领了一股项目架构潮流。灵活,可复用,后期易维护,代码逻辑清晰,所有的这些都成为了模块化开发的代名词。然而任何一种事物,只要能够被众人所认可,自然有他被认可的理由,从分工管理的角度来看的话这种模块化架构方式是有一定的哲学思想在其中的。

    面向接口编程的优势

    1. 逻辑自定义复用性增强
      好多人会提到面向接口编程,我们知道接口最大的优势就是他方法的逻辑是可以自定义的,我们定义一个接口,然后通过实现该接口可以创建出无数拥有自己内部逻辑的类,最大的优势这些逻辑是由你来定的,从这个角度来看的话定义一个接口可以在很多地方得到运用,这要比你单独去创建若干个类显然要“合算”的多。

    2. 带返回值方法的回调利于封装,模块化
      接口编程的基本流程就是定义接口和抽象方法;创建实现类并在方法的实现中书写逻辑;以接口实现类的方式实例化;调用实现类中写好的方法并在外部传入参数实现数据库的操作。用一句话来总结的话就是封装逻辑,回调方法。

    3. 作为方法参数传值灵活性更强(匿名内部类)
      接口的另外一个优势就是可以作为方法的形参,和其他类型的参数不同的是,以接口为参数我们在传入具体参数值的时候就可以直接以匿名内部类的形式传入相关逻辑,这样就实现了逻辑随处可以自定义的效果,从灵活性的角度来看的话这种方式更具灵活性。
    4. 接口继承实现逻辑的组合
      接口是可以相互继承的,我们完全可以运用接口这种特点,在项目功能模块划分的时候进行有效的分类,接口的这种特点使得模块化开发更加灵活多样。(纵向继承,横向封装)

    集中式管理的优劣

    集中式优点:

    1. 将所有的操作都集中起来,便于配置和查询。
    2. 整合到一起管理起来更加方便。
    3. 配置项一目了然,非常直观。

    缺点:

    1. 高度集中会导致相应的配置文件过于臃肿。
    2. 由于模块配置数据高度集中,无形中文件的健壮性就会大大降低(串并连原理)。
    3. 高集中不代表着高内聚。

    分布管理的优劣

    分布式优点

    1. 灵活性强,模块之间不会相互影响
    2. 类似电路中的并联,使得整个项目的稳定性更强

    分布式缺点

    1. 模块集中程度低不利于统一管理
    2. 分散性给调试带来了不便

    高内聚和低耦合

    高内聚:

    内聚指的是单个模块内部功能的集成程度,可以理解为密度。模块的内聚性强不等同于“大集成”,“大杂烩”。我们要事先明确一个前提,内聚说的是单个功能模块的属性特点,是对单个功能模块的性能进行优化。所以在谈到内聚和耦合的时候我们要干的第一件事情就是要对项目整体进行一个清晰的模块划分,做到没有重合,没有冗余。然后针对单个功能模块进行内聚优化。

    高内聚的优点:

    1. 从模块的角度来看就是项目整体模块功能划分的更细,各司其职,各自为营。
    2. 单个模块内聚程度高 牵连的额外”类”少,不会出现牵一发而动全身的状况,这样就更利于项目后期的变更和维护。
    3. 项目整体分门别类,代码逻辑更加清晰
    4. 代码的复用性和健壮性增强,用一句话来形容就是“事不关己高高挂起”,远离是非之地,那你肯定能活的逍遥快活(健壮性)。

    低耦合:

    低耦合说的是模块与模块之间的一种状态,耦合即关联,耦合性高就是模块之间关联程度高,是唇亡齿寒的关系,也可以理解是电路中的串联,只要有一个模块出问题就会波及关联模块。我们追求的是一种模块各自工作,互不影响的工作状态,就好比并联电路。从项目整体稳定性而言,低耦合的优势显而易见,即便是某一块模块出现了问题也不会影响项目的其他功能。

    总结:

    在理解项目架构优化和模块化开发的优点的时候,我们要本着一个原则那就是最优原则,我们追求高内聚低耦合但也不是任何时候项目都必须要满足这种要求(就好比数据库设计中的忽略第三范式一样),权衡利弊找到一个最佳的平衡点,然后大胆的去对项目的功能模块进行划分,要坚信自己的想法,并用自己的行动去践行自己的创造性思维。

    展开全文
  • 在大型集群分布式应用中,配置不宜分散到节点中,应该集中管理,为各种业务平台提供统一的配置管理服务。 随着业务的发展,应用系统中的配置通常会越来越多,常见的一些应用配置大致会有数据源配置,数据源组件...
    在大型集群和分布式应用中,配置不宜分散到节点中,应该集中管理,为各种业务平台提供统一的配置管理服务。
    随着业务的发展,应用系统中的配置通常会越来越多,常见的一些应用配置大致会有数据源配置,数据源组件配置,业务组件配置等,对于这类配置都会比较稳定且较少变化,通常会放在文件中随应用一起发布。但实际中会有某些配置信息变化有一定频率和规律,并且希望能够做到尽量实时,比如一些营销类,或活动类应用系统,若使用传统的配置文件,加上重新发布应用可能会有些不方便,因此,才有了分布式配置管理平台,旨在能更好地解决这类问题。

    统一配置管理 VS 分布式管理配置
    (中央管理VS去中心化) 

    这个技术话题让我们想起了svn和git之争,统一管理和分布式之间的那些事儿,各有千秋。

     编程开发+脚本 或者借助第三方开源自动化工具 

    spring cloud/dubbo/autoconfig  +docker+k8s+ansible/saltstack  目前业界通用的解决方案

    Disconf+ZooKeeper+Spring (360和淘宝也开源了自己的统一配置管理)
    XXL-CONF
    diablo 
    ansible-playbook
    Fourinone
    saltstack
    DCMP

     推荐用 分布式管理配置  现在开源社区很多  你可以去搜一哈 
    选适合自己的  别人推荐的 不一定是最好的 

     分布式配置管理 - 开源中国社区 https://www.oschina.net/search?scope=all&q=%E5%88%86%E5%B8%83%E5%BC%8F%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86 

    分布式配置管理平台的设计与实现


    随着业务的发展,应用系统中的配置通常会越来越多,常见的一些应用配置大致会有数据源配置,数据源组件配置,业务组件配置等,对于这类配置都会比较稳定且较少变化,通常会放在文件中随应用一起发布。但实际中会有某些配置信息变化有一定频率和规律,并且希望能够做到尽量实时,比如一些营销类,或活动类应用系统,若使用传统的配置文件,加上重新发布应用可能会有些不方便,因此,才有了分布式配置管理平台,旨在能更好地解决这类问题。本文将介绍相关细节,及一个轻量的开源实现(https://github.com/ihaolin/diablo)

    分布式配置平台的一些应用场景

    分布式配置,也即配置中心。通常有以下的场景或需求,可以需要考虑使用分布式配置:

    • 对某些配置的更新,不想要重启应用,并且能近似实时生效;

    • 希望将配置进行统一管理,而非放入各应用的配置文件中;

    • 对于某些应用系统,其某些配置变更比较频繁,规律;

    • 通常配置中心也可作为在其他分布式应用中的感知组件,比如典型的Zookeeper;

    • ...。

    分布式配置平台需要满足的一些基本特性

    对于一个可靠的分布式配置平台,大致应该满足一些基本特性,如:

    • 高可用性:服务器集群应该无单点故障,即只要集群中还有存活的节点,就能提供服务;

    • 容错性:容错性主要针对客户端,应保证即便在配置平台不可用时,也不影响客户端的正常运行;

    • 高性能:对于配置平台,主要操作则是获取配置,不能因为获取配置给应用带来不可接受的损失;

    • 可靠的存储:这包括数据的备份容灾,一致性等,通过数据库和一些运维手段可以解决;

    • 近似实时生效:对于配置的变更,客户端应用能够及时感知;

    • 负载均衡:为了尽量提升服务器集群的性能及稳定性,应尽量保证客户端的请求能尽量均衡负载到各服务器节点;

    • 扩展性:服务器集群应该保证做到无感扩容,以提升集群服务能力;

    • ...。

    分布式配置平台Diablo的设计与实现

    Diablo架构设计

    Diablo的架构设计比较简单轻量,如图:

    • Apps:及各类业务应用实例;

    • Servers:为客户端提供获取配置服务的Server集群;

    • Redis Storage Service:用作数据存储。

    Diablo模型设计

    • 应用(App):通常,对于一个用于各外部系统的平台,都可以抽象这些系统为应用,用于标识或是分组。对于应用环境,个人觉得应交由应用去处理,而不是在平台为各应用提供不同环境,比如可以通过应用名称就能区分不同环境。除此外,通常需要让应用提供一些安全方面的配置,如签名Key,加密Key等,可用于在与外部应用交互中作一些安全处理(如签名,加密等);

    • 配置项(Config):对于配置平台,其数据模型比较简单,核心数据就是配置项。配置项除了基本的配置名称和配置值外,通常还需要有用于判定配置项是否变更的字段,可以用MD5值等。

    对等的服务器集群

    Diablo集群中的Server被视为是对等的,即各节点没有主从(Master/Slave)关系,是逻辑相等的,这样就避免了Master/Slave架构带来的问题,如数据同步延迟,数据丢失等问题。

    高性能处理

    客户端应用获取配置时,仅会从本地缓存中获取,开发人员在控制台更改配置后,会通知客户端刷新缓冲;

    使用Redis作存储

    配置平台本身并没有太多复杂的关联关系,因此使用NoSQL也能满足常用的查询。在设计存储Key上,因尽量保证Key的简洁清晰,比如,存储应用记录,可以以apps:1来标识一条记录,而存储结构最好使用hash,而不是使用JSON字符串。在使用Redis时,diablo避免使用了一些特殊函数,如管道,事务等,因为这些函数在一些Redis的高可用解决方案(如Redis Cluster,Redis Proxy等)中通常不支持,这样用户可以自由使用不同的Redis高可用方案。

    客户端的实现

    • 重试等待:diablo会通过重试等待等机制保证,在服务端集群不可用时,也不会影响客户端应用的正常运行,而是等待集群恢复;

    • 请求负载:为了使服务器集群的各节点的负载尽量均衡,在客户端进行请求处理前,服务端会为客户端分配一个可用的Server节点,后续的请求将在该节点上,这里使用的负载算法是一致性哈希;

    • 额外参数:通常对于客户端实现,在与服务器交互过程中,除了必要的数据外,还会携带一些额外参数,如客户端版本号(为后期作兼容性处理),语言类型(后端可针对不同语言进行处理)等。

    配置更新实时生效

    配置更新实时生效是配置平台的核心功能之一,对于获取配置的方式,大致有两种模式:

    • Pull模式:即客户端主动向服务端拉取配置信息,通常是客户端定时轮询拉取。这种方式最简单稳定,但是存在时间间隔问题,间隔太长,配置延迟更新越大,间隔太短对服务器会造成过多的压力;

    • Push模式:即当配置发生变更时,服务端主动推送更新至各个客户端。这种方式能保证配置更新实时生效,但需要在客户端/服务端建立长链接,服务端需要处理各种异常情况和协议规范,保证更新能实时推送成功,实现起来相对麻烦些。

    diablo使用了特殊Pull模式,即(长轮询)Long Pulling。当客户端发起Http请求后,服务端接收处理完请求,并不会立即返回客户端,而是等待一定条件发生或超时后才返回客户端,这里的一定条件就是当有配置发生变更时,这样就有效减少了客户端请求,也达到了实时生效的目的。对于Java长连接的实现,主要使用了Servlet规范中的AsyncContext,使得服务端接收到请求后,并不会让Servlet容器立即返回客户端,而是当调用AsyncContext.complete()方法时,才会返回。

    客户端语言类型

    diablo默认实现了Java语言的客户端,希望以后能支持node,go,python等语言。由于diablo仅通过Http接口提供服务,不同语言只要遵循API接口,即可实现不同的语言版本。若读者有意实现,可参考该客户端规范,下图为客户端与服务端的交互过程:

    diablo实践建议

    服务器集群部署:对于一个高可用的服务器集群,建议可以nginx等代理服务器作转发,这样在服务器集群发生变化时,客户端应用也不用更新任何配置,如:

    应用环境区分:对于需要区分不同环境的应用,可以通过不同的应用名称作区分,如app_dev,app_test。但对于生产环境,都建议与其他环境隔离,独立部署。

    总结

    以上,则是有关分布式配置管理平台设计与实现的相关细节,也欢迎issue和fork项目diablo。



    [案例分析讲解]

       案例一、  为了更好的解决分布式环境下多台服务实例的配置统一管理问题,本文提出了一套完整的分布式配置管理解决方案。结合.net项目具体情况,实现了配置发布的统一化,对配置进行持久化管理并对外提供restful接口,在此基础上,基于ZooKeeper实现对配置更改的实时推送。系统参考了百度的Disconf,实现和改进了部分功能,是Disconf的.Net精简版,功能有待进一步完善。

    这里主要使用到disconf分布式配置管理平台 支持window和linux下面是大家window环境步骤和一些操作总结。

      所需环境:Windows、nginx1.8.1、redis3.0.5、zookeeper3.4.6、mysql5.7 、python2.7.11、Git-2.6.4-64-bit.exe

    之前一直采用properties文件管理配置信息,若是集群则每个机器上都要拷贝一份,每次修改也需要依次修改。一直在寻找统一修改,实时生效,方便修改,分环境分系统的配置管理,自己也在整理设计,若找不到合意的就准备自己写一个,可以根据自己需求慢慢改进。通过开源中国微博知道了360的配置管理,看了下没大搞明白,貌似管理不太方便,反正不是我想要的,后来知道了百度的disconf,淘宝也有一个配置管理。我先看了百度的disconf,这就是我想要的,所以没看淘宝那个配置管理。

      首先这是一个开源项目,托管在github上,地址: https://github.com/knightliao/disconf,官方的文档还是很丰富的,地址:https://github.com/knightliao/disconf/wiki 。建议先看官方文档,文档很实用,花不了多少时间,我这里仅就官方没说,但刚接触这个的人常见的部分问题说说自己的解决方案,下面是一张运行效果图。

      

      要看这个项目,需要的知识:java相关技术、前端、git、mysql、tomcat、redis、zookeper、nginx,后面几个简单度一下就能了解个大概。

    1. 安装git客户端、下载代码、导入eclipse、运行redis、zookeper、mysql就不说了。
    2. windows上运行sh脚本小知识。
      一看项目内容就知道,这应该只考虑了Linux环境开发,只提供了sh脚本,而很多人都是windows开发环境。其实安装git客户端后,windows下是可以运行sh脚本的。如下图就是git下的sh软件和运行效果,需要先按官方教程配置环境变量,我换系统了所以没配置,之前配置过。

    3. 能不安装nginx吗?
      这是我刚开始在官方讨论群提的问题,得到的答案是不能,提到了什么动静分离,于是百度了解了下,对nginx在这里扮演的角色有了一个了解,知道他做了什么,才能知道他是否必须。了解了之后,就会知道,这里应该有多中方式实现不安装nginx,我实现了一种如下图所示,其他方式可以百度springMVC关于静态文件的处理方式,第一张截图就是我在eclipse中用tomcat运行的结果。这个能方便开发,正式环境建议还是按官方设计的方式使用,nginx对静态文件的处理要比tomcat快不少。
    4. 看交流群讨论,记录如下几点,可以研究下,看怎么修改能解决问题,然后推送官方,也贡献自己的一份力。
      1) 貌似使用spring4时有问题。
      2) 有人建议添加配置优先级,先读取环境变量,再各种配置文件,都没有时提供默认配置。

      由于官方文档比较详细,这里基本没有提到disconf本身的用途,使用方式。建议到处问人前先仔细看看官方教程。

    案例二、

    1.系统设计

    1.1设计理念

          l  简单易用,用户体验良好

          l  支持配置(KV配置项+配置文件)的分布式化管理

          l  配置发布、更新统一化:用户统一在平台上进行发布、更新配置。

          l  配置更新自动化:用户在平台更新配置,使用该配置的系统会自动发现该情况,并应用新配置。

     

          系统结构图如下: 

     

     

          初始化时,业务流程图如下:

     

          配置更新时,业务流程图如下:

     

    1.2.功能介绍

          系统模块架构图如下:

     

    1.2.1Client

      配置管理模块:统一管理用户实例中本地配置文件和配置项

      下载模块:restful风格的下载配置文件和配置项

      watch模块:监控远程配置文件和配置项的变化

    1.2.2Web

    配置管理模块:支持配置模板(配置项或配置文件)的上传、下载、更新

    配置存储模块:管理所有配置的存储和读取,根据appName、version、environment来区分项目配置

    通知模块:当配置更新后,实时通知使用这些配置的所有实例

    权限控制:web用户的权限控制

    2.客户端应用

    2.1添加clientConfig配置节点

    在app.config或者web.config中的configSections节点下添加配置

    <section name=”clientConfig” type=”Disconf.Net.Client.ClientConfigSection,Disconf.Net.Client”/>

    然后在appSettings同级别的节点上添加clientConfig配置,示例如下

    复制代码
    <configSections>
    
     <section name=”clientConfig” type=”Disconf.Net.Client.ClientConfigSection,Disconf.Net.Client”/>
    
    </configSections>
    
    <appSettings file=”appSettings.config”/>
    
    <clientConfig configSource=”clientConfig.config”/>
    复制代码

     

    2.2clientConfig配置说明

    具体示例如下:

    复制代码
    <clientConfig webApiHost=”http://192.168.1.100:8088/” enableRemote=”true”>
    
    <clientInfo appName=”consoletest” environment=”Dev” version=”1.0.0.0” clientName=”Console_1”/>
    
    <updateStrategy fileIgnores="notdown.txt" itemIgnores="aa,bb,cc " startedSync="true" retryTimes="3" retryIntervalSeconds="10" />
    
    <preservation absolutePath="false" tmpRootDirectory="Tmp\Download\Configs" factRootDirectory="" tmpItemsLocalName="~items.xml" tmpFilesLocalName="~files.txt"/>
    
    </clientConfig>
    复制代码

     

     

    节点名称

    必配

    默认值

    节点描述

    webApiHost

     

    Y

     

    Rest服务器域名地址

    enableRemote

     

    N

    true

    是否启用远程配置,默认true,设为false的话表示不从远程服务器下载配置

    clientInfo

    appName

    Y

     

    客户端程序名称,注意大小写要与服务端一致

    environment

    Y

     

    当前客户端程序所处环境,注意大小写要与服务端一致

    version

    Y

     

    当前客户端程序版本,注意大小写要与服务端一致

    clientName

    N

     

    客户端标识,用于服务端查看已更新客户端,如果不设置则默认获取客户端电脑名称

    updateStrategy

    fileIgnores

    N

     

    要忽略更新的文件配置,以,分割,注意大小写要与服务端一致

    itemIgnores

    N

     

    要忽略更新的键值对配置,以,分割,注意大小写要与服务端一致

    startedSync

    N

    true

    启动时是否同步加载,默认同步

    retryTimes

    N

    3

    当获取失败时的重试次数

    retryIntervalSeconds

    N

    10

    每次重试时间间隔,单位秒

    preservation

    absolutePath

    N

    false

    是否绝对路径,默认false。当false时,表示默认以

    AppDomain.CurrentDomain.BaseDirectory为比较点,注意:该配置同时适用于TmpRootDirectory、

    FactRootDirectory,即要么都只能绝对路径,要么都只能相对路径

    tmpRootDirectory

    N

    Tmp/Download/Configs

    下载下来的配置临时保存文件夹根目录

    factRootDirectory

    N

    Configs

    配置文件实际所在的根目录

    tmpItemsLocalName

    N

    ~items.xml

    在临时目录下用于保存所有键值对的文件名,设置为空表示不保存,文件保存在TmpRootDirectory目录下,所以注意不要与

    实际配置文件名字冲突

     

    tmpFilesLocalName

    N

    ~files.txt

    在临时目录下用于保存所有文件配置名的文件名,设置为空表示不保存,文件保存在TmpRootDirectory目录下,所以注意不要与实际配置文件名字冲突

     

    2.3Rules

    除了配置外,还需要设置更新策略,客户端才能进行配置更新。目前,Rules设置仅支持编码的方式进行,Rule分两种:FileRule,ItemRule,下面分别进行描述:

    FileRule:用于设置如何更新文件类型配置,其包含以下方法

    方法名

    描述

    IFileRule MapTo(string refreshSectionName)

    注册Rule规则,设置默认的文件配置映射

    参数refreshSectionName表示更新回调时,

    ConfigurationManager.RefreshSection要刷新的节点名称,默认采用远程配置的configName

    IFileRule RefreshIgnores()

    不自动调用ConfigurationManager.RefreshSection方法更新配置

    IFileRule CallBack(Action action)

    当文件下载完成并且替换本地对应文件后回调,注意此处将采用委托链的方式,即多次调用均会被执行

    ItemRule:用于设置如何更新键值对类型配置,其包含以下方法

    方法名

    描述

    IItemRule MapTo(string propName)

    注册Rule规则,设置默认的属性映射参数

    propName表示要赋值的属性名,默认采用远程的configName

    IItemRule SetProperty<T>(T entity, string propName = null, Func<string, object> typeConvert = null)

    更新指定实体的属性值,按默认方式获取实例属性,注意此处多次调用均会被执行

    IItemRule SetProperty(object entity, PropertyInfo prop, Func<string, object> typeConvert = null)

    更新指定实体的属性值,注意此处多次调用均会被执行

    IItemRule SetStaticProperty<T>(string propName = null, Func<string, object> typeConvert = null)

    更新静态属性的值,按默认方式获取静态属性,注意此处多次调用均会被执行

    IItemRule SetStaticProperty(PropertyInfo prop, Func<string, object> typeConvert = null)

    更新静态属性的值,注意此处多次调用均会被执行

    IItemRule CallBack(Action<string> action)

    当值发生变更时如何进行回调,注意此处将采用委托链的方式,即多次调用均会被执行

    2.4ConfigManager

    该类为Client配置入口,通过Singleton提供唯一实例,除了提供Rules的配置入口外,还提供异常通知的事件

    要使Disconf.Net.Client工作,必须显示执行指定方法manager.Init(),而在init之前,还需设置Rule和Fault,可以通过ConfigManager.Instance来获取该类的实例对象,然后通过对应的Rule进行相关Rule设定,示例如下:

    复制代码
    //要更新的文件
    
    ConfigManager.Instance.FileRules.For("appSettings.config").CallBack(() => {
    
          Console.WriteLine("File changed notice twice");
    
    });
    
    
    //要更新的键值对
    
    ConfigManager.Instance.ItemRules.For("Dai").MapTo("Person").SetStaticProperty<Program>().CallBack(v =>{
    
    Console.WriteLine("Now item value:{0}", v);
    
    Console.WriteLine("Program.Person is {0} now", Program.Person);
    
        if (v.Length > 3)
    
        {
    
            throw new Exception("Too Long");
    
        }
    
    });
    
    
    //忽略更新到本地的键值对
    
    ConfigManager.Instance.ItemRules.For("Peng").CallBack(v =>{
    
    Console.WriteLine("Now item value:{0}", v);
    
    });
    
    
    //异常处理
    
    ConfigManager.Instance.Faulted+=Manager_Faulted;
    
    //Config初始化,包括ZooKeeper、scan等
    
    ConfigManager.Instance.Init();
    复制代码

     

    需要特别说明的是:

    1、File因为属于下载后覆盖指定位置文件的方式,所以对于Rule可以设置默认规则,如例子中的appSettings.config,其对应的就是config文件中的appSettings部分,此时如果不需要进行CallBack调用,且文件名称(去除后缀)部分与Section一致,那么这部分Rule设置可以忽略,程序会在初始化时自动进行默认设置,而对于Item,因为无法确认更新策略,所以如果不设置Rule,那么就算从服务端获取到了值,该部分也只能被忽略。

    2、对于异常部分,程序只是简单的通过Faulted事件来传递异常信息,该事件只有一个Exception类型的参数。

    3.web端应用

    配置步骤:

    1、  创建具体应用(项目)

    2、  创建应用的配置模板(1~n个配置,如appSetting.config、redisconfig.config、rabbitMQConfig.config等配置模板)

    3、  创建应用的环境(如:开发环境、测试环境、仿真环境等),修改相关的配置

    4、  启用对应的配置

    5、  至此,client端就可以获取应用环境对应的所有配置

    3.1登录

    登陆进入配置管理界面

    3.2应用

     

     

    【新建】:填写应用名称,应用描述保存完成新建,返回可返回应用管理首页。

    【初始化ZooKeeper】:第一次启动时Zookeeper初始化。

    【编辑】:与新建界面一致,可修改应用名称,应用描述,保存即返回应用管理首页。

    【编辑环境】:进入环境环境配置管理首页。

    【删除】:删除对应应用记录。

    3.3模板

    显示所有模板,操作环境配置前,需要先配置模板,根据模板对相应环境的配置进行操作。

     

    【新建】:新增模板,填写模板名称、描述、类型、默认值版本号等,如选择文件类型。可上传文件读取文件内容,版本号可以选择已经有的版本号,或者新建版本号。

    【编辑】:操作同新建模板,可对模板内容进行修改。

    【删除】:点击删除可删除对应模板记录,如该模板在环境中存在配置项,则该模板不允许删除,需删除对应该模板的配置项,才可以删除对应模板。

    3.4环境

    【新增环境】点击加号可以新增环境,填写环境名称,描述保存即可。

     

    【编辑环境】在对应环境上点击鼠标右键即可弹出编辑菜单,点击Edit即可编辑环境,可以修改名称内容等。

     

    【配置首页】:配置首页根据版本进行分类,默认显示头部第一个版本,点击其他版本可以进行切换,显示的配置项是模板默认配置项,点击启用即可个性化赋值,针对不同环境进行不同的赋值。编辑可编辑相应配置,禁用等同于删除配置。

     

    【启用配置】:名称默认值不能修改,可以点击使用默认值,直接赋值,也可以上传文件使用文件内容,保存即可。

    【编辑配置】:操作同启用配置,保存即可修改值。

    【禁用配置】:禁用等同于删除配置,删除对应模板配置项,可删除对应模板。

    3.5角色

    【角色首页】:

    Ø  角色首页展示角色列表,角色分为超级管理员和非超级管理员;

    Ø  超级管理员角色不展示;

    Ø  超级管理员可以看到所有非超级管理员角色,非超级管理员只可以看到当前角色用户创建的角色;

    Ø  可以新增角色,也可以对角色进行编辑,只有在创建用户时勾选是否为系统管理员才可以进行角色管理。

    【新建角色】:

    Ø  新建角色输入角色名称,可以勾选的权限为当前用户所拥有的权限;

    Ø  新建的角色作为该用户的下属角色,可分配给当前用户新建的用户;

    Ø  父级权限为新建应用所增加的权限,以后每增加一个环境,就相应的增加该应用下的该环境权限,除超级管理员外的角色需对应勾选该权限才能看到该应用或者该权限,保存角色即可。

    【编辑角色】:操作同新建角色,可以对该角色进行名称修改,权限修改。

    3.6用户

    管理用户首页,显示所有用户,可进行新建,编辑用户等操作。

     

    【新建用户】:填写姓名,用户名,密码,选择角色(拥有对应角色权限、且可以选择的角色为当前登陆用户新建的角色),选择是否为系统管理员(系统管理员拥有新建用户、新建角色权限),保存即可。

    【编辑用户】:操作同新建用户,保存即可修改。


    案例三、

    《分布式配置管理平台XXL-CONF》

    一、简介

    1.1 概述

    XXL-CONF 是一个分布式配置管理平台,其核心设计目标是“为分布式业务提供统一的配置管理服务”。现已开放源代码,开箱即用。

    1.2 特性

    • 1、简单易用: 上手非常简单, 只需要引入maven依赖和一行配置即可;
    • 2、在线管理: 提供配置管理中心, 支持在线管理配置信息;
    • 3、实时推送: 配置信息更新后, Zookeeper实时推送配置信息, 项目中配置数据会实时更新并生效, 不需要重启线上机器;
    • 4、高性能: 系统会对Zookeeper推送的配置信息, 在Encache中做本地缓存, 在接受推送更新或者缓存失效时会及时更新缓存数据, 因此业务中对配置数据的查询并不存在性能问题;
    • 5、配置备份: 配置数据首先会保存在Zookeeper中, 同时, 在MySQL中会对配置信息做备份, 保证配置数据的安全性;
    • 6、HA: 配置中心基于Zookeeper集群, 只要集群节点保证存活数量大于N/2+1, 就可保证服务稳定, 避免单点风险;
    • 7、分布式: 可方便的接入线上分布式部署的各个业务线, 统一管理配置信息;
    • 8、配置共享: 平台中的配置信息针对各个业务线是平等的, 各个业务线可以共享配置中心的配置信息, 当然也可以配置业务内专属配置信息;
    • 9、配置分组: 支持对配置进行分组管理, 每条配置将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    1.3 背景

    why not properties

    常规项目开发过程中, 通常会将配置信息位于在项目resource目录下的properties文件文件中, 配置信息通常包括有: jdbc地址配置、redis地址配置、活动开关、阈值配置、黑白名单……等等。使用properties维护配置信息将会导致以下几个问题:

    • 1、需要手动修改properties文件;
    • 2、需要重新编译打包;
    • 3、需要重启线上服务器 (项目集群时,更加令人崩溃) ;
    • 4、配置生效不及时: 因为流程复杂, 新的配置生效需要经历比较长的时间才可以生效;
    • 5、不同环境上线包不一致: 例如JDBC连接, 不同环境需要差异化配置;

    why XXL-CONF

    • 1、不需要 (手动修改properties文件) : 在配置管理中心提供的Web界面中, 定位到指定配置项, 输入新的配置的值, 点击更新按钮即可;
    • 2、不需要 (重新编译打包) : 配置更新后, 实时推送新配置信息至项目中, 不需要编译打包;
    • 3、不需要 (重启线上服务器) : 配置更新后, 实时推送新配置信息至项目中, 实时生效, 不需要重启线上机器; (在项目集群部署时, 将会节省大量的时间, 避免了集群机器一个一个的重启, 费时费力)
    • 4、配置生效 "非常及时" : 点击更新按钮, 新的配置信息将会即可推送到项目中, 瞬间生效, 非常及时。比如一些开关类型的配置, 配置变更后, 将会立刻推送至项目中并生效, 相对常规配置修改繁琐的流程, 及时性可谓天壤之别;
    • 5、不同环境 "同一个上线包" : 因为差异化的配置托管在配置中心, 因此一个上线包可以复用在生产、测试等各个运行环境, 提供能效;

    1.4 下载

    源码地址 (将会在两个git仓库同步发布最新代码)
    中央仓库地址 (最新Release版本)
    <dependency>
      <groupId>com.xuxueli</groupId>
      <artifactId>xxl-conf-core</artifactId>
      <version>1.3.0</version>
    </dependency>
    
    博客地址 (将会在两个博客同步更新文档)
    技术交流群 (仅作技术交流)
    • 群4:464762661 image
    • 群3:242151780 (群即将满,请加群4)
    • 群2:438249535 (群即将满,请加群4)
    • 群1:367260654 (群即将满,请加群4)

    1.5 环境

    • Maven3+
    • Jdk1.7+
    • Tomcat7+
    • Zookeeper3.4+
    • Mysql5.5+

    二、快速入门

    2.1 初始化“数据库”

    请下载项目源码并解压,获取 "调度数据库初始化SQL脚本" 并执行即可。脚本位置如下:

    xxl-conf/db/xxl-conf.sql
    

    2.2 编译源码

    解压源码,按照maven格式将源码导入IDE, 使用maven进行编译即可,源码结构如下图所示:

    输入图片说明

    • xxl-conf-admin:配置管理中心
    • xxl-conf-core:公共依赖
    • xxl-conf-example: 接入XXl-CONF的Demo项目

    2.3 “配置管理中心” 项目配置

    项目:xxl-conf-admin
    作用:管理线上配置信息
    

    配置文件位置:

    xxl-conf/xxl-conf-admin/src/main/resources/xxl-config-admin.properties
    

    配置项目说明:

    # xxl-conf, zk address  (配置中心zookeeper集群地址,如有多个地址用逗号分隔)
    xxl.conf.zkserver=127.0.0.1:2181
    
    # xxl-conf, jdbc    (配置中心mysql地址)
    xxl.conf.jdbc.driverClass=com.mysql.jdbc.Driver
    xxl.conf.jdbc.url=jdbc:mysql://localhost:3306/xxl-conf?Unicode=true&amp;characterEncoding=UTF-8
    xxl.conf.jdbc.username=root
    xxl.conf.jdbc.password=root_pwd
    
    # xxl-conf, admin login (管理中心登录账号密码)
    xxl.conf.login.username=admin
    xxl.conf.login.password=123456
    

    2.4 “接入XXL-CONF的Demo项目” 项目配置

    项目:xxl-conf-example
    作用:供用户参考学习如何接入XXL-CONF
    
    A、引入maven依赖
    <!-- xxl-conf-client -->
    <dependency>
        <groupId>com.xuxueli</groupId>
        <artifactId>xxl-conf-core</artifactId>
        <version>${xxl.conf.version}</version>
    </dependency>
    
    B、配置 “XXL-CONF配置解析器”

    可参考配置文件:

    /xxl-conf/xxl-conf-example/src/main/resources/spring/applicationcontext-xxl-conf.xml
    

    配置项说明

    <!-- XXL-CONF配置解析器 -->
    <bean id="xxlConfPropertyPlaceholderConfigurer" class="com.xxl.conf.core.spring.XxlConfPropertyPlaceholderConfigurer" />
    
    C、设置 "xxl-conf.properties"

    可参考配置文件:

    /xxl-conf/xxl-conf-example/src/main/resources/xxl-conf.properties
    

    配置项说明

    # xxl-conf, zk address  (配置中心zookeeper集群地址,如有多个地址用逗号分隔)
    xxl.conf.zkserver=127.0.0.1:2181
    

    该配置文件,除了支持配置ZK地址,还可以配置一些本地配置。 XXL-CONF 加载配置时会优先加载 "xxl-conf.properties" 中的配置, 然后才会加载ZK中的配置。可以将一些希望存放本地的配置存放在该文件。

    2.5 新增配置分组

    输入图片说明

    每个配置分组对应一个唯一的GroupName,作为该分组下配置的统一前缀。在“分组管理”栏目可以创建并管理配置分组信息,系统已经提供一个默认分组.

    2.6 新增配置信息

    登录"配置管理中心"

    输入图片说明

    进入"配置管理界面",点击"新增配置"按钮

    输入图片说明

    在弹出界面,填写配置信息

    输入图片说明

    至此, 一条配置信息已经添加完成.

    通过client端,可以实时获取配置信息, 通过本地已经加载过得配置将会接受Zookeeper的更新推送, 如下如日志:

    输入图片说明

    2.7 项目中使用XXL-CONF

    项目: xxl-conf-example:   (可以参考 com.xxl.conf.example.controller.IndexController.index() )
    作用: 接入XXl-CONF的Demo项目
    
    • 方式1: XML文件中的占位符方式

      <bean id="configuration" class="com.xxl.conf.example.core.constant.Configuration">
          <property name="paramByXml" value="${default.key01}" />
      </bean>
      

      特点:

      • 上面配置说明: 在项目启动时, Configuration的paramByXml属性, 会根据配置的占位符${default.key01}, 去XXL-CONF中匹配KEY=key01的配置信息, 赋值给paramByXml;
      • 目前, 该方式配置信息, 只会在项目启动时从XXL-CONF中加载一次, 项目启动后该值不会变更。 例如配置数据连接信息, 如果XXL-CONF平台中连接地址配置改边, 需要重启后才生效;
      • 该方式, 底层本质上是通过 "方式2: API方式" 实现的。
    • 方式2: API方式

      String paramByClient = XxlConfClient.get("default.key02", null);
      

      特点:

      • 上面代码说明: 会获取XXL-CONF平台中KEY=default.key02的配置信息, 如果不存在值使用传递的默认值;
      • 因为Zookeeper会实时推送配置更新到客户端, 因此该方法放回的值可以XXL-CONF平台中的值保持实时一致;
      • XXL-CONF会对Zookeeper推送的配置信息做本地缓存, 该方法查询的是缓存的配置信息, 因此该方法并不会产生性能问题, 使用时不需要考虑性能问题;

    三、总体设计

    3.1 架构图

    输入图片说明

    3.2 "配置项" 设计

    系统配置信息以K/V的形式存在, "配置项" 属性如下:

    • 分组: "配置项" 的分组, 便于配置分组管理;
    • KEY : "配置项" 的全局唯一标识, 对应一条配置信息;
    • VALUE : "配置项" 中保存的数据信息, 仅仅支持String字符串格式;
    • 描述 : 配置项的描述信息;

    每条配置,将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    3.3 "配置中心" 设计

    输入图片说明

    • 1、ZK设计: 系统在ZK集群中占用一个根目录 "/xxl-conf", 每新增一条配置项, 将会在该目录下新增一个子节点。结构如下图, 当配置变更时将会触发ZK节点的变更, 将会触发对应类型的ZK广播。
    • 2、数据库备份配置信息: 配置信息在ZK中的新增、变更等操作, 将会同步备份到Mysql中, 进一步保证数据的安全性;
    • 3、配置推送: 配置推送功能在ZK的Watch机制实现。Client在加载一条配置信息时将会Watch该配置对应的ZK节点, 因此, 当对该配置项进行配置更新等操作时, 将会触发ZK的NodeDataChanged广播, Client竟会立刻得到通知并刷新本地缓存中的配置信息;

    ZK之watcher普及(来源官方文档,以及网络博客)

    1、可以注册watcher的方法:getData、exists、getChildren。
    2、可以触发watcher的方法:create、delete、setData。连接断开的情况下触发的watcher会丢失。
    3、一个Watcher实例是一个回调函数,被回调一次后就被移除了。如果还需要关注数据的变化,需要再次注册watcher。
    4、New ZooKeeper时注册的watcher叫default watcher,它不是一次性的,只对client的连接状态变化作出反应。(推荐ZK初始化时, 主动Watcher如exists)
    5、实现永久监听: 由于zookeeper是一次性监听,所以我们必须在wather的process方法里面再设置监听。
    6、getChildren("/path")监视/path的子节点,如果(/path)自己删了,也会触发NodeDeleted事件。
    
    《操作--事件》 event For “/path” event For “/path/child”
    create(“/path”) EventType.NodeCreated
    delete(“/path”) EventType.NodeDeleted
    setData(“/path”) EventType.NodeDataChanged
    create(“/path/child”) EventType.NodeChildrenChanged(getChild) EventType.NodeCreated
    delete(“/path/child”) EventType.NodeChildrenChanged(getChild) EventType.NodeDeleted
    setData(“/path/child”) EventType.NodeDataChanged

    《事件--Watch方式》 | Default Watcher | exists(“/path”) | getData(“/path”) | getChildren(“/path”) --- | --- | --- | --- EventType.None | 触发 | 触发 | 触发 | 触发 EventType.NodeCreated | | 触发 | 触发 |
    EventType.NodeDeleted | | 触发 | 触发 | EventType.NodeDataChanged | | 触发 | 触发 | EventType.NodeChildrenChanged | | | | 触发

    ZooKeeper的一个性能测试

    测试数据来自阿里中间件团队

    ZK集群情况: 3台ZooKeeper服务器。8核64位jdk1.6;log和snapshot放在不同磁盘;

    • 场景一: pub创建NODE,随后删除

      • 操作: 同一个目录下,先create EPHEMERAL node,再delete;create和delete各计一次更新。没有订阅。一个进程开多个连接,每个连接绑定一个线程,在多个path下做上述操作;不同的连接操作的path不同
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-14723-82, 1024-7677-280, 4096-2037-1585;
    • 场景二: pub创建NODE, sub订阅并获取数据

      • 操作: 一个进程开多个连接,每连接一个线程,每个连接在多个path下做下述操作;不同的连接操作的path不同。每个path有3个订阅者连接,一个修改者连接。先全部订阅好。然后每个修改者在自己的每个path下创建一个EPHEMERAL node,不删除;创建前记录时间,订阅者收到event后记录时间(eventStat);重新get到数据后再记录时间(dataStat)。共1000个pub连接,3000个sub连接,20W条数据。收到通知后再去读取数据,五台4核client机器。
      • 结果汇总: getAfterNotify=false(只收事件,受到通知后不去读取数据);五台4核client机器
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-1W+-256ms, 1024-1W+-256, 2048-1W+-270, 4096-8000+-520;
    • 场景三: pub创建NODE,随后设置数据

      • 一个进程开多个连接,每连接一个线程,每个连接在多个path下做下述操作;不同的连接操作的path不同。每个path有一个修改者连接,没有订阅者。每个修改者在自己的每个path下设置数据。
      • 结果汇总: getAfterNotify=false(只收事件,受到通知后不去读取数据);五台4核client机器
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-14723-82, 1024-7677-280, 4096-2037-1585 ;

    总结: 由于一致性协议带来的额外网络交互,消息开销,以及本地log的IO开销,再加上ZK本身每1000条批量处理1次的优化策略,写入的平均响应时间总会在50-60ms之上。但是整体的TPS还是可观的。单个写入数据的体积越大,响应时间越长,TPS越低,这也是普遍规律了。压测过程中log文件对磁盘的消耗很大。实际运行中应该使用自动脚本定时删除历史log和snapshot文件。

    3.4 "配置管理中心" 设计

    "配置管理中心" 是 "配置中心" 的上层封装, 提供Web界面供用户对配置信息进行配置查询、配置新增、配置更新和配置删除等操作;

    3.5 "客户端" 设计

    输入图片说明

    API方式加载配置: 客户端主要分为三层:

    • ZK-Client : 第一层为ZK远程客户端的封装, 当业务方项目初始化某一个用到的配置项时, 将会触发ZK-Client对该配置对应节点的Watch, 因此当该节点变动时将会监听到ZK的类似NodeDataChanged的广播, 可以实时获取最新配置信息;
    • Ehcache : 第二层为客户端本地缓存, 可以大大提高系统的并发能力, 当配置初始化或者接受到ZK-Client的配置变更时, 将会把配置信息缓存只Encache中, 业务中针对配置的查询都是读缓存方式实现, 降低对ZK集群的压力;
    • Client-API : 第三层为暴露给业务方使用API, 简单易用, 一行代码获取配置信息, 同时可保证API获取到的配置信息是实时最新的配置信息;

    (API方式加载配置, 因为底层做了配置本地缓存, 因此可以放心应用在业务代码中, 不必担心并发压力。完整的支持配置实时推送更新)

    输入图片说明

    Bean方式加载配置:

    系统会在Spring容器中追加一个"PropertyPlaceholderConfigurer"属性解析器, 内部通过自定义的"StringValueResolver"解析器解析配置占位符 "${...}", 匹配到的配置信息将调用"XXL-CFONF"的API客户端加载最新配置信息进行Bean对象的属性赋值,最终完成实例化过程。

    (Bean方式加载配置,仅仅在实例化时加载一次; 考虑都实例化后的对象通常为持久化对象, 如数据库连接池对象, 不建议配置的太灵活, 因此Bean类型配置更新需要重启机器)

    四、历史版本

    4.1 版本1.1.0新特性

    • 1、简单易用: 上手非常简单, 只需要引入maven依赖和一行配置即可;
    • 2、在线管理: 提供配置管理中心, 支持在线管理配置信息;
    • 3、实时推送: 配置信息更新后, Zookeeper实时推送配置信息, 项目中配置数据会实时更新并生效, 不需要重启线上机器;
    • 4、高性能: 系统会对Zookeeper推送的配置信息, 在Encache中做本地缓存, 在接受推送更新或者缓存失效时会及时更新缓存数据, 因此业务中对配置数据的查询并不存在性能问题;
    • 5、配置备份: 配置数据首先会保存在Zookeeper中, 同时, 在MySQL中会对配置信息做备份, 保证配置数据的安全性;
    • 6、HA: 配置中心基于Zookeeper集群, 只要集群节点保证存活数量大于N/2+1, 就可保证服务稳定, 避免单点风险;
    • 7、分布式: 可方便的接入线上分布式部署的各个业务线, 统一管理配置信息;
    • 8、配置共享: 平台中的配置信息针对各个业务线是平等的, 各个业务线可以共享配置中心的配置信息, 当然也可以配置业务内专属配置信息;

    4.2 版本1.2.0新特性

    • 1、配置分组: 支持对配置进行分组管理, 每条配置将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    4.3 版本1.3.0新特性

    • 1、支持在线维护配置分组;
    • 2、项目groupId从com.xxl迁移至com.xuxueli,为推送maven中央仓库做准备;
    • 3、v1.3.0版本开始,推送公共依赖至中央仓库;

    4.4 版本1.3.1新特性(Coding)

    • zookeeper地址方式从磁盘迁移至项目内;

    TODO LIST

    • 1、权限管理:以分组为权限最小单元,只有分组的成员用户才有权限进行对应的配置操作;
    • 2、zookeeper客户端优化, 或将改用zkclient或者curator;
    • 3、local cache 备份到磁盘;zk异常且local properties未配置时,从磁盘上读取配置;

    五、其他

    5.1 报告问题

    XXL-CONF托管在Github上,如有问题可在 ISSUES 上提问,也可以加入上文技术交流群;

    5.2 接入登记

    更多接入公司,欢迎在github 登记


    案例四、

    DCMP 详细介绍

    DCMP是分布式配置管理平台。提供了一个etcd的管理界面,可通过界面修改配置信息,借助confd可实现配置文件的同步。

    安装 && 启动

    > go get github.com/silenceper/dcmp
    > ./service.sh

    界面预览

    访问 http://127.0.0.1:8000/


    Ø  超级管理员角色不展示;

    Ø  超级管理员可以看到所有非超级管理员角色,非超级管理员只可以看到当前角色用户创建的角色;

    Ø  可以新增角色,也可以对角色进行编辑,只有在创建用户时勾选是否为系统管理员才可以进行角色管理。

    【新建角色】:

    Ø  新建角色输入角色名称,可以勾选的权限为当前用户所拥有的权限;

    Ø  新建的角色作为该用户的下属角色,可分配给当前用户新建的用户;

    Ø  父级权限为新建应用所增加的权限,以后每增加一个环境,就相应的增加该应用下的该环境权限,除超级管理员外的角色需对应勾选该权限才能看到该应用或者该权限,保存角色即可。

    【编辑角色】:操作同新建角色,可以对该角色进行名称修改,权限修改。

    3.6用户

    管理用户首页,显示所有用户,可进行新建,编辑用户等操作。

     

    【新建用户】:填写姓名,用户名,密码,选择角色(拥有对应角色权限、且可以选择的角色为当前登陆用户新建的角色),选择是否为系统管理员(系统管理员拥有新建用户、新建角色权限),保存即可。

    【编辑用户】:操作同新建用户,保存即可修改。


    案例三、

    《分布式配置管理平台XXL-CONF》

    一、简介

    1.1 概述

    XXL-CONF 是一个分布式配置管理平台,其核心设计目标是“为分布式业务提供统一的配置管理服务”。现已开放源代码,开箱即用。

    1.2 特性

    • 1、简单易用: 上手非常简单, 只需要引入maven依赖和一行配置即可;
    • 2、在线管理: 提供配置管理中心, 支持在线管理配置信息;
    • 3、实时推送: 配置信息更新后, Zookeeper实时推送配置信息, 项目中配置数据会实时更新并生效, 不需要重启线上机器;
    • 4、高性能: 系统会对Zookeeper推送的配置信息, 在Encache中做本地缓存, 在接受推送更新或者缓存失效时会及时更新缓存数据, 因此业务中对配置数据的查询并不存在性能问题;
    • 5、配置备份: 配置数据首先会保存在Zookeeper中, 同时, 在MySQL中会对配置信息做备份, 保证配置数据的安全性;
    • 6、HA: 配置中心基于Zookeeper集群, 只要集群节点保证存活数量大于N/2+1, 就可保证服务稳定, 避免单点风险;
    • 7、分布式: 可方便的接入线上分布式部署的各个业务线, 统一管理配置信息;
    • 8、配置共享: 平台中的配置信息针对各个业务线是平等的, 各个业务线可以共享配置中心的配置信息, 当然也可以配置业务内专属配置信息;
    • 9、配置分组: 支持对配置进行分组管理, 每条配置将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    1.3 背景

    why not properties

    常规项目开发过程中, 通常会将配置信息位于在项目resource目录下的properties文件文件中, 配置信息通常包括有: jdbc地址配置、redis地址配置、活动开关、阈值配置、黑白名单……等等。使用properties维护配置信息将会导致以下几个问题:

    • 1、需要手动修改properties文件;
    • 2、需要重新编译打包;
    • 3、需要重启线上服务器 (项目集群时,更加令人崩溃) ;
    • 4、配置生效不及时: 因为流程复杂, 新的配置生效需要经历比较长的时间才可以生效;
    • 5、不同环境上线包不一致: 例如JDBC连接, 不同环境需要差异化配置;

    why XXL-CONF

    • 1、不需要 (手动修改properties文件) : 在配置管理中心提供的Web界面中, 定位到指定配置项, 输入新的配置的值, 点击更新按钮即可;
    • 2、不需要 (重新编译打包) : 配置更新后, 实时推送新配置信息至项目中, 不需要编译打包;
    • 3、不需要 (重启线上服务器) : 配置更新后, 实时推送新配置信息至项目中, 实时生效, 不需要重启线上机器; (在项目集群部署时, 将会节省大量的时间, 避免了集群机器一个一个的重启, 费时费力)
    • 4、配置生效 "非常及时" : 点击更新按钮, 新的配置信息将会即可推送到项目中, 瞬间生效, 非常及时。比如一些开关类型的配置, 配置变更后, 将会立刻推送至项目中并生效, 相对常规配置修改繁琐的流程, 及时性可谓天壤之别;
    • 5、不同环境 "同一个上线包" : 因为差异化的配置托管在配置中心, 因此一个上线包可以复用在生产、测试等各个运行环境, 提供能效;

    1.4 下载

    源码地址 (将会在两个git仓库同步发布最新代码)
    中央仓库地址 (最新Release版本)
    <dependency>
      <groupId>com.xuxueli</groupId>
      <artifactId>xxl-conf-core</artifactId>
      <version>1.3.0</version>
    </dependency>
    
    博客地址 (将会在两个博客同步更新文档)
    技术交流群 (仅作技术交流)
    • 群4:464762661 image
    • 群3:242151780 (群即将满,请加群4)
    • 群2:438249535 (群即将满,请加群4)
    • 群1:367260654 (群即将满,请加群4)

    1.5 环境

    • Maven3+
    • Jdk1.7+
    • Tomcat7+
    • Zookeeper3.4+
    • Mysql5.5+

    二、快速入门

    2.1 初始化“数据库”

    请下载项目源码并解压,获取 "调度数据库初始化SQL脚本" 并执行即可。脚本位置如下:

    xxl-conf/db/xxl-conf.sql
    

    2.2 编译源码

    解压源码,按照maven格式将源码导入IDE, 使用maven进行编译即可,源码结构如下图所示:

    输入图片说明

    • xxl-conf-admin:配置管理中心
    • xxl-conf-core:公共依赖
    • xxl-conf-example: 接入XXl-CONF的Demo项目

    2.3 “配置管理中心” 项目配置

    项目:xxl-conf-admin
    作用:管理线上配置信息
    

    配置文件位置:

    xxl-conf/xxl-conf-admin/src/main/resources/xxl-config-admin.properties
    

    配置项目说明:

    # xxl-conf, zk address  (配置中心zookeeper集群地址,如有多个地址用逗号分隔)
    xxl.conf.zkserver=127.0.0.1:2181
    
    # xxl-conf, jdbc    (配置中心mysql地址)
    xxl.conf.jdbc.driverClass=com.mysql.jdbc.Driver
    xxl.conf.jdbc.url=jdbc:mysql://localhost:3306/xxl-conf?Unicode=true&amp;characterEncoding=UTF-8
    xxl.conf.jdbc.username=root
    xxl.conf.jdbc.password=root_pwd
    
    # xxl-conf, admin login (管理中心登录账号密码)
    xxl.conf.login.username=admin
    xxl.conf.login.password=123456
    

    2.4 “接入XXL-CONF的Demo项目” 项目配置

    项目:xxl-conf-example
    作用:供用户参考学习如何接入XXL-CONF
    
    A、引入maven依赖
    <!-- xxl-conf-client -->
    <dependency>
        <groupId>com.xuxueli</groupId>
        <artifactId>xxl-conf-core</artifactId>
        <version>${xxl.conf.version}</version>
    </dependency>
    
    B、配置 “XXL-CONF配置解析器”

    可参考配置文件:

    /xxl-conf/xxl-conf-example/src/main/resources/spring/applicationcontext-xxl-conf.xml
    

    配置项说明

    <!-- XXL-CONF配置解析器 -->
    <bean id="xxlConfPropertyPlaceholderConfigurer" class="com.xxl.conf.core.spring.XxlConfPropertyPlaceholderConfigurer" />
    
    C、设置 "xxl-conf.properties"

    可参考配置文件:

    /xxl-conf/xxl-conf-example/src/main/resources/xxl-conf.properties
    

    配置项说明

    # xxl-conf, zk address  (配置中心zookeeper集群地址,如有多个地址用逗号分隔)
    xxl.conf.zkserver=127.0.0.1:2181
    

    该配置文件,除了支持配置ZK地址,还可以配置一些本地配置。 XXL-CONF 加载配置时会优先加载 "xxl-conf.properties" 中的配置, 然后才会加载ZK中的配置。可以将一些希望存放本地的配置存放在该文件。

    2.5 新增配置分组

    输入图片说明

    每个配置分组对应一个唯一的GroupName,作为该分组下配置的统一前缀。在“分组管理”栏目可以创建并管理配置分组信息,系统已经提供一个默认分组.

    2.6 新增配置信息

    登录"配置管理中心"

    输入图片说明

    进入"配置管理界面",点击"新增配置"按钮

    输入图片说明

    在弹出界面,填写配置信息

    输入图片说明

    至此, 一条配置信息已经添加完成.

    通过client端,可以实时获取配置信息, 通过本地已经加载过得配置将会接受Zookeeper的更新推送, 如下如日志:

    输入图片说明

    2.7 项目中使用XXL-CONF

    项目: xxl-conf-example:   (可以参考 com.xxl.conf.example.controller.IndexController.index() )
    作用: 接入XXl-CONF的Demo项目
    
    • 方式1: XML文件中的占位符方式

      <bean id="configuration" class="com.xxl.conf.example.core.constant.Configuration">
          <property name="paramByXml" value="${default.key01}" />
      </bean>
      

      特点:

      • 上面配置说明: 在项目启动时, Configuration的paramByXml属性, 会根据配置的占位符${default.key01}, 去XXL-CONF中匹配KEY=key01的配置信息, 赋值给paramByXml;
      • 目前, 该方式配置信息, 只会在项目启动时从XXL-CONF中加载一次, 项目启动后该值不会变更。 例如配置数据连接信息, 如果XXL-CONF平台中连接地址配置改边, 需要重启后才生效;
      • 该方式, 底层本质上是通过 "方式2: API方式" 实现的。
    • 方式2: API方式

      String paramByClient = XxlConfClient.get("default.key02", null);
      

      特点:

      • 上面代码说明: 会获取XXL-CONF平台中KEY=default.key02的配置信息, 如果不存在值使用传递的默认值;
      • 因为Zookeeper会实时推送配置更新到客户端, 因此该方法放回的值可以XXL-CONF平台中的值保持实时一致;
      • XXL-CONF会对Zookeeper推送的配置信息做本地缓存, 该方法查询的是缓存的配置信息, 因此该方法并不会产生性能问题, 使用时不需要考虑性能问题;

    三、总体设计

    3.1 架构图

    输入图片说明

    3.2 "配置项" 设计

    系统配置信息以K/V的形式存在, "配置项" 属性如下:

    • 分组: "配置项" 的分组, 便于配置分组管理;
    • KEY : "配置项" 的全局唯一标识, 对应一条配置信息;
    • VALUE : "配置项" 中保存的数据信息, 仅仅支持String字符串格式;
    • 描述 : 配置项的描述信息;

    每条配置,将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    3.3 "配置中心" 设计

    输入图片说明

    • 1、ZK设计: 系统在ZK集群中占用一个根目录 "/xxl-conf", 每新增一条配置项, 将会在该目录下新增一个子节点。结构如下图, 当配置变更时将会触发ZK节点的变更, 将会触发对应类型的ZK广播。
    • 2、数据库备份配置信息: 配置信息在ZK中的新增、变更等操作, 将会同步备份到Mysql中, 进一步保证数据的安全性;
    • 3、配置推送: 配置推送功能在ZK的Watch机制实现。Client在加载一条配置信息时将会Watch该配置对应的ZK节点, 因此, 当对该配置项进行配置更新等操作时, 将会触发ZK的NodeDataChanged广播, Client竟会立刻得到通知并刷新本地缓存中的配置信息;

    ZK之watcher普及(来源官方文档,以及网络博客)

    1、可以注册watcher的方法:getData、exists、getChildren。
    2、可以触发watcher的方法:create、delete、setData。连接断开的情况下触发的watcher会丢失。
    3、一个Watcher实例是一个回调函数,被回调一次后就被移除了。如果还需要关注数据的变化,需要再次注册watcher。
    4、New ZooKeeper时注册的watcher叫default watcher,它不是一次性的,只对client的连接状态变化作出反应。(推荐ZK初始化时, 主动Watcher如exists)
    5、实现永久监听: 由于zookeeper是一次性监听,所以我们必须在wather的process方法里面再设置监听。
    6、getChildren("/path")监视/path的子节点,如果(/path)自己删了,也会触发NodeDeleted事件。
    
    《操作--事件》 event For “/path” event For “/path/child”
    create(“/path”) EventType.NodeCreated
    delete(“/path”) EventType.NodeDeleted
    setData(“/path”) EventType.NodeDataChanged
    create(“/path/child”) EventType.NodeChildrenChanged(getChild) EventType.NodeCreated
    delete(“/path/child”) EventType.NodeChildrenChanged(getChild) EventType.NodeDeleted
    setData(“/path/child”) EventType.NodeDataChanged

    《事件--Watch方式》 | Default Watcher | exists(“/path”) | getData(“/path”) | getChildren(“/path”) --- | --- | --- | --- EventType.None | 触发 | 触发 | 触发 | 触发 EventType.NodeCreated | | 触发 | 触发 |
    EventType.NodeDeleted | | 触发 | 触发 | EventType.NodeDataChanged | | 触发 | 触发 | EventType.NodeChildrenChanged | | | | 触发

    ZooKeeper的一个性能测试

    测试数据来自阿里中间件团队

    ZK集群情况: 3台ZooKeeper服务器。8核64位jdk1.6;log和snapshot放在不同磁盘;

    • 场景一: pub创建NODE,随后删除

      • 操作: 同一个目录下,先create EPHEMERAL node,再delete;create和delete各计一次更新。没有订阅。一个进程开多个连接,每个连接绑定一个线程,在多个path下做上述操作;不同的连接操作的path不同
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-14723-82, 1024-7677-280, 4096-2037-1585;
    • 场景二: pub创建NODE, sub订阅并获取数据

      • 操作: 一个进程开多个连接,每连接一个线程,每个连接在多个path下做下述操作;不同的连接操作的path不同。每个path有3个订阅者连接,一个修改者连接。先全部订阅好。然后每个修改者在自己的每个path下创建一个EPHEMERAL node,不删除;创建前记录时间,订阅者收到event后记录时间(eventStat);重新get到数据后再记录时间(dataStat)。共1000个pub连接,3000个sub连接,20W条数据。收到通知后再去读取数据,五台4核client机器。
      • 结果汇总: getAfterNotify=false(只收事件,受到通知后不去读取数据);五台4核client机器
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-1W+-256ms, 1024-1W+-256, 2048-1W+-270, 4096-8000+-520;
    • 场景三: pub创建NODE,随后设置数据

      • 一个进程开多个连接,每连接一个线程,每个连接在多个path下做下述操作;不同的连接操作的path不同。每个path有一个修改者连接,没有订阅者。每个修改者在自己的每个path下设置数据。
      • 结果汇总: getAfterNotify=false(只收事件,受到通知后不去读取数据);五台4核client机器
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-14723-82, 1024-7677-280, 4096-2037-1585 ;

    总结: 由于一致性协议带来的额外网络交互,消息开销,以及本地log的IO开销,再加上ZK本身每1000条批量处理1次的优化策略,写入的平均响应时间总会在50-60ms之上。但是整体的TPS还是可观的。单个写入数据的体积越大,响应时间越长,TPS越低,这也是普遍规律了。压测过程中log文件对磁盘的消耗很大。实际运行中应该使用自动脚本定时删除历史log和snapshot文件。

    3.4 "配置管理中心" 设计

    "配置管理中心" 是 "配置中心" 的上层封装, 提供Web界面供用户对配置信息进行配置查询、配置新增、配置更新和配置删除等操作;

    3.5 "客户端" 设计

    输入图片说明

    API方式加载配置: 客户端主要分为三层:

    • ZK-Client : 第一层为ZK远程客户端的封装, 当业务方项目初始化某一个用到的配置项时, 将会触发ZK-Client对该配置对应节点的Watch, 因此当该节点变动时将会监听到ZK的类似NodeDataChanged的广播, 可以实时获取最新配置信息;
    • Ehcache : 第二层为客户端本地缓存, 可以大大提高系统的并发能力, 当配置初始化或者接受到ZK-Client的配置变更时, 将会把配置信息缓存只Encache中, 业务中针对配置的查询都是读缓存方式实现, 降低对ZK集群的压力;
    • Client-API : 第三层为暴露给业务方使用API, 简单易用, 一行代码获取配置信息, 同时可保证API获取到的配置信息是实时最新的配置信息;

    (API方式加载配置, 因为底层做了配置本地缓存, 因此可以放心应用在业务代码中, 不必担心并发压力。完整的支持配置实时推送更新)

    输入图片说明

    Bean方式加载配置:

    系统会在Spring容器中追加一个"PropertyPlaceholderConfigurer"属性解析器, 内部通过自定义的"StringValueResolver"解析器解析配置占位符 "${...}", 匹配到的配置信息将调用"XXL-CFONF"的API客户端加载最新配置信息进行Bean对象的属性赋值,最终完成实例化过程。

    (Bean方式加载配置,仅仅在实例化时加载一次; 考虑都实例化后的对象通常为持久化对象, 如数据库连接池对象, 不建议配置的太灵活, 因此Bean类型配置更新需要重启机器)

    四、历史版本

    4.1 版本1.1.0新特性

    • 1、简单易用: 上手非常简单, 只需要引入maven依赖和一行配置即可;
    • 2、在线管理: 提供配置管理中心, 支持在线管理配置信息;
    • 3、实时推送: 配置信息更新后, Zookeeper实时推送配置信息, 项目中配置数据会实时更新并生效, 不需要重启线上机器;
    • 4、高性能: 系统会对Zookeeper推送的配置信息, 在Encache中做本地缓存, 在接受推送更新或者缓存失效时会及时更新缓存数据, 因此业务中对配置数据的查询并不存在性能问题;
    • 5、配置备份: 配置数据首先会保存在Zookeeper中, 同时, 在MySQL中会对配置信息做备份, 保证配置数据的安全性;
    • 6、HA: 配置中心基于Zookeeper集群, 只要集群节点保证存活数量大于N/2+1, 就可保证服务稳定, 避免单点风险;
    • 7、分布式: 可方便的接入线上分布式部署的各个业务线, 统一管理配置信息;
    • 8、配置共享: 平台中的配置信息针对各个业务线是平等的, 各个业务线可以共享配置中心的配置信息, 当然也可以配置业务内专属配置信息;

    4.2 版本1.2.0新特性

    • 1、配置分组: 支持对配置进行分组管理, 每条配置将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    4.3 版本1.3.0新特性

    • 1、支持在线维护配置分组;
    • 2、项目groupId从com.xxl迁移至com.xuxueli,为推送maven中央仓库做准备;
    • 3、v1.3.0版本开始,推送公共依赖至中央仓库;

    4.4 版本1.3.1新特性(Coding)

    • zookeeper地址方式从磁盘迁移至项目内;

    TODO LIST

    • 1、权限管理:以分组为权限最小单元,只有分组的成员用户才有权限进行对应的配置操作;
    • 2、zookeeper客户端优化, 或将改用zkclient或者curator;
    • 3、local cache 备份到磁盘;zk异常且local properties未配置时,从磁盘上读取配置;

    五、其他

    5.1 报告问题

    XXL-CONF托管在Github上,如有问题可在 ISSUES 上提问,也可以加入上文技术交流群;

    5.2 接入登记

    更多接入公司,欢迎在github 登记


    案例四、

    Ø  超级管理员角色不展示;

    Ø  超级管理员可以看到所有非超级管理员角色,非超级管理员只可以看到当前角色用户创建的角色;

    Ø  可以新增角色,也可以对角色进行编辑,只有在创建用户时勾选是否为系统管理员才可以进行角色管理。

    【新建角色】:

    Ø  新建角色输入角色名称,可以勾选的权限为当前用户所拥有的权限;

    Ø  新建的角色作为该用户的下属角色,可分配给当前用户新建的用户;

    Ø  父级权限为新建应用所增加的权限,以后每增加一个环境,就相应的增加该应用下的该环境权限,除超级管理员外的角色需对应勾选该权限才能看到该应用或者该权限,保存角色即可。

    【编辑角色】:操作同新建角色,可以对该角色进行名称修改,权限修改。

    3.6用户

    管理用户首页,显示所有用户,可进行新建,编辑用户等操作。

     

    【新建用户】:填写姓名,用户名,密码,选择角色(拥有对应角色权限、且可以选择的角色为当前登陆用户新建的角色),选择是否为系统管理员(系统管理员拥有新建用户、新建角色权限),保存即可。

    【编辑用户】:操作同新建用户,保存即可修改。


    案例三、

    《分布式配置管理平台XXL-CONF》

    一、简介

    1.1 概述

    XXL-CONF 是一个分布式配置管理平台,其核心设计目标是“为分布式业务提供统一的配置管理服务”。现已开放源代码,开箱即用。

    1.2 特性

    • 1、简单易用: 上手非常简单, 只需要引入maven依赖和一行配置即可;
    • 2、在线管理: 提供配置管理中心, 支持在线管理配置信息;
    • 3、实时推送: 配置信息更新后, Zookeeper实时推送配置信息, 项目中配置数据会实时更新并生效, 不需要重启线上机器;
    • 4、高性能: 系统会对Zookeeper推送的配置信息, 在Encache中做本地缓存, 在接受推送更新或者缓存失效时会及时更新缓存数据, 因此业务中对配置数据的查询并不存在性能问题;
    • 5、配置备份: 配置数据首先会保存在Zookeeper中, 同时, 在MySQL中会对配置信息做备份, 保证配置数据的安全性;
    • 6、HA: 配置中心基于Zookeeper集群, 只要集群节点保证存活数量大于N/2+1, 就可保证服务稳定, 避免单点风险;
    • 7、分布式: 可方便的接入线上分布式部署的各个业务线, 统一管理配置信息;
    • 8、配置共享: 平台中的配置信息针对各个业务线是平等的, 各个业务线可以共享配置中心的配置信息, 当然也可以配置业务内专属配置信息;
    • 9、配置分组: 支持对配置进行分组管理, 每条配置将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    1.3 背景

    why not properties

    常规项目开发过程中, 通常会将配置信息位于在项目resource目录下的properties文件文件中, 配置信息通常包括有: jdbc地址配置、redis地址配置、活动开关、阈值配置、黑白名单……等等。使用properties维护配置信息将会导致以下几个问题:

    • 1、需要手动修改properties文件;
    • 2、需要重新编译打包;
    • 3、需要重启线上服务器 (项目集群时,更加令人崩溃) ;
    • 4、配置生效不及时: 因为流程复杂, 新的配置生效需要经历比较长的时间才可以生效;
    • 5、不同环境上线包不一致: 例如JDBC连接, 不同环境需要差异化配置;

    why XXL-CONF

    • 1、不需要 (手动修改properties文件) : 在配置管理中心提供的Web界面中, 定位到指定配置项, 输入新的配置的值, 点击更新按钮即可;
    • 2、不需要 (重新编译打包) : 配置更新后, 实时推送新配置信息至项目中, 不需要编译打包;
    • 3、不需要 (重启线上服务器) : 配置更新后, 实时推送新配置信息至项目中, 实时生效, 不需要重启线上机器; (在项目集群部署时, 将会节省大量的时间, 避免了集群机器一个一个的重启, 费时费力)
    • 4、配置生效 "非常及时" : 点击更新按钮, 新的配置信息将会即可推送到项目中, 瞬间生效, 非常及时。比如一些开关类型的配置, 配置变更后, 将会立刻推送至项目中并生效, 相对常规配置修改繁琐的流程, 及时性可谓天壤之别;
    • 5、不同环境 "同一个上线包" : 因为差异化的配置托管在配置中心, 因此一个上线包可以复用在生产、测试等各个运行环境, 提供能效;

    1.4 下载

    源码地址 (将会在两个git仓库同步发布最新代码)
    中央仓库地址 (最新Release版本)
    <dependency>
      <groupId>com.xuxueli</groupId>
      <artifactId>xxl-conf-core</artifactId>
      <version>1.3.0</version>
    </dependency>
    
    博客地址 (将会在两个博客同步更新文档)
    技术交流群 (仅作技术交流)
    • 群4:464762661 image
    • 群3:242151780 (群即将满,请加群4)
    • 群2:438249535 (群即将满,请加群4)
    • 群1:367260654 (群即将满,请加群4)

    1.5 环境

    • Maven3+
    • Jdk1.7+
    • Tomcat7+
    • Zookeeper3.4+
    • Mysql5.5+

    二、快速入门

    2.1 初始化“数据库”

    请下载项目源码并解压,获取 "调度数据库初始化SQL脚本" 并执行即可。脚本位置如下:

    xxl-conf/db/xxl-conf.sql
    

    2.2 编译源码

    解压源码,按照maven格式将源码导入IDE, 使用maven进行编译即可,源码结构如下图所示:

    输入图片说明

    • xxl-conf-admin:配置管理中心
    • xxl-conf-core:公共依赖
    • xxl-conf-example: 接入XXl-CONF的Demo项目

    2.3 “配置管理中心” 项目配置

    项目:xxl-conf-admin
    作用:管理线上配置信息
    

    配置文件位置:

    xxl-conf/xxl-conf-admin/src/main/resources/xxl-config-admin.properties
    

    配置项目说明:

    # xxl-conf, zk address  (配置中心zookeeper集群地址,如有多个地址用逗号分隔)
    xxl.conf.zkserver=127.0.0.1:2181
    
    # xxl-conf, jdbc    (配置中心mysql地址)
    xxl.conf.jdbc.driverClass=com.mysql.jdbc.Driver
    xxl.conf.jdbc.url=jdbc:mysql://localhost:3306/xxl-conf?Unicode=true&amp;characterEncoding=UTF-8
    xxl.conf.jdbc.username=root
    xxl.conf.jdbc.password=root_pwd
    
    # xxl-conf, admin login (管理中心登录账号密码)
    xxl.conf.login.username=admin
    xxl.conf.login.password=123456
    

    2.4 “接入XXL-CONF的Demo项目” 项目配置

    项目:xxl-conf-example
    作用:供用户参考学习如何接入XXL-CONF
    
    A、引入maven依赖
    <!-- xxl-conf-client -->
    <dependency>
        <groupId>com.xuxueli</groupId>
        <artifactId>xxl-conf-core</artifactId>
        <version>${xxl.conf.version}</version>
    </dependency>
    
    B、配置 “XXL-CONF配置解析器”

    可参考配置文件:

    /xxl-conf/xxl-conf-example/src/main/resources/spring/applicationcontext-xxl-conf.xml
    

    配置项说明

    <!-- XXL-CONF配置解析器 -->
    <bean id="xxlConfPropertyPlaceholderConfigurer" class="com.xxl.conf.core.spring.XxlConfPropertyPlaceholderConfigurer" />
    
    C、设置 "xxl-conf.properties"

    可参考配置文件:

    /xxl-conf/xxl-conf-example/src/main/resources/xxl-conf.properties
    

    配置项说明

    # xxl-conf, zk address  (配置中心zookeeper集群地址,如有多个地址用逗号分隔)
    xxl.conf.zkserver=127.0.0.1:2181
    

    该配置文件,除了支持配置ZK地址,还可以配置一些本地配置。 XXL-CONF 加载配置时会优先加载 "xxl-conf.properties" 中的配置, 然后才会加载ZK中的配置。可以将一些希望存放本地的配置存放在该文件。

    2.5 新增配置分组

    输入图片说明

    每个配置分组对应一个唯一的GroupName,作为该分组下配置的统一前缀。在“分组管理”栏目可以创建并管理配置分组信息,系统已经提供一个默认分组.

    2.6 新增配置信息

    登录"配置管理中心"

    输入图片说明

    进入"配置管理界面",点击"新增配置"按钮

    输入图片说明

    在弹出界面,填写配置信息

    输入图片说明

    至此, 一条配置信息已经添加完成.

    通过client端,可以实时获取配置信息, 通过本地已经加载过得配置将会接受Zookeeper的更新推送, 如下如日志:

    输入图片说明

    2.7 项目中使用XXL-CONF

    项目: xxl-conf-example:   (可以参考 com.xxl.conf.example.controller.IndexController.index() )
    作用: 接入XXl-CONF的Demo项目
    
    • 方式1: XML文件中的占位符方式

      <bean id="configuration" class="com.xxl.conf.example.core.constant.Configuration">
          <property name="paramByXml" value="${default.key01}" />
      </bean>
      

      特点:

      • 上面配置说明: 在项目启动时, Configuration的paramByXml属性, 会根据配置的占位符${default.key01}, 去XXL-CONF中匹配KEY=key01的配置信息, 赋值给paramByXml;
      • 目前, 该方式配置信息, 只会在项目启动时从XXL-CONF中加载一次, 项目启动后该值不会变更。 例如配置数据连接信息, 如果XXL-CONF平台中连接地址配置改边, 需要重启后才生效;
      • 该方式, 底层本质上是通过 "方式2: API方式" 实现的。
    • 方式2: API方式

      String paramByClient = XxlConfClient.get("default.key02", null);
      

      特点:

      • 上面代码说明: 会获取XXL-CONF平台中KEY=default.key02的配置信息, 如果不存在值使用传递的默认值;
      • 因为Zookeeper会实时推送配置更新到客户端, 因此该方法放回的值可以XXL-CONF平台中的值保持实时一致;
      • XXL-CONF会对Zookeeper推送的配置信息做本地缓存, 该方法查询的是缓存的配置信息, 因此该方法并不会产生性能问题, 使用时不需要考虑性能问题;

    三、总体设计

    3.1 架构图

    输入图片说明

    3.2 "配置项" 设计

    系统配置信息以K/V的形式存在, "配置项" 属性如下:

    • 分组: "配置项" 的分组, 便于配置分组管理;
    • KEY : "配置项" 的全局唯一标识, 对应一条配置信息;
    • VALUE : "配置项" 中保存的数据信息, 仅仅支持String字符串格式;
    • 描述 : 配置项的描述信息;

    每条配置,将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    3.3 "配置中心" 设计

    输入图片说明

    • 1、ZK设计: 系统在ZK集群中占用一个根目录 "/xxl-conf", 每新增一条配置项, 将会在该目录下新增一个子节点。结构如下图, 当配置变更时将会触发ZK节点的变更, 将会触发对应类型的ZK广播。
    • 2、数据库备份配置信息: 配置信息在ZK中的新增、变更等操作, 将会同步备份到Mysql中, 进一步保证数据的安全性;
    • 3、配置推送: 配置推送功能在ZK的Watch机制实现。Client在加载一条配置信息时将会Watch该配置对应的ZK节点, 因此, 当对该配置项进行配置更新等操作时, 将会触发ZK的NodeDataChanged广播, Client竟会立刻得到通知并刷新本地缓存中的配置信息;

    ZK之watcher普及(来源官方文档,以及网络博客)

    1、可以注册watcher的方法:getData、exists、getChildren。
    2、可以触发watcher的方法:create、delete、setData。连接断开的情况下触发的watcher会丢失。
    3、一个Watcher实例是一个回调函数,被回调一次后就被移除了。如果还需要关注数据的变化,需要再次注册watcher。
    4、New ZooKeeper时注册的watcher叫default watcher,它不是一次性的,只对client的连接状态变化作出反应。(推荐ZK初始化时, 主动Watcher如exists)
    5、实现永久监听: 由于zookeeper是一次性监听,所以我们必须在wather的process方法里面再设置监听。
    6、getChildren("/path")监视/path的子节点,如果(/path)自己删了,也会触发NodeDeleted事件。
    
    《操作--事件》 event For “/path” event For “/path/child”
    create(“/path”) EventType.NodeCreated
    delete(“/path”) EventType.NodeDeleted
    setData(“/path”) EventType.NodeDataChanged
    create(“/path/child”) EventType.NodeChildrenChanged(getChild) EventType.NodeCreated
    delete(“/path/child”) EventType.NodeChildrenChanged(getChild) EventType.NodeDeleted
    setData(“/path/child”) EventType.NodeDataChanged

    《事件--Watch方式》 | Default Watcher | exists(“/path”) | getData(“/path”) | getChildren(“/path”) --- | --- | --- | --- EventType.None | 触发 | 触发 | 触发 | 触发 EventType.NodeCreated | | 触发 | 触发 |
    EventType.NodeDeleted | | 触发 | 触发 | EventType.NodeDataChanged | | 触发 | 触发 | EventType.NodeChildrenChanged | | | | 触发

    ZooKeeper的一个性能测试

    测试数据来自阿里中间件团队

    ZK集群情况: 3台ZooKeeper服务器。8核64位jdk1.6;log和snapshot放在不同磁盘;

    • 场景一: pub创建NODE,随后删除

      • 操作: 同一个目录下,先create EPHEMERAL node,再delete;create和delete各计一次更新。没有订阅。一个进程开多个连接,每个连接绑定一个线程,在多个path下做上述操作;不同的连接操作的path不同
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-14723-82, 1024-7677-280, 4096-2037-1585;
    • 场景二: pub创建NODE, sub订阅并获取数据

      • 操作: 一个进程开多个连接,每连接一个线程,每个连接在多个path下做下述操作;不同的连接操作的path不同。每个path有3个订阅者连接,一个修改者连接。先全部订阅好。然后每个修改者在自己的每个path下创建一个EPHEMERAL node,不删除;创建前记录时间,订阅者收到event后记录时间(eventStat);重新get到数据后再记录时间(dataStat)。共1000个pub连接,3000个sub连接,20W条数据。收到通知后再去读取数据,五台4核client机器。
      • 结果汇总: getAfterNotify=false(只收事件,受到通知后不去读取数据);五台4核client机器
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-1W+-256ms, 1024-1W+-256, 2048-1W+-270, 4096-8000+-520;
    • 场景三: pub创建NODE,随后设置数据

      • 一个进程开多个连接,每连接一个线程,每个连接在多个path下做下述操作;不同的连接操作的path不同。每个path有一个修改者连接,没有订阅者。每个修改者在自己的每个path下设置数据。
      • 结果汇总: getAfterNotify=false(只收事件,受到通知后不去读取数据);五台4核client机器
      • 结果数据: "dataSize(字节)-TPS-响应时间(ms)" 统计结果为: 255-14723-82, 1024-7677-280, 4096-2037-1585 ;

    总结: 由于一致性协议带来的额外网络交互,消息开销,以及本地log的IO开销,再加上ZK本身每1000条批量处理1次的优化策略,写入的平均响应时间总会在50-60ms之上。但是整体的TPS还是可观的。单个写入数据的体积越大,响应时间越长,TPS越低,这也是普遍规律了。压测过程中log文件对磁盘的消耗很大。实际运行中应该使用自动脚本定时删除历史log和snapshot文件。

    3.4 "配置管理中心" 设计

    "配置管理中心" 是 "配置中心" 的上层封装, 提供Web界面供用户对配置信息进行配置查询、配置新增、配置更新和配置删除等操作;

    3.5 "客户端" 设计

    输入图片说明

    API方式加载配置: 客户端主要分为三层:

    • ZK-Client : 第一层为ZK远程客户端的封装, 当业务方项目初始化某一个用到的配置项时, 将会触发ZK-Client对该配置对应节点的Watch, 因此当该节点变动时将会监听到ZK的类似NodeDataChanged的广播, 可以实时获取最新配置信息;
    • Ehcache : 第二层为客户端本地缓存, 可以大大提高系统的并发能力, 当配置初始化或者接受到ZK-Client的配置变更时, 将会把配置信息缓存只Encache中, 业务中针对配置的查询都是读缓存方式实现, 降低对ZK集群的压力;
    • Client-API : 第三层为暴露给业务方使用API, 简单易用, 一行代码获取配置信息, 同时可保证API获取到的配置信息是实时最新的配置信息;

    (API方式加载配置, 因为底层做了配置本地缓存, 因此可以放心应用在业务代码中, 不必担心并发压力。完整的支持配置实时推送更新)

    输入图片说明

    Bean方式加载配置:

    系统会在Spring容器中追加一个"PropertyPlaceholderConfigurer"属性解析器, 内部通过自定义的"StringValueResolver"解析器解析配置占位符 "${...}", 匹配到的配置信息将调用"XXL-CFONF"的API客户端加载最新配置信息进行Bean对象的属性赋值,最终完成实例化过程。

    (Bean方式加载配置,仅仅在实例化时加载一次; 考虑都实例化后的对象通常为持久化对象, 如数据库连接池对象, 不建议配置的太灵活, 因此Bean类型配置更新需要重启机器)

    四、历史版本

    4.1 版本1.1.0新特性

    • 1、简单易用: 上手非常简单, 只需要引入maven依赖和一行配置即可;
    • 2、在线管理: 提供配置管理中心, 支持在线管理配置信息;
    • 3、实时推送: 配置信息更新后, Zookeeper实时推送配置信息, 项目中配置数据会实时更新并生效, 不需要重启线上机器;
    • 4、高性能: 系统会对Zookeeper推送的配置信息, 在Encache中做本地缓存, 在接受推送更新或者缓存失效时会及时更新缓存数据, 因此业务中对配置数据的查询并不存在性能问题;
    • 5、配置备份: 配置数据首先会保存在Zookeeper中, 同时, 在MySQL中会对配置信息做备份, 保证配置数据的安全性;
    • 6、HA: 配置中心基于Zookeeper集群, 只要集群节点保证存活数量大于N/2+1, 就可保证服务稳定, 避免单点风险;
    • 7、分布式: 可方便的接入线上分布式部署的各个业务线, 统一管理配置信息;
    • 8、配置共享: 平台中的配置信息针对各个业务线是平等的, 各个业务线可以共享配置中心的配置信息, 当然也可以配置业务内专属配置信息;

    4.2 版本1.2.0新特性

    • 1、配置分组: 支持对配置进行分组管理, 每条配置将会生成全局唯一标示GroupKey,在client端使用时,需要通过该值匹配对应的配置信息;

    4.3 版本1.3.0新特性

    • 1、支持在线维护配置分组;
    • 2、项目groupId从com.xxl迁移至com.xuxueli,为推送maven中央仓库做准备;
    • 3、v1.3.0版本开始,推送公共依赖至中央仓库;

    4.4 版本1.3.1新特性(Coding)

    • zookeeper地址方式从磁盘迁移至项目内;

    TODO LIST

    • 1、权限管理:以分组为权限最小单元,只有分组的成员用户才有权限进行对应的配置操作;
    • 2、zookeeper客户端优化, 或将改用zkclient或者curator;
    • 3、local cache 备份到磁盘;zk异常且local properties未配置时,从磁盘上读取配置;

    五、其他

    5.1 报告问题

    XXL-CONF托管在Github上,如有问题可在 ISSUES 上提问,也可以加入上文技术交流群;

    5.2 接入登记

    更多接入公司,欢迎在github 登记


    案例五、

    分布式配置管理平台Disconf

    摘要

    为了更好的解决分布式环境下多台服务实例的配置统一管理问题,本文提出了一套完整的分布式配置管理解决方案(简称为disconf[4],下同)。首先,实现了同构系统的配置发布统一化,提供了配置服务server,该服务可以对配置进行持久化管理并对外提供restful接口,在此基础上,基于zookeeper实现对配置更改的实时推送,并且,提供了稳定有效的容灾方案,以及用户体验良好的编程模型和WEB用户管理界面。其次,实现了异构系统的配置包管理,提出基于zookeeper的全局分布式一致性锁来实现主备统一部署、系统异常时的主备自主切换。通过在百度内部以及外部等多个产品线的实践结果表明,本解决方案是有效且稳定的。

    技术背景

    在一个分布式环境中,同类型的服务往往会部署很多实例。这些实例使用了一些配置,为了更好地维护这些配置就产生了配置管理服务。通过这个服务可以轻松地管理成千上百个服务实例的配置问题。

    王阿晶提出了基于zooKeeper的配置信息存储方案的设计与实现[1], 它将所有配置存储在zookeeper上,这会导致配置的管理不那么方便,而且他们没有相关的源码实现。淘宝的diamond[2]是淘宝内部使用的一个管理持久配置的系统,它具有完整的开源源码实现,它的特点是简单、可靠、易用,淘宝内部绝大多数系统的配置都采用diamond来进行统一管理。他将所有配置文件里的配置打散化进行存储,只支持KV结构,并且配置更新的推送是非实时的。百度内部的BJF配置中心服务[3]采用了类似淘宝diamond的实现,也是配置打散化、只支持KV和非实时推送。

    同构系统是市场的主流,特别地,在业界大量使用部署虚拟化(如JPAAS系统,SAE,BAE)的情况下,同一个系统使用同一个部署包的情景会越来越多。但是,异构系统也有一定的存在意义,譬如,对于“拉模式”的多个下游实例,同一时间点只能只有一个下游实例在运行。在这种情景下,就存在多台实例机器有“主备机”模式的问题。目前国内并没有很明显的解决方案来统一解决此问题。

    功能特点与设计理念

    disconf是一套完整的基于zookeeper的分布式配置统一解决方案。

    它的功能特点是

    • 支持配置(配置项+配置文件)的分布式化管理
      • 配置发布统一化
      • 配置发布、更新统一化(云端存储、发布):配置存储在云端系统,用户统一在平台上进行发布、更新配置。
      • 配置更新自动化:用户在平台更新配置,使用该配置的系统会自动发现该情况,并应用新配置。特殊地,如果用户为此配置定义了回调函数类,则此函数类会被自动调用。
    • 配置异构系统管理
      • 异构包部署统一化:这里的异构系统是指一个系统部署多个实例时,由于配置不同,从而需要多个部署包(jar或war)的情况(下同)。使用Disconf后,异构系统的部署只需要一个部署包,不同实例的配置会自动分配。特别地,在业界大量使用部署虚拟化(如JPAAS系统,SAE,BAE)的情况下,同一个系统使用同一个部署包的情景会越来越多,Disconf可以很自然地与他天然契合。 异构主备自动切换:如果一个异构系统存在主备机,主机发生挂机时,备机可以自动获取主机配置从而变成主机。
      • 异构主备机Context共享工具:异构系统下,主备机切换时可能需要共享Context。可以使用Context共享工具来共享主备的Context。
    • 注解式编程,极简的使用方式:我们追求的是极简的、用户编程体验良好的编程方式。通过简单的标注+极简单的代码撰写,即可完成复杂的配置分布式化。
    • 需要Spring编程环境

    它的设计理念是:

    • 简单,用户体验良好:
      • 摒弃了打散化配置的管理方式[2,3],仍旧采用基于配置文件的编程方式,这和程序员以前的编程习惯(配置都是放在配置文件里)一致。特别的,为了支持较为小众的打散化配置功能,还特别支持了配置项。
      • 采用了基于XML无代码侵入编程方式:只需要几行XML配置,即可实现配置文件发布更新统一化、自动化。
      • 采用了基于注解式的弱代码侵入编程方式:通过编程规范,一个配置文件一个配置类,代码结构简单易懂。XML几乎没有任何更改,与原springXML配置一样。真正编程时,几乎感觉不到配置已经分布式化
    • 可以托管任何类型的配置文件,这与[2,3]只能支持KV结构的功能有较大的改进。
    • 配置更新实时推送
    • 提供界面良好Web管理功能,可以非常方便的查看配置被哪些实例使用了。

    详细设计

    架构设计

    disconf服务集群模式

    disconf的模块架构图

    每个模块的简单介绍如下:

    • Disconf-core
      • 分布式通知模块:支持配置更新的实时化通知
      • 路径管理模块:统一管理内部配置路径URL
    • Disconf-client
      • 配置仓库容器模块:统一管理用户实例中本地配置文件和配置项的内存数据存储
      • 配置reload模块:监控本地配置文件的变动,并自动reload到指定bean
      • 扫描模块:支持扫描所有disconf注解的类和域
      • 下载模块:restful风格的下载配置文件和配置项
      • watch模块:监控远程配置文件和配置项的变化
      • 主备分配模块:主备竞争结束后,统一管理主备分配与主备监控控制
      • 主备竞争模块:支持分布式环境下的主备竞争
    • Disconf-web
      • 配置存储模块:管理所有配置的存储和读取
      • 配置管理模块:支持配置的上传、下载、更新
      • 通知模块:当配置更新后,实时通知使用这些配置的所有实例
      • 配置自检监控模块:自动定时校验实例本地配置与中心配置是否一致
      • 权限控制:web的简单权限控制
    • Disconf-tools
      • context共享模块:提供多实例间context的共享。

    流程设计

    运行流程详细介绍:

    与2.0版本的主要区别是支持了:主备分配功能/主备切换事件。

    • 启动事件A:以下按顺序发生。
      • A3:扫描静态注解类数据,并注入到配置仓库里。
      • A4+A2:根据仓库里的配置文件、配置项,去 disconf-web 平台里下载配置数据。这里会有主备竞争
      • A5:将下载得到的配置数据值注入到仓库里。
      • A6:根据仓库里的配置文件、配置项,去ZK上监控结点。
      • A7+A2:根据XML配置定义,到 disconf-web 平台里下载配置文件,放在仓库里,并监控ZK结点。这里会有主备竞争。
      • A8:A1-A6均是处理静态类数据。A7是处理动态类数据,包括:实例化配置的回调函数类;将配置的值注入到配置实体里。
    • 更新配置事件B:以下按顺序发生。
      • B1:管理员在 Disconf-web 平台上更新配置。
      • B2:Disconf-web 平台发送配置更新消息给ZK指定的结点。
      • B3:ZK通知 Disconf-cient 模块。
      • B4:与A4一样。
      • B5:与A5一样。
      • B6:基本与A4一样,唯一的区别是,这里还会将配置的新值注入到配置实体里。
    • 主备机切换事件C:以下按顺序发生。
      • C1:发生主机挂机事件。
      • C2:ZK通知所有被影响到的备机。
      • C4:与A2一样。
      • C5:与A4一样。
      • C6:与A5一样。
      • C7:与A6一样。

    模块实现

    disconf-web提供了前后端分离的web架构,具体可见:https://github.com/knightliao/disconf/tree/master/disconf-web

    本部分会重点介绍disconf-client的实现方式。

    注解式disconf实现

    本实现会涉及到 配置仓库容器模块、扫描模块、下载模块、watch模块,

    http://ww1.sinaimg.cn/bmiddle/60c9620fjw1eqj9zzgc7yj20b20pn41v.jpg

    使用AOP拦截的一个好处是可以比较轻松的实现配置控制,比如并发环境下的配置统一生效。关于这方面的讨论可以见这里

    特别地,本方式提供的编程模式非常简单,例如使用以下配置类的程序在使用它时,可以直接@Autowired进来进行调用,使用它时就和平常使用普通的JavaBean一样,但其实它已经分布式化了。配置更新时,配置类亦会自动更新。

    @Service
    @DisconfFile(filename = "redis.properties")
    public class JedisConfig {
    
        // 代表连接地址
        private String host;
    
        // 代表连接port
        private int port;
    
        /**
         * 地址, 分布式文件配置
         * 
         * @return
         */
        @DisconfFileItem(name = "redis.host", associateField = "host")
        public String getHost() {
            return host;
        }
    
        public void setHost(String host) {
            this.host = host;
        }
    
        /**
         * 端口, 分布式文件配置
         * 
         * @return
         */
        @DisconfFileItem(name = "redis.port", associateField = "port")
        public int getPort() {
            return port;
        }
    
        public void setPort(int port) {
            this.port = port;
        }
    }
    

    基于XML配置disconf实现

    本实现提供了无任何代码侵入方式的分布式配置。

    ReloadablePropertiesFactoryBean继承了Spring Properties文件的PropertiesFactoryBean类,管理所有当配置更新时要进行reload的配置文件。对于被管理的每一个配置文件,都会通过 配置仓库容器模块、扫描模块、下载模块、watch模块 进行配置获取至配置仓库里。

    ReloadingPropertyPlaceholderConfigurer继承了Spring Bean配置值控制类PropertyPlaceholderConfigurer。在第一次扫描spring bean里,disconf会记录配置文件的配置与哪些bean有关联。

    ReloadConfigurationMonitor是一个定时任务,定时check本地配置文件是否有更新。

    当配置中心的配置被更新时,配置文件会被下载至实例本地,ReloadConfigurationMonitor即会监控到此行为,并且通知 ReloadingPropertyPlaceholderConfigurer 对相关的bean类进行值更新。

    特别的,此种方式无法解决并发情况下配置统一生效的问题。

    主备分配实现

    在实现中,为每个配置提供主备选择的概念。用户实例在获取配置前需要先进行全局唯一性竞争才能得到配置值。在这里,我们采用基于zookeeper的全局唯一性锁来实现。

    Comparisons

      淘宝Diamond[2] Disconf 比较
    数据持久性 存储在mysql上 存储在mysql上 都持久化到数据库里,都易于管理
    推拉模型 拉模型,每隔15s拉一次全量数据 基于Zookeeper的推模型,实时推送 disconf基于分布式的Zookeeper来实时推送,在稳定性、实效性、易用性上均优于diamond
    配置读写 支持实例对配置读写。支持某台实例写配置数据,并广播到其它实例上 只支持实例对配置读。通过在disconf-web上更新配置到达到广播写到所有应用实例 从目前的应用场景来看,实例对配置的写需求不是那么明显。disconf支持的中心化广播方案可能会与人性思考更加相似。
    容灾 多级容灾模式,配置数据会dump在本地,避免中心服务挂机时无法使用 多级容灾模式,优先读取本地配置文件。 双方均支持在中心服务挂机时配置实例仍然可以使用
    配置数据模型 只支持KV结构的数据,非配置文件模式 支持传统的配置文件模式(配置文件),亦支持KV结构数据(配置项) 使用配置文件的编程方式可能与程序员的编程习惯更为相似,更易于接受和使用。
    编程模型 需要将配置文件拆成多个配置项,没有明显的编程模型 在使用配置文件的基础上,提供了注解式和基于XML的两种编程模型
    并发性 多条配置要同时生效时,无法解决并发同时生效的问题




    展开全文
  • 什么叫分散控制系统?它有什么特点?集散控制系统是以微处理器为基础,采用控制功能分散、显示操作集中、兼顾分而自治...其主要特征是它的集中管理和分散控制。目前DCS在电力、冶金、石化等各行各业都获得了极其广泛...

    什么叫分散控制系统?它有什么特点?

    集散控制系统是以微处理器为基础,采用控制功能分散、显示操作集中、兼顾分而自治和综合协调的设计原则的新一代仪表控制系统。集散控制系统简称DCS,也可直译为“分散控制系统”或“分布式计算机控制系统”。

    它采用控制分散、操作和管理集中的基本设计思想,采用多层分级、合作自治的结构形式。其主要特征是它的集中管理和分散控制。目前DCS在电力、冶金、石化等各行各业都获得了极其广泛的应用。

    DCS通常采用分级递阶结构,每一级由若干子系统组成,每一个子系统实现若干特定的有限目标,形成金字塔结构。

    可靠性是DCS发展的生命,要保证DCS的高可靠性主要有三种措施:一是广泛应用高可靠性的硬件设备和生产工艺;二是广泛采用冗余技术;三是在软件设计上广泛实现系统的容错技术、故障自诊断和自动处理技术等。当今大多数集散控制系统的MTBF可达几万甚至几十万小时。

    a139d3ab58b89238517e43e369fde680.png

    分散控制系统又称总体分散型控制系统,它是以微处理机为核心的分散型直接控制装置。它的控制功能分散(以微处理机为中心构成子系统),管理集中(用计算机管理)。它与集中控制系统比较有以下特点:

    1、可靠性高(即危险分散)。以微处理机为核心的微型机比中小型计算机的可靠性高,即使一部分系统故障也不会影响全局,当管理计算机故障时,各子系统仍能进行独立的控制。

    2、系统结构合理(即结构分散)。系统的输入、输出数据预先通过子系统处理或选择,数据传输量减小,减轻了微型机的负荷,提高了控制速度。

    3、由于信息量减小,使编程简单,修改、变动都很方便。

    4、由于控制功能分散,子系统可靠性提高,对管理计算机的要求可以降低,对微型机的要求也可以降低。

    展开全文
  • ERP与集中管理

    千次阅读 2001-07-30 14:43:00
    ERP是在西方产生发展起来的,它是与市场经济紧密联系在一起的,是市场竞争的产物。...信息技术高速发展,Internet化解了时空的界限,导致全球化竞争无法回避,集中管理模式将成为未来集团企业的新型管理模式。
  • 极致物业管理软件的系统特点

    千次阅读 2010-07-20 10:55:00
    一、 成熟的基于三级组织的集中管理模式 极致物业管理系统打破了传统的部门独立地域分散的限制,通过互联网连接将总公司、区域公司、管理处连接到一起,所有数据集中储存在一个数据库中,能够实时...
  • 数据管理是指对数据进行分类、组织、编码、存储、检索维护,它是数据处理的中心问题。而数据的处理是指对各种数据进行收集、存储、加工传播的一系列活动的总和。     在应用需求的推动下,在计算机硬件、...
  • 利用服务器虚拟化技术对学校的服务器资源进行集中管理,可提高服务器管理效率,节省资源,同时降低成本。中央财经大学网络部负责人乔晓宇表示,这也是我们利用新技术来提升IT系统管控水平的初步尝试。今后我们还计划...
  • 分散控制系统是由过程控制级过程监控级组成的,以通讯网络为纽带的多级计算机系统,具有控制分散集中操作、管理分级、配置灵活以及组态方便等优点。详细介绍了新一代开放式国产TD6000分散控制系统的构成、特点和...
  • 大数据应用管理模式及内容

    千次阅读 2019-01-31 23:36:30
    通过调研,数据应用管理可总结为分散管理型、职能复用型、集中管理型三种模式,数据应用管理模式中重点关注组织管理、需求管理、建设管理、成果管理四大领域。 (1) 管理模式 分散管理型:各部门分散开展数据应用...
  • 新一代调度集中系统New Generation CTC (FZK-CTC),是在铁路跨越式发展的新形势下,在计算机技术、通信技术、信号技术高度发达以及DMIS系统成功实施的基础上, 提出来的一种新型的行车指挥信号控制设备,同时也将带来...
  • 网络管理和SNMP协议

    千次阅读 2004-09-20 14:33:00
    不仅如此,网络的复杂性使得被管理的对象在系统中不是集中的,而是分散的。分布式的管理必然要求网络管理员在网络的协议层次结构上对系统管理做出重新的认识,即从物理层、链路层、网络层、传输层应用层的角度重新...
  • 第三章城市智慧交通管理和服务平台系统方案设计 3.1系统构成 按照信息获取的方式、传递及使用情况,可以把城市智慧交通管理和服务综合信息服务平台系统划分为4 个层次: 基础层、功能层、共享信息层服务层。在...
  • 精确是指一致性,重复度量值集中并有一点分散。正确是指正确性度量值非常接近真实值。精确度量不需要正确。非常正确的度量不需要精确。 项目成本管理包括三个管理过程: 1、质量计划编制:确定适合于项目的质量...
  • 性格特质自我管理

    千次阅读 2014-12-16 09:40:05
    1,管理需具备的性格特质 欣赏他人:以一种不以自我为中心的合作的方式他人相处,能平静客观地接受不同的人,放下自己的性格、喜好,去欣赏不同类型的人。不是通过个人友谊或者熟悉程度,而是通过某个人的性格...
  • PMP项目管理13个计划

    千次阅读 2019-06-14 09:57:50
    1、变更管理计划 所属过程:制定项目管理计划 ...含义:定义配置项,定义需要正式变更控制的内容,并为这些配置项内容规定变更控制过程,用来明确如何开展配置管理。 内容: 如何管理配置。 配置管...
  • 操作系统的分页分段式管理

    千次阅读 2019-03-30 15:27:54
    计算存储的层次结构: 当前技术没有能够提供这样的存储器,因此大部分的计算机都有一个存储器层次结构,即少量的非常快速... 内存管理主要包括虚地址、地址变换、内存分配回收、内存扩充、内存共享保护等功能。...
  • 随着社会信息化的发展,社会上很多事务的管理也跟着相应发生了根本的变化,项目申报管理也跟着发生了变化,以前的管理是一种各地信息分散然后再集中到中央,信息的传送途径是通过简单人工传送,这样使办事效率低。...
  • ·电子政务概念:指政府机构在其管理和服务职能中运用现代化信息技术,实现政府组织结构工作流程的重组优化,超越时间。空间部门分割的制约,建成一个精简、高效、廉洁、公平的政府运作模式。 ·电子政务...
  • [管理]管理向左 ERP向右?

    千次阅读 2010-07-16 07:56:00
    管理向左 ERP向右? 问题提出  从“管理混乱的全部暴露”来说,王晖也确实稍嫌冤枉,“现代化”仓库问题仅仅是冰山一角,笔者也相信鑫华峰机械ERP系统上线遭遇的也不仅仅是仓库问题,而是一系列的连锁问题!究其...
  • MyEclipes+JSP+tomcat+MySQL实现JavaEE平台项目管理系统

    千次阅读 多人点赞 2021-01-25 18:22:54
    导读:随着社会信息化的发展,很多的社会管理问题也一并出现了根本性变化,项目公司的报表及文件管理也发生了变化,以前的管理是一个分布式的信息,然后围绕中心由通过简单的来传输信息,这使得办事效率非常低下,...
  • Linux内存管理是一个很负责的系统,也是linux的精髓之一,网络上讲解这方面的文档也很多,我把这段时间学习内存管理方面的知识记录在这里,涉及的代码太多,也没有太多仔细的去看代码,深入解算法,这篇文章就当做...
  • 谈项目管理和软件测试过程

    万次阅读 2005-01-06 14:20:00
    以华友公司研发部的组织结构为例,测试部门属于研发部副总裁直接管理,见如下结构图公司研发部的组织结构图对于从事软件研发的组织来说,工作类型至少包括项目管理、产品设计、编码、测试、质量保证软件配置管理,...
  • 当今社会经济发展面临着日趋严重的资源约束更加迫切的绿色环保要求,我国各类园区更是首当其冲,面临经济增长的艰巨任务资源环境保护的巨大压力。传统园区建设者通常只提供水、电、气、交通、建筑等“硬件”基础...
  • 固定资产管理是企业管理中的一个重要组成部分,固定资产具有价值高,使用周期长、使用地点分散管理难度大等特点。许多企业在固定资产管理过程中也许都遇到过以下所列的问题: 资产折旧数据不准确 ----不能准确...
  • Laxcus是Laxcus大数据实验室全体系自主设计研发的多用户多集群大数据管理系统,支持一到百万台级节点,提供零至EB量级数据存储、计算能力,集运行、开发、部署、维护为一体的平台。现在已经在多地部署投入运营。逐...
  • 内存管理主要包括内存分配回收、地址变换、内存扩充、内存共享保护等功能。 下面主要介绍连续分配存储管理、覆盖与交换技术以及页式与段式存储管理等基本概念原理。 1.连续分配存储管理方式 连续...
  • 俗称二八定律,又名80/20定律、帕累托法则(定律)也叫巴莱特定律、最省力的法则、不平衡原则等,被广泛应用于社会学及企业管理学等。 是19世纪末20世纪初意大利经济学家巴莱多发现的。他认为,在任何一组东西中,...
  • 利用编写的LabVIEW程序对设备进行状态监测,对设备旋转部件进行故障树诊断,以及对重要数据进行MySQL数据库管理,实现分散设备的集中监测、故障诊断数据管理,满足煤矿设备巡检监测与故障诊断实际要求。
  • 操作系统内存管理(思维导图详解)

    万次阅读 多人点赞 2010-07-05 11:26:00
    在介绍内存管理的细节前,先要了解一下分层存储器体系: 大部分的计算机都有一个存储器层次结构,即少量的非常快速、昂贵、易变的高速缓存(cache);若干兆字节的中等速度、中等价格、易变的主存储器(RAM);...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,454
精华内容 13,781
关键字:

集中管理和分散管理的特点