配置(Configuration) 这个概念每一个技术人都不陌生,能够说一个不提供几个配置参数的系统都很差意思上线跟别的系统打招呼。php
究其本质是咱们人类没法掌控和预知一切,映射到软件领域上,咱们老是须要对系统的某些功能特性预留出一些控制的线头,以便咱们在将来须要的时候,能够人为的拨弄这些线头从而控制系统的行为特征,我把它叫作 “系统运行时(runtime)飞行姿态的动态调整“。mysql
咱们的系统存在一些外部依赖,这些依赖与业务无关,可是在开发阶段具备不肯定性,咱们一般会将这些配置在属性文件中,如数据库url,帐户名,密码,等,这些配置项基本不会轻易改变,并且配置也简单,基本都是字符串,因此称他们为静态配置
git
所谓静态配置,就是在程序启动前一次性配好,启动时一次性生效,在程序运行期通常不会变化的配置。github
具体包括:sql
有些配置是和环境相关的,每一个环境的配置不同,例如数据库、中间件和其它服务的链接字符串配置。这些配置一次性配好,运行期通常不变。数据库
有些配置和安全相关,例如用户名,密码,访问令牌,许可证书等,这些也是一次性配好,运行期通常不变。由于涉及安全,相关信息通常须要加密存储,对配置访问须要权限控制。c#
咱们在业务开发中,会提早预料到业务的不肯定性,而产生的复杂的业务配置项,类型简单的可使数字,字符,复杂点的能够是数组,map,以及其混合的组织形式,因为业务需求,会须要经常发生改变,这类配置项,咱们称为动态配置。
数组
所谓动态配置,就是在程序的运行期能够根据须要动态调整的配置。动态配置让应用行为和功能的调整变得更加灵活,是持续交付和 DevOps 的最佳实践。
缓存
和应用相关的配置,例如服务请求超时,线程池和队列的大小,缓存过时时间,数据库链接池的容量,日志输出级别,限流熔断阀值,服务安全黑白名单等。通常开发或者运维会根据应用的实际运行状况调整这些配置。安全
和业务相关的一些配置,例如促销规则,贷款额度,利率等业务参数,A/B 测试参数等。通常产品运营或开发人员会根据实际的业务需求,动态调整这些参数。
在英文中也称 Feature Flag/Toggle/Switch,简单的只有真假两个值,复杂的能够是多值参数。功能开关是 DevOps 的一种最佳实践,在运维中有不少应用场景,好比蓝绿部署,灰度开关,降级开关,主备切换开关,数据库迁移开关等。功能开关在国外互联网公司用得比较多,国内尚未普及开,因此我在下一节会给出一些功能开关的高级应用场景。
在单机时代,咱们都是用配置文件来存储配置项。一个配置文件通常是一组配置项的集合或者叫配置集,一个系统根据逻辑模块划分,能够有1到多个配置文件。
在集中式开放时代,配置文件基本够用了,由于那是配置的管理一般不会成为一个很大的问题。若是要修改一个配置,登陆到这台机器上,登陆到这台生产机器上,vi配置这个配置文件,而后reload一下并非很大的负担。
在分布式系统中,一次构建、发布、上线是很是很是重的一个过程,它不像单机时代那样重启一台机器、一个进程就能够了。
在分布式系统中,它涉及到将软件包(例如war)分发到可能超过几千台机器,而后将几千台机器上的应用进程一一重启这么一个过程,超过2000台机器的一个应用一次完整的发布过程须要多长时间,相信你们都必定会清楚,因此从时效性上来讲,配置中心是势在必行。
分发到几千台机器上,谁能保证几千次配置都会一致,不会有哪一个人手误致使文件更改有错误,因此有一个应用统一管理管理配置,以后其余应用须要更改本地配置的时候,来向配置中心拉取,以后替换配置,以后从新发布就行了,这样就能保证全部机器上的配置的都一致。
在分布式计算技术的设计和实现中,CAP理论是一个重要的指导原则,其基本内容以下:
一、“C”是指一致性,即当一个Process(过程)修改了某个数据后,其余Process读取这是数据是,获得的是更新后的数据,但并非全部系统都 能够作到这一点。例如,在一些并不是严格要求一致性的系统中,后来的Process获得的数据可能仍是修改以前的数据,或者须要等待必定时间后才能获得修改 以后的数据,这被成为“弱一致性”,最经典的应用就是DNS系统。当用户修改了DNS配置后,每每不会立刻在全网更新,一定会有一个延迟,这个延迟被称为 “不一致窗口”,它的长度取决于系统的负载、冗余的个数等因素。但对于某些系统而言,一旦写入,后面读取的必定是修改后的数据,如银行帐户信息,这被称为 “强一致性”。
二、“A”是指可用性。即系统老是可以为用户提供连续的服务能力。当用户发出请求是,系统能给出响应(成功或者失败),并且是当即给出响应,而不是等待其余事情完成才响应。若是须要等待某件事情完成才响应,那么“可用性”就不存在了。
三、“P”是指容错性。任何一个分布式计算系统都是由多个节点组成的。在正常状况下,节点与节点之间的通讯是正常的。可是在某些状况下,节点之间的通讯会 断开,这种断开成为“Partition”。在分布式计算的实现中,Partition是很常见的,由于节点不可能永远不出故障,尤为是对于跨物理地区的 海量存储系统而言,而容错性则能够保证若是只是系统中的部分节点不可用,那么相关的操做仍旧可以正常完成。
通过上面的内容,你们知道确定要有一个配置中心来统一管理,经过配置中心系统对每一条配置(每个配置有惟一的配置ID)进行增删改查。区分不一样环境的配置,每一个环境同一配置ID对应不一样数据库记录。配置最终以key-value储存在mysql数据库中。
1.
能够有一个配置中心,经过配置中心对每一条配置进行增删改查,配置最终以key-value储存在mysql数据库,配置对外服务,多机器部署,知足性能须要。应用直接去调用配置中心提供的接口查询配置,这样可能对数据库压力太大,这样的话能够在配置中心添加缓存,每次查询缓存,这样的话每次查询的时候,就不会调用数据库,每次可用直接查询缓存,每次更改配置的时候,顺便更改缓存,这样能保证可用性和一致性。
不少时候,这样能够基本上知足咱们对配置系统的基本需求,对配置的增删改查,能容忍一段时间的数据不一致性。
这种设计,因为全部的配置都存放在集中式缓存中,这样集中式的缓存也会有他的性能瓶颈。并且,每次配置的访问都须要发起rpc请求(网络请求),所以考虑在客户端引入本地缓存(localCache,例如Ehcache)。
2.
能在服务端使用缓存,为何不能再客户端使用缓存呢。
使用客户端缓存,那么缓存存在哪呢?
在客户端使用缓存能够分红三种,分布式缓存,内存和硬盘。
可是这三种各有利弊。
分布式缓存 那么网络资源的耗费没有获得节约,可是能够保证应用读取的配置一致性的保证。
内存 不用耗费网络资源,很快,可是重启会丢失配置
硬盘 不用耗费网络资源,不会丢失配置,相对来讲会慢一些
考虑到,减小网络请求的因素,在客户端引入localcache,虽然内存和硬盘能够节省网络资源,可是内存和硬盘都存在各自的缺点,那么咱们能够采用内存+硬盘的格式,把资源保存再硬盘里,每次重启时在从硬盘中读取以后加载到内存中。这样的话来解决系统的高可用,高性能、可伸缩性。
一致性的话的咱们能够采用缩短更新缓存的问题来解决。也能够经过配置中心通知应用配置更新,应用从配置中心拉取最新的配置、更新本地配置并通知到应用。
与c#、Java、Go、Python、Node.JS等等应用不一样,php的程序不支持常驻内存,php每处理完一个请求后,资源都会被释放掉;这也就意味着若是咱们在请求进来时,都须要去访问配置中心得到各类配置信息。
由于配置中心是外部程序,每次访问都是跨进程通信;假设获取一个配置须要耗时1ms,那么一百项配置就是0.1s;这是巨大的潜在性能影响。
get_key
函数时,便会自动去配置中心得到新值,并从新缓存。