0

Yaconf - 一个高性能的配置管理扩展

 3 years ago
source link: https://www.laruence.com/2015/06/12/3051.html
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.

Yaconf - 一个高性能的配置管理扩展

这个项目其实不是一个新的idea, 这个是我在来微博以后, 第一个优化项目中顺手做的一个小工具, 本身叫做Weibo_Conf. 但是因为Weibo_Conf是属于Weibo扩展的, 里面还有一些其他功能是专门为Weibo定制的. 所以不适合直接开源.
随着PHP7的发布, 新增了很多持久化类型的支持比如IS_IMMUTABLE_ARRAY, 于是我就在PHP7下重新开发了Yaconf, 开源出来, 方便大家使用.

代码已经提交到了Github: Yaconf sources , 欢迎大家提交Issue

你也可以在PECL中直接安装,以及下载windows下的dll: Yaconf package.

首先说说, 这个是干啥的.

  • 我见过很多的项目中, 用PHP文件做配置的, 一个config目录下可能有十几个甚至数十个.php配置文件, 里面都是各种各样的array, 还有甚者会把一些词典文件(比如中文/英文对照)也放到配置中去. 这就导致配置文件的解析耗费了很大的性能(诚然, 用了opcache能好点, 但是实际上还是有执行的过程).
  • 除了PHP的, 还有用json的, yaml的, 一个共同的特点就是这些配置的可读性比较差. 另外, 他们也都要runtime解析.
  • config目录往往和代码在一起, 首先会有安全隐患(配置中往往有敏感信息), 其次如果配置和代码属于一个项目, 这就会导致配置的修改也要走代码上线的流程.
  • 一些资源配置文件, 比如mysql/memcache的配置信息, 这些内容本来是应该对开发透明的, 运维直接负责即可. 但是放到了代码中就会导致, 运维如果要发起一些变更, 也要开发配合修改配置文件上线.

所以, Yaconf就是为了解决这些问题而生的一个工具.

  • 它使用单独的一个配置目录(在yaconf.directory指定), 不和代码在一起.
  • 它在PHP启动的时候, 处理所有的要处理的配置, 然后这些配置就会常驻内存, 随着PHP的生命周期存亡. 避免了每次请求的时候解析配置文件.
  • 所有的配置内容都是immutable的, 这就可以借助于Fork的COW, 降低内存占用, 并且在访问配置的时候, 几乎不需要任何的内存Copy, 也不会有无谓的引用计数增减
  • 最重要的, 配置目录和代码分离以后, 可以借助一个配置管理后台, 来实现配置的统一化管理.
  • 它支持(对于非ZTS)配置变更重新加载, 也就是说配置如果有变化(建议更改配置一定使用mv, 不要使用cp), 它会reload, 不需要重启(检测的频率由yaconf.check_delay控制).
  • 它支持丰富的配置类型, 包括字符串, 数组, 分节, 分节继承, 并且还可以在配置中直接写PHP的常量和环境变量等.
  • 最重要的是, 它很简单.

Yaconf 只提供了俩个方法,

    1. mixed Yaconf::get(string $name, mixed $default = NULL)

    这个是获取一个配置, 名字是配置的名字, 一般来说如果你有一个ini文件叫做foo.ini, 那么$name使用foo的话就会获取到这个文件内的所有内容, 以数组形式返回. default是当配置不存在的时候返回的默认值.

    1. bool Yaconf::has(string $name)

    这个是检测一个配置是否存在.

Yaconf的配置项

  • yaconf.directory

配置文件目录, 这个配置不能通过ini_set指定, 因为必须在PHP启动的时候就确定好.

yaconf.check_delay

多久(秒)检测一次文件变动, 如果是0就是不检测, 也就是说如果是0的时候, 文件变更只能通过重启PHP重新加载

配置的格式

Yaconf采用ini文件作为配置文件, 这是因为我一直觉得ini是最适合做配置文件的, key-value格式, 清晰可读.
简单的配置写起来如下(以下全部假设ini文件的名字是test):

  1. foo="bar"
  2. phpversion=PHP_VERSION
  3. env=${HOME}

如上所示, 对于一般的配置我们都用引号引起来. 而对于没有引起来的, 会尝试以PHP的常量做解释, 也就是说我们可以直接在配置里面写PHP的常量.
另外你也看到了, 我们可以直接在配置中写环境变量, 比如上面的env:

  1. Yaconf::get("test.env"); //test是配置文件名字
  2. //string(16) "/home/huixinchen"

如上面所示, 你可以看到, 假设对于foo的值, 你可以通过如下代码访问:

  1. Yaconf::get("test.foo"); //test是配置文件名字

Yaconf也支持数组类型的配置, 写法如下:

  1. arr.0=1
  2. arr.1=2

如果是连续的数组,你也可以直接写:

  1. arr[]=1
  2. arr[]=2

那对于数组的值,你可以通过如下代码获取:

  1. Yaconf::get("test.arr");

这就获取到了test配置文件中的arr数组, 当然你也可以直接获取数组中的一个具体的值,比如你要直接获取test配置文件中arr数组的第0号元素:

  1. $arr = Yaconf::get("test.arr.0");

Yaconf也支持map类型的配置, 写法如下:

  1. map.foo=bar
  2. map.bar=foo
  3. ;你可以使用分号来写注释
  4. map2.foo.name=yaconf
  5. map2.foo.year=2015

对于map2的foo子map的name值可以通过如下形式访问:

  1. Yaconf::get("test.map2.foo.name"); //test是配置文件名字

并且, 配置文件还可以分节, 和分节继承:

  1. [parent]
  2. parent="base"
  3. children="NULL"
  4. [children : parent]
  5. children="children"

请注意配置的分节继承的语法 children:(冒号)parent, 这的意思是children节继承全部base的配置项. 然后你在children节里面定义的和parent节中同名的配置, 会覆盖掉parent中定义的内容.
对于chidlren节的children配置的值可以通过如下形式访问:

  1. Yaconf::get("test.children.children"); //test是配置文件名字

首先, 假设我们的所有的配置文件都放置在/tmp/yaconf中, 那么我们就需要在php.ini中增加如下配置:

  1. yaconf.directory=/tmp/yaconf

这样yaconf在PHP启动的时候, 就会在这个目录下找所有的*.ini文件, 然后尝试处理他们. 这里要注意的是不支持多级目录, 也就是说, yaconf只会处理yaconf.directory内的*.ini文件, 不会处理子目录里面的(这主要是为了简单考虑, 因为有分节, 你就可以一个项目定义一个ini文件).
假设/tmp/yaconf下有俩个ini文件, 分别是:
foo.ini

  1. name="yaconf"
  2. year=2015
  3. features[]="fast"
  4. features.1="light"
  5. features.plus="zero-copy"
  6. features.constant=PHP_VERSION

bar.ini

  1. [base]
  2. parent="yaconf"
  3. children="NULL"
  4. [children:base]
  5. children="set"

然后对于foo的内容:

  1. php7 -r 'var_dump(Yaconf::get("foo"));'
  2. array(3) {
  3. ["name"]=>
  4. string(6) "yaconf"
  5. ["year"]=>
  6. string(4) "2015"
  7. ["features"]=>
  8. array(4) {
  9. [0]=>
  10. string(4) "fast"
  11. [1]=>
  12. string(5) "light"
  13. ["plus"]=>
  14. string(9) "zero-copy"
  15. ["constant"]=>
  16. string(9) "7.0.0-dev"

对于bar的内容:

  1. php7 -r 'var_dump(Yaconf::get("bar"));'
  2. array(2) {
  3. ["base"]=>
  4. array(2) {
  5. ["parent"]=>
  6. string(6) "yaconf"
  7. ["children"]=>
  8. string(4) "NULL"
  9. ["children"]=>
  10. array(2) {
  11. ["parent"]=>
  12. string(6) "yaconf"
  13. ["children"]=>
  14. string(3) "set"

当然你可以用 (.)链接语法精确访问任何一个特定的值.

我的Ya系列扩展从此又多了一个新成员, 算上之前的Yaf(PHP框架), Yar(PHP RPC框架), Yac(PHP单机缓存), 大家就可以很容易搭建一套高性能的LAMP应用解决方案出来.
最后: Yaconf要求PHP7才能用 🙂

最后附上源代码链接:Yaconf at Github
PECL链接:Yaconf at PECL


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK