配置【文件】处理

1    什么是配置或配置文件
配置文件就是程序的相对固定参数,让程序能够在一定程度上有运行的灵活性。
文件只是配置一种形式,例如存在某个外部的地方,能在运行的时候加载的都算配置。所以我们关注的是配置,文件只是一种形式。

2    配置[文件]格式
2.1    文件
文本格式常见:

传统的properties文件、ini文件。
相对较新的json文件、xml文件、Yaml文件、hocon(没用过)、TOML(其他同事用过,据他说是非常适合,网上也有人说可能是最好的配置格式)

非文本格式也很多了,例如:protobuff等都可以是二进制格式存在的。

文本格式修改方便,便于人阅读,但是不安全且存储尺寸效率低。二进制相反。
2.2    非文件
非文件的形式也可以有多种,例如:

传统数据库,nosql数据库,甚至一些配置中心。只要连接到这些外部的存储,都能取到配置。
3    配置[文件]的使用
配置既然是给程序运行过程中提供灵活性的,那在程序运行过程中就需要根据配置信息进行各种判断和分支等处理。
配置可以一次性读取,程序运行过程中不需要修改,但是作为配置,很多场景还是需要提供一定的动态修改灵活性。特别是长期运行的应用,如果让这些程序只能停止再启动才能变更配置的确影响可用性。当然一些对可用性要求不高的一次性执行程序或者测试程序等,可以这么做,因为这样最简单。所以不是所有程序都必须这种灵活性。

3.1    运行过程不需要修改配置:
这种场景,直接读配置到内存变量中,然后访问内存变量就可以了。甚至如果配置使用的非常不频繁,甚至可以在用的时候读取,用完连内存变量都不需要保留。

方式一:读取到内存容器中,每次用的时候再取
config_container = read_config(config_file or config_url);
config_item = config_container.get_config(config_key);
If (config_item == condition) {
}

方式一:每次用的时候直接读取
config_item = read_config(config_file or config_url, config_key);
If (config_item == condition) {
}

方式一和方式二的明细区别是性能,方式二每次都读文件,性能会差的多。

当然方式二还有个特性和方式一不同,就是如果每次使用的时候,文件内容发生了变化,后次访问会读取到新的配置文件内容。这块需要考虑一致性。所以大部分场景还是使用方式一。

3.2    运行过程中需要修改配置
要想运行过程中能修改配置,需要考虑的场景就多了,参照上面章节《运行过程中不需要修改配置》的描述,如果每次读取都从文件里面现读,当然是能读到最新修改的配置,但是性能堪忧,所以上面结论也给了:大部分情况都不适合。

那如果读取到内存中,运行过程中修改配置的话,还有那些需要考虑呢?
1、    如何知道外部的配置修改了。
2、    如果修改了,怎么通知代码去适应。

3.2.1    如何感知配置修改
订阅通知:
    文件系统有钩子,操作系统会通知。部分NoSQL或者专门的配置中心,都只是Watch模式,当数据有变化的时候会接收到通知。这种情况下效率很高,很及时而且不消耗太多的轮训资源。通知也分变化信号通知和内容变化通知,信号变化只是告诉你变了,不告诉那些变了,收到这种通知还是需要自己去查询具体那些变化了。参见后面章节。如果是内容变化通知,这种收到通知就是变化的内容,这种效率看起来很高。唯一需要注意的是避免丢失通知消息,因为一旦丢失本身程序的配置就和配置存储中的配置不一致了。这种场景需要定期做一次对账比对,保证不会长时间不一致。

主动轮询:
    当使用没有通知机制或者Watch能力的配置存储(例如配置存储在传统数据库),那就只能定期轮训了,可以开个线程背后去轮询配置的修改,这种做法有如下特点:轮询时间是配置的感知时间,太短浪费资源,太长时效性差,需要根据不同的配置特点确定。
    主动轮询也需要注意判断是否有变化,如果配置存储源能提供变化标记,则会效率高很多,否则则需要读所有的数据回来比较了。这种就不适合大量配置数据或者频度很高的场合。

3.2.2    如何读取配置的修改
如果发现配置修改了,需要读取到内存中,读取的方式也有多种:
1.    如果是订阅的是变化通知,则只收到变化的部分。
2.    如果是订阅的是变化信号,或者主动轮询返回的是变化标记,这种情况下最好配置存储能够提供变化部分的查询能力(例如按版本)。否则只能全量读取配置进行比较了。
3.    如果配置存储不能提供变化部分查询能力,则只能全量读取了。

3.2.3    如何分析配置的变化
1、    如果是订阅的变化通知,通知内就包含变化的配置;
2、    如果配置存储支持查询变化查询(例如按版本),则查询到的就是变化的配置;
3、    否则只能读取全量数据,和已经加载的数据进行逐一比较,然后识别变化部分。

3.2.4    如何应用这些配置的变化
如果这些配置是被实时使用的,则内存中的配置数据修改后,下一次使用就可以生效了。

但是如果一些配置只是在初始化阶段才生效的,配置数据修改后,需要重新初始化一下,否则就无法生效了。

还有一些配置是相互有关系,要求同时生效的,如果有这种情况,需要注意原子变更,确保一次性变更完毕。

4    一些其他考虑
4.1    批量提交变更
对于配置的修改,通常都不是一次性完成的,例如手工修改配置文件,或者使用配置工具修改配置数据库中的数据。所以数据本身或者文件本身的变化,一般都不需要及时的进行加载。所以有一个提交的过程,修改之后,调用一个机制,通知程序去加载。

这个通知机制可以是给程序发信号,或者提交时候才发送订阅通知的方式。
例如:nginx等程序,给它发配置加载信号的时候它才进行配置加载。

4.2    能力封装到SDK中
上述考虑的问题和场景很多,最好的方式还是将这些能力封装到SDK中,或者框架中,提供一个简便的使用接口。

4.3    多种能力的组合
有些程序本身已经支持了配置文件的灵活加载能力,或者基于文件的处理方式容易实现,在考虑解耦的情况下,可以将多个配置处理功能组合进行使用。
例如:你的应用程序只从本地文件中读取配置信息。类似ETCD和Consul的程序,他们有集群化配置管理能力,通过一个agent将配置服务上的配置watch到本地,生成本地的文件,又调用程序的本地文件加载能力,从而实现了配置的集中管控。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值