微信公众号:内核小王子 关注可了解更多关于数据库,JVM内核相关的知识; 若是你有任何疑问也能够加我pigpdong[^1]java
平常开发中咱们的应用中通常都会有数据库相关的配置,redis相关的配置,log4j相关的配置 等经常使用配置,这些咱们称为静态配置,在应用启动的时候就须要加载,修改配置须要重启应用,这类配置通常是针对相关资源的访问地址和访问权限,还有一类配置和业务密切相关,应用在运行过程当中须要监听这些配置的变化以方便修改运行模式或者响应对应的策略,例如并发控制数,业务开关等,能够用来作服务降级和限流,例如在数据库新老表作迁移的时候,咱们能够用来配置进行动态切换模式:同步双写读老表,同步双写读新表,写新表读新表。若是这些配置不能进行集中式管理,那么当咱们的服务部署有成千上万的实例后,即便借助ansible这些运维工具,那么修改配置也将是一件超级麻烦并且极容易出错的事情,在作发布的时候也不在敏捷。node
因此,微服务架构下,咱们须要一个集中式的配置管理系统,那么这个系统须要提供哪些功能才能解决上面的问题呢nginx
1.权限控制,固然不能全部的人均可以修改配置,若是可以继承公司的SSO或者LDAP固然更好redis
2.审计日志,全部的修改须要记录操做日志,方便后续出现异议可以找到对应的操做人,也能够提供审批流程spring
3.环境管理,开发,测试,生成环境下的配置确定要作隔离,相同group内的配置可能大多相同,例如同一个IDC机房的应用也能够有namespace作区分数据库
4.配置回滚,当发现配置错误,或者在该配置下程序发生异常能够当即回滚到以前的版本,这须要该系统可以有版本管理的功能api
5.灰度发布,有时候咱们新上线一个功能,想先经过少部分流量测试下,这个时候咱们能够随机只修改部分应用的配置,当测试正常后在推送到全部的应用缓存
6.高可用,配置中心须要高可用,因此最好能支持集群部署,同时配置中心系统挂了以后最好能不影响应用,应用可以继续使用本地缓存的配置安全
7.配置中心,应该可以在配置发生变动后实时通知到应用,应用端多是一个监听器,配置也可能就是一个普通bean里面的属性,须要自动监听到变化并进行调整微信
目前已经开源的集中式配置管理中间件里面有携程的apollo和百度的disconf,已经阿里的diamond和spring cloud生态下地config系统,下面咱们主要分析下disconf和apollo的实现
disconf提供一个客户端程序集成在应用程序内方便应用去远程获取配置,并监听配置的变化,服务端提供配置的新增和修改,并给客户端提供获取配置的api
其中客户端有如下几个模块
scan模块
扫描全部的disconf注解,注解有两种,一张是标示这个bean是一个配置能够和具体的配置文件作管理,bean里面的属性就是配置文件里面的key-value,当服务端配置修改后,这个bean会自动经过反射调用对应属性的set方法,将这个bean里面属性的value值变动为最新的配置的值,另外一个注解是标示这是一个配置监听器,当配置变动后,会调用监听器里的方法,当有业务须要关联到配置变化进行改变策略的时候能够加上这种注解
store模块
将从远程服务端拉取到的配置文件存储到本地,store模块有一个后台线程会按期扫描存储在本地的配置文件是否有变化,若是有变化就会通知scan模块扫描到得javabean和对应的监听器
fetch模块
当watch模块监控到节点变化后,经过http调用远程restful接口,获取最新配置,而后调用store模块存储
watch模块
监控zookeeper上node的变更,当有变化后会会调用fetch模块获取配置,服务端在作配置修改的时候会将ZOOKEEPER里面相关的临时节点删除,而后全部watch该node的应用都会收到通知,全部须要监听配置变化的应用都须要和zookeeper维护一个长链接
disconf的高可用保证:server端只是提供了配置的管理以及提供接口供客户端经过http获取, 因此server端是无状态的
相比于disconf长期没有维护,并且只提供了较为简单的分组管理功能,apollo社区目前比较活跃,并且功能更为完善,不只仅提供了权限审计等安全措施,还提供了灰度发布,版本回滚等,在高可用方面将服务拆分了3个独立的模块,每一个模块均可以独立集群化部署,也不用依赖zookeeper,并且有不少大公司作背书。不过disconf部署简单,而apollo就复杂的多
和应用端集成, 监听配置变化,获取最新配置
提供获取配置的接口供客户端使用以及当有新配置更新时会通知客户端,客户端能够以必定周期定时从ConfigService获取最新配置,configservice和客户端维护一个长链接,当有配置更新的时候,会经过长链接通知客户端去取最新配置
提供配置管理的接口供portal管理页面使用,例如配置的修改和发布 AdminService和ConfigService共用一个数据库,adminService每次发布配置的时候都会往releasemessage表里面插入一条记录,而configService会扫描这张表看是否有新插入数据,若是有变化就会通知客户端
提供登录和审计日志的功能,提供http接口给管理界面,portal须要经过rpc调用AdminService提供的配置管理的接口,portal有本身的数据库
咱们能够从两条线来看这个架构
是springcloud生态下一个服务注册和发现的插件,configService是集群部署的,并且是须要作负载均衡的,不能全部的客户端都和同一个configservice维护长链接,那么当客户端应用继续增加的时候,configservice也能够横向扩展来支撑,那么如何作到configservice在扩展的时候对应用无感呢,须要一个注册中心来作服务发现的功能,因此configservice会在启动和下线的时候通知注册中心,而客户端只须要去注册中心获取最新的configservice列表,让后选择一个就行了,而AdminService和potal之间存在rpc调用,而AdminService也是无状态而且集群化部署的,那么portal也能够经过注册中心去坐负载均衡,在其中一个AdminService节点挂了以后能够选其余的节点继续使用, 因此部署一套Eureka能够同时给configService和客户端,portal和adminService同时使用
这个服务主要是封装了Eureka的API,至关于Eureka的代理,这个服务主要是由于Eureka只有java的api作服务发现,若是应用要使用apollo便须要在客户端经过Eureka的java api获取adminservice的服务列表,而其余语言环境就没有办法了,因此MetaService提供了一个http接口供client和potal使用,客户端经过http请求MetaService就能够获取到AdminService得地址
因为上面的MetaService也是集群化部署的,那么client和portal怎么知道MetaService的地址呢,能够在nginx上配置一个域名,在nginx上作负载均衡转发到对应的metaservice, 而portal也是集群部署的,配置管理人员也须要经过域名访问nginx,在转发到对应的portal
因此portal节点和metaservice节点的增长和删除都须要在nginx上作对应的更改,而configService和AdminService则的弹性扩容则不须要