Experience by itself teaches nothing... Without theory, experience has no meaning. Without theory, one has no questions to ask. Hence, without theory, there is no learning. – Edwards Deming
通常,我们会有以下三个配置文件:
dogstar@ubuntu:Config$ tree . ├── app.php ├── dbs.php └── sys.php
其中app.php为项目应用配置;dbs.php为分布式存储的数据库配置;sys.php为不同环境下的系统配置。
在入口文件,注册配置组件服务后:
//$ vim ./Public/init.php //配置 DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');
假设有这样的app.php配置:
return array( 'version' => '1.1.1', 'email' => array( 'address' => '[email protected]', ); );
我们就可以分别这样根据需要获取配置:
//app.php里面的全部配置 DI()->config->get('app'); //app.php里面的单个配置 DI()->config->get('app.version'); //返回:1.1.1 //app.php里面的多级配置 DI()->config->get('app.version'); //返回:[email protected]
其他配置文件类似,你也可以随意添加新的配置文件。
可以说,在项目开发中,除了我们的代码、数据和文档外,配置也是一块相当重要的组成部分,而且占据着非常重要的位置。最为明显的是,如果配置一旦出 错,就很可能影响到整个系统的运行,并且远比修改代码再上线发布速度快(假设我们不用文件存储配置而是以分布式存储在各服务器内存中)。
但这里将讨论另外一个同样重要的问题,即: 不同环境下不同配置的管理和切换 。
现在将不同的策略分说如下。
此种策略的主要方法就是在PHP代码中读取php-fpm中的ENV环境配置,再对应到linux环境下的profile环境变量,即:
PHP代码 --> $_ENV环境配置 --> Linux服务器环境变量/etc/profile
这样的好处莫过于可以支持项目代码的整包发布,而不需要在各个环境(开发环境、测试环境、回归环境、预发布环境、生产环境)来回修改切换配置,同时运维可以更好地保护服务器的账号和密码而不让开发知道。
而这样的不足则是,在对项目进行初次部署时,需要添加以上一系列的配置,而且后期维护也比较复杂麻烦,特别当机器多时。这时可以通过pupple/stacksalt这些运维工具进行自动化管理。但对于开发来说,依然会觉得有点烦锁。
当服务器的账号和密码也是由开发来掌控时,则可以使用这种在代码层次控制的策略。
我们可以在Public下提供不同的入口,一如:
$ mkdir ./Public/myapi $ myapi$ tree . ├── index.php └── test.php
我们有这样不同的入口,客户端在测试时,只需要将入口路径改成:/myapi/test.php?service=XXX.XXX,而在打包发布时只需要将入口路径改成:/myapi/?service=XXX.XXX 即可。也就是将test.php去掉。
而在服务端,仅需要在这些不同的入口文件,修改一下配置文件目录路径即可:
//$ vim ./Public/myapi/test.php DI()->config = new PhalApi_Config_File(API_ROOT . '/ConfigTest');
另外,也可以通过客户端在请求时带参数来作区分,如带上&env=test或者&env=prod。
但个人最为建议的还是在 持续集成 下作配置管理。
因为首先,持续集成中的发布应该是经常性的,且应该是自动化的。所以,既然有自动化的支持,我们也应该及早地将配置纳入其中管理。
配置文件不同只要是环境不同,而环境不同所影响的配置文件通常只有sys.php和dbs.php;为此,我们为测试环境和生产环境准备了各自的配置文件,而在发布时自动选择所需要的配置文件。一般地,我们建议生产环境的配置文件以 .prod 结尾。所以,这时我们的配置文件可能会是这样:
dogstar@ubuntu:Config$ tree . ├── app.php ├── dbs.php ├── dbs.php.prod ├── sys.php └── sys.php.prod
多了生产环境的配置文件:dbs.php.prod和sys.php.prod。
再通过发布工具,我们就可以对不同环境的配置文件进行快速选择了。这里以phing为例,说明一下相关的配置和效果。
如下,在Phing的配置文件build.xml中,在生产环境发布过程中,我们将配置文件进行了替换。
//$ vim ./build.xml <copy file="./Config/dbs.php.prod" tofile="./Config/dbs.php" overwrite="true" /> <copy file="./Config/sys.php.prod" tofile="./Config/sys.php" overwrite="true" />
执行phing发布后,将会看到对应的这样提示:
[copy] Copying 1 file to /home/phapapi/Config [copy] Copying 1 file to /home/phapapi/Config
虽然上面有不同的配置文件管理策略,但很多实际情况下,我们的配置需要可以随时更改、下发和调整。并且在海量访问,性能要求高的情况下快速读取配置。
这就要求我们的项目既可以方便维护即时修改,又需要能够快速同步一致更新下发和读取。这样就涉及到了配置更高层的管理: 统一集中式的配置管理,还是分布式的配置管理? 文件存储,还是DB存储,还是MC缓存,还是进驻内存?
个人认为,性能最优的莫过于配置进驻内存并分布式存储。毕竟作为前端机的PHP内存这块还是相对充裕且可以利用的。但需要把这一条线打通,有点难度。
这里不过多地谈论配置更多的内容,但在PhalApi框架中,当你根据自己项目的需要实现了自己的配置读取方式后,再次简单的在入口文件重新注册即可。