配置讀?。簝?nèi)外網(wǎng)環(huán)境配置的完美切換

2018-11-21 21:14 更新

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 配置的簡單讀取

通常,我們會有以下三個(gè)配置文件:

dogstar@ubuntu:Config$ tree
.
├── app.php
├── dbs.php
└── sys.php

其中app.php為項(xiàng)目應(yīng)用配置;dbs.php為分布式存儲的數(shù)據(jù)庫配置;sys.php為不同環(huán)境下的系統(tǒng)配置。

在入口文件,注冊配置組件服務(wù)后:

//$ vim ./Public/init.php

//配置
DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');

假設(shè)有這樣的app.php配置:

return array(

    'version' => '1.1.1',

    'email' => array(
        'address' => 'chanzonghuang@gmail.com',
    );
);

我們就可以分別這樣根據(jù)需要獲取配置:

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

//app.php里面的單個(gè)配置
DI()->config->get('app.version');  //返回:1.1.1

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

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

1.16.2 內(nèi)外環(huán)境配置管理的策略

可以說,在項(xiàng)目開發(fā)中,除了我們的代碼、數(shù)據(jù)和文檔外,配置也是一塊相當(dāng)重要的組成部分,而且占據(jù)著非常重要的位置。最為明顯的是,如果配置一旦出錯,就很可能影響到整個(gè)系統(tǒng)的運(yùn)行,并且遠(yuǎn)比修改代碼再上線發(fā)布速度快(假設(shè)我們不用文件存儲配置而是以分布式存儲在各服務(wù)器內(nèi)存中)。

但這里將討論另外一個(gè)同樣重要的問題,即: 不同環(huán)境下不同配置的管理和切換

現(xiàn)在將不同的策略分說如下。

(1)支持整包發(fā)布的環(huán)境變量配置

此種策略的主要方法就是在PHP代碼中讀取php-fpm中的ENV環(huán)境配置,再對應(yīng)到linux環(huán)境下的profile環(huán)境變量,即:

PHP代碼  -->    $_ENV環(huán)境配置  -->   Linux服務(wù)器環(huán)境變量/etc/profile

這樣的好處莫過于可以支持項(xiàng)目代碼的整包發(fā)布,而不需要在各個(gè)環(huán)境(開發(fā)環(huán)境、測試環(huán)境、回歸環(huán)境、預(yù)發(fā)布環(huán)境、生產(chǎn)環(huán)境)來回修改切換配置,同時(shí)運(yùn)維可以更好地保護(hù)服務(wù)器的賬號和密碼而不讓開發(fā)知道。

而這樣的不足則是,在對項(xiàng)目進(jìn)行初次部署時(shí),需要添加以上一系列的配置,而且后期維護(hù)也比較復(fù)雜麻煩,特別當(dāng)機(jī)器多時(shí)。這時(shí)可以通過pupple/stacksalt這些運(yùn)維工具進(jìn)行自動化管理。但對于開發(fā)來說,依然會覺得有點(diǎn)煩鎖。

(2)不同環(huán)境,不同入口

當(dāng)服務(wù)器的賬號和密碼也是由開發(fā)來掌控時(shí),則可以使用這種在代碼層次控制的策略。

我們可以在Public下提供不同的入口,一如:

$ mkdir ./Public/myapi
$ myapi$ tree
.
├── index.php
└── test.php

我們有這樣不同的入口,客戶端在測試時(shí),只需要將入口路徑改成:/myapi/test.php?service=XXX.XXX,而在打包發(fā)布時(shí)只需要將入口路徑改成:/myapi/?service=XXX.XXX 即可。也就是將test.php去掉。

而在服務(wù)端,僅需要在這些不同的入口文件,修改一下配置文件目錄路徑即可:

//$ vim ./Public/myapi/test.php
DI()->config = new PhalApi_Config_File(API_ROOT . '/ConfigTest');

另外,也可以通過客戶端在請求時(shí)帶參數(shù)來作區(qū)分,如帶上&env=test或者&env=prod。

(3)持續(xù)集成下的配置管理

但個(gè)人最為建議的還是在 持續(xù)集成 下作配置管理。

因?yàn)槭紫?,持續(xù)集成中的發(fā)布應(yīng)該是經(jīng)常性的,且應(yīng)該是自動化的。所以,既然有自動化的支持,我們也應(yīng)該及早地將配置納入其中管理。

配置文件不同只要是環(huán)境不同,而環(huán)境不同所影響的配置文件通常只有sys.php和dbs.php;為此,我們?yōu)闇y試環(huán)境和生產(chǎn)環(huán)境準(zhǔn)備了各自的配置文件,而在發(fā)布時(shí)自動選擇所需要的配置文件。一般地,我們建議生產(chǎn)環(huán)境的配置文件以 .prod 結(jié)尾。所以,這時(shí)我們的配置文件可能會是這樣:

dogstar@ubuntu:Config$ tree
.
├── app.php
├── dbs.php
├── dbs.php.prod
├── sys.php
└── sys.php.prod

多了生產(chǎn)環(huán)境的配置文件:dbs.php.prod和sys.php.prod。

再通過發(fā)布工具,我們就可以對不同環(huán)境的配置文件進(jìn)行快速選擇了。這里以phing為例,說明一下相關(guān)的配置和效果。

如下,在Phing的配置文件build.xml中,在生產(chǎn)環(huán)境發(fā)布過程中,我們將配置文件進(jìn)行了替換。

//$ 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" />

執(zhí)行phing發(fā)布后,將會看到對應(yīng)的這樣提示:

     [copy] Copying 1 file to /home/phapapi/Config
     [copy] Copying 1 file to /home/phapapi/Config

1.16.3 主從數(shù)據(jù)庫的配置

通常一般而言,數(shù)據(jù)庫支持分表分庫配置,且只有一份,即:

./Config/dbs.php

然后,我們這樣指定數(shù)據(jù)庫的配置:

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

如果需要從庫時(shí),要以參考./Config/dbs.php,創(chuàng)建一個(gè)從庫的配置拷貝,即:

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

然后,注冊一個(gè)從庫的notorm:

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

最后使用此從庫的服務(wù)DI()->notormSlave即可完成對從庫的讀取操作,用法同DI()->notorm,這里不再贅述。

1.16.4 擴(kuò)展你的配置讀取

雖然上面有不同的配置文件管理策略,但很多實(shí)際情況下,我們的配置需要可以隨時(shí)更改、下發(fā)和調(diào)整。并且在海量訪問,性能要求高的情況下快速讀取配置。

這就要求我們的項(xiàng)目既可以方便維護(hù)即時(shí)修改,又需要能夠快速同步一致更新下發(fā)和讀取。這樣就涉及到了配置更高層的管理: 統(tǒng)一集中式的配置管理,還是分布式的配置管理? 文件存儲,還是DB存儲,還是MC緩存,還是進(jìn)駐內(nèi)存?

個(gè)人認(rèn)為,性能最優(yōu)的莫過于配置進(jìn)駐內(nèi)存并分布式存儲。畢竟作為前端機(jī)的PHP內(nèi)存這塊還是相對充裕且可以利用的。但需要把這一條線打通,有點(diǎn)難度。

這里不過多地談?wù)撆渲酶嗟膬?nèi)容,但在PhalApi框架中,當(dāng)你根據(jù)自己項(xiàng)目的需要實(shí)現(xiàn)了自己的配置讀取方式后,再次簡單的在入口文件重新注冊即可。

1.16.5 使用Yaconf擴(kuò)展快速讀取配置

首先,非常感謝 @豹 同學(xué)的提議:使用Yaconf擴(kuò)展快速讀取配置。

雖然現(xiàn)在是冬天,有點(diǎn)冷(特別是在北京的同學(xué)),而且現(xiàn)在還是凌晨1點(diǎn)25分。但我們希望能繼續(xù)將開源的熱情繼續(xù)下去。

以下是剛剛這幾個(gè)小時(shí)努力的成果。

(1)前期準(zhǔn)備:PHP7 的安裝

具體可以參考:Linux環(huán)境PHP7.0安裝

(2)前期準(zhǔn)備:Yaconf擴(kuò)展的安裝

具體可以參考:laruence/yaconf

(3)使用

和正常的配置一樣,簡單如下:

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

var_dump(DI()->config->get('foo')); //相當(dāng)于var_dump(Yaconf::get("foo"));

var_dump(DI()->config->has('foo')); //相當(dāng)于var_dump(Yaconf::has("foo"));

以上,假設(shè)我們已經(jīng)有了這樣的配置文件:

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

需要注意的是,如果需要使用Yaconf擴(kuò)展,需要PHP7的版本支持,但使用基本上和原來PhalApi的思路是完全一樣的。
但還有所區(qū)別的是,配置文件的目錄路徑(當(dāng)然也可以配置成和PhalApi的配置目錄一致)、以及配置文件的格式。

Just have fun!

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號