3

关于配置的思考

 3 years ago
source link: https://www.zenlife.tk/%E5%85%B3%E4%BA%8E%E9%85%8D%E7%BD%AE%E7%9A%84%E6%80%9D%E8%80%83.md
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

关于配置的思考

2015-06-04

以前研究某个网游的源代码时,发现它的配置是存在数据库的。从游戏的经验倍数/暴率/某个怪物的经验/物品掉落,到登陆服务器IP端口数据库IP端口等等,差不多全部的配置都是。当时比较反感,数据是数据,配置是配置,为什么要把配置的东西存到数据库里面去呢。更底层的心理是,我讨厌任何复杂的东西。不就是一点点配置么,读配置文件就行了,凭什么还要搞出一个对数据库的依赖呢?

慢慢体会到,一个大的系统,会有好些子系统,配置文件分散在好多地方,每项可能还不知道是什么含义。我又开始怀念windows软件了那种界面的东西。点开配置,勾勾叉叉点几项就好。然后也慢慢能理解用数据库存配置的做法:可视化以及查询修改特别方便!这是配置文件远远做不到的。

后来接触的更多了。发现有许多更深层次的东西,比如灵活性vs简单。emacs可以配置得无所不能,什么按键都可以配,想做什么东西都可以改,只要改下配置文件就行了,而vi却简单得多。用户的数量表明,大多数人还是喜欢简单的。我也是喜欢简单。所以,能写死就写死,不要多搞出一项配置。能约定的就用约定风格,不要做成可配置风格。

继续说"喜欢简单"这个话题。当我的程序只需要运行在一台机器上面,改改配置文件就可以了。我喜欢这种简单。再到后来,程序要分布在各个机器上,每个机器上都需要去配置,万一哪里配置出错了还会造成很严重的问题。大多数时候发生的错误,并不是代码出了bug什么的,往往是简单的配置没弄对。比如配置系统一边写到消息队列A,而另一边却是从消息队列B在读取,系统当然不会正常工作了。这个时候单纯的配置文件好像有点力不从心了。

我开始反思这个问题,其实这是问题规模复杂性vs解决方案复杂性所导致的必然。分布式系统成长到一定规模时,大概会需要做一个配置中心。配置中心这种解决方案明显是复杂的,不符合我喜欢的简单原则。但是简单的方案又没法解决问题。说到底,是问题规模的复杂度变高了,导致相应的解决也变得复杂。当问题规模变得复杂之后,为了处理这种复杂,有两套典型的哲学。window哲学是,封装起来,掩盖这种复杂,以保持用户友好,比如GUI。unix哲学是,暴露给用户,但是让每一处细节尽量简单,简单到能够理解的程度。

上面谈的都是设计哲学的取舍,下面看一些实际的跟分布式配置相关的东西。

基于etcd/zookeeper自己撸一套解决方案。这类开源软件提供的是灵活性,可以提供分布式锁,可以用于元数据存储,当然,也可以用于服务发现和中心化配置信息。灵活的代价就是不好用,需要自己做较多工作。

disconf/diamond分别是百度和淘宝开源的分布式配置中心。不过都是Java派系的,难以跟我们的Go的生态结合。

如果要有一个分布式的配置中心,我希望有哪些东西呢?

可用性是需要保证的。一旦配置中心挂了,读不了配置,所以服务就全部起不来了。这里有一篇为什么不要把ZooKeeper用于服务发现,指出需要的是一个AP的系统。而在CP之上构建AP系统,根本就是错误的。

可视化修改。用户友好性非常重要。

动态更新。一旦改了中心化的配置,各个客户端能获取到配置的变化并相应地进行更新。

library or not? 一般都会提供一套相应的库,封装好跟配置中心的交互。客户端使用时直接调库的方法来获取配置。从简单的角度,是比读本地配置文件变复杂了,引入了更多的依赖。原本可以在自己机器就可以跑测试,而后来离开公司环境就测不了了。

内部配置和外部配置。比如说业务对redis或者nsq的依赖,这种属于外部配置。而业务内部某个队列的长度,某个超时时间,或者缓存大小等等,这种属于内部配置。外部配置我希望写成服务发现,类似一层域名到ip的转换,必要场景下还可以高可用。

既然说到了服务发现,有个很有趣的idea是利用DNS来做,比如SkyDNS。DNS是算是互联网非常基础的部件,经过验证过的东西在云时代发挥新的作用。反对的声音也有,比如这里就有提到不靠谱,由于缓存更新是不够及时的,甚至传递过程的延迟多久生效都不可知。

最后说一个考虑中的方案consul+confd。

把配置使用的数据统一到一个地方,其实随便用什么数据库都可以存储。但是这样做有单点问题,可用性达不到要求。为了处理这个问题,可以用etcd或者zookeeper这样的项目来做这里的数据库,就可以解决单点问题了。但是接下来面临的问题,是需要自己做的工作比较多。像封装客户端,可视化方面。

使用consul替换etcd可以解决这个问题。一句话描述consul是什么:"Service discovery and configuration made easy. Distributed, highly available, and datacenter-aware."

我们现在的项目是大量使用json配置文件的。改成写一个客户端库去读配置,工作量会比较大。最直接的方式,使用confd。依然维持原来的配置文件形式,不过数据却是从consul中获取得到。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK