Fork me on GitHub

上一章 文档首页 下一章


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

1.16.1 配置的简单读取

通常,我们会有以下三个配置文件:

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' => 'chanzonghuang@gmail.com',
    );
);

我们就可以分别这样根据需要获取配置:

//app.php里面的全部配置
DI()->config->get('app');

//app.php里面的单个配置
DI()->config->get('app.version');  //返回:1.1.1

//app.php里面的多级配置
DI()->config->get('app.email.address');  //返回:'chanzonghuang@gmail.com'

其他配置文件类似,你也可以随意添加新的配置文件。

1.16.2 内外环境配置管理的策略

可以说,在项目开发中,除了我们的代码、数据和文档外,配置也是一块相当重要的组成部分,而且占据着非常重要的位置。最为明显的是,如果配置一旦出错,就很可能影响到整个系统的运行,并且远比修改代码再上线发布速度快(假设我们不用文件存储配置而是以分布式存储在各服务器内存中)。

但这里将讨论另外一个同样重要的问题,即: 不同环境下不同配置的管理和切换

现在将不同的策略分说如下。

(1)支持整包发布的环境变量配置

此种策略的主要方法就是在PHP代码中读取php-fpm中的ENV环境配置,再对应到linux环境下的profile环境变量,即:

PHP代码  -->    $_ENV环境配置  -->   Linux服务器环境变量/etc/profile

这样的好处莫过于可以支持项目代码的整包发布,而不需要在各个环境(开发环境、测试环境、回归环境、预发布环境、生产环境)来回修改切换配置,同时运维可以更好地保护服务器的账号和密码而不让开发知道。

而这样的不足则是,在对项目进行初次部署时,需要添加以上一系列的配置,而且后期维护也比较复杂麻烦,特别当机器多时。这时可以通过pupple/stacksalt这些运维工具进行自动化管理。但对于开发来说,依然会觉得有点烦锁。

(2)不同环境,不同入口

当服务器的账号和密码也是由开发来掌控时,则可以使用这种在代码层次控制的策略。

我们可以在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。

(3)持续集成下的配置管理

但个人最为建议的还是在 持续集成 下作配置管理。

因为首先,持续集成中的发布应该是经常性的,且应该是自动化的。所以,既然有自动化的支持,我们也应该及早地将配置纳入其中管理。

配置文件不同只要是环境不同,而环境不同所影响的配置文件通常只有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

1.16.3 主从数据库的配置

通常一般而言,数据库支持分表分库配置,且只有一份,即:

./Config/dbs.php

然后,我们这样指定数据库的配置:

DI()->notorm = function() {
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new PhalApi_DB_NotORM(DI()->config->get('dbs'), $debug);
};

如果需要从库时,要以参考./Config/dbs.php,创建一个从库的配置拷贝,即:

cp ./Config/dbs.php ./Config/dbs_slave.php

然后,注册一个从库的notorm:

DI()->notormSlave = function() {
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new PhalApi_DB_NotORM(DI()->config->get('dbs_slave'), $debug); //注意:配置不同
};

最后使用此从库的服务DI()->notormSlave即可完成对从库的读取操作,用法同DI()->notorm,这里不再赘述。

1.16.4 扩展你的配置读取

虽然上面有不同的配置文件管理策略,但很多实际情况下,我们的配置需要可以随时更改、下发和调整。并且在海量访问,性能要求高的情况下快速读取配置。

这就要求我们的项目既可以方便维护即时修改,又需要能够快速同步一致更新下发和读取。这样就涉及到了配置更高层的管理: 统一集中式的配置管理,还是分布式的配置管理? 文件存储,还是DB存储,还是MC缓存,还是进驻内存?

个人认为,性能最优的莫过于配置进驻内存并分布式存储。毕竟作为前端机的PHP内存这块还是相对充裕且可以利用的。但需要把这一条线打通,有点难度。

这里不过多地谈论配置更多的内容,但在PhalApi框架中,当你根据自己项目的需要实现了自己的配置读取方式后,再次简单的在入口文件重新注册即可。

1.16.5 使用Yaconf扩展快速读取配置

首先,非常感谢 @豹 同学的提议:使用Yaconf扩展快速读取配置。

虽然现在是冬天,有点冷(特别是在北京的同学),而且现在还是凌晨1点25分。但我们希望能继续将开源的热情继续下去。

以下是刚刚这几个小时努力的成果。

(1)前期准备:PHP7 的安装

具体可以参考:Linux环境PHP7.0安装

(2)前期准备:Yaconf扩展的安装

具体可以参考:laruence/yaconf

(3)使用

和正常的配置一样,简单如下:

DI()->config = new PhalApi_Config_Yaconf();

var_dump(DI()->config->get('foo')); //相当于var_dump(Yaconf::get("foo"));

var_dump(DI()->config->has('foo')); //相当于var_dump(Yaconf::has("foo"));

以上,假设我们已经有了这样的配置文件:

$ vim ./test.ini
name="PhalApi"
version="1.3.1"

需要注意的是,如果需要使用Yaconf扩展,需要PHP7的版本支持,但使用基本上和原来PhalApi的思路是完全一样的。
但还有所区别的是,配置文件的目录路径(当然也可以配置成和PhalApi的配置目录一致)、以及配置文件的格式。

Just have fun!


上一章 文档首页 下一章