目录:
- QConf介绍
- QConf优点
- QConf架构
- zookeeper 安装
- QConf安装部署
- 使用QConf
- QConf管理界面安装
- PHP SDK 扩展
- 分集群配置 - 不同环境,不同配置
- 与YCRoute框架集成 - db/redis配置化
- 灰度发布
QConf介绍:
QConf 是奇虎360开源的一款分布式配置中心。是一款非常成熟的系统组件,运行3年多,当前超过2万台机器的部署,日处理请求过千亿,并且仍有大量的新业务蜂拥接入,我在360工作的时候,经常会与它打交道。
为什么要用到他呢?
因为它做到了代码和配置的完全分离,避免开发人员被配置文件绑架,也解耦了开发和运维工程师的相互依赖。
尤其是当业务分布较广,配置分布较广的时候,就会很容易地出现一些问题,比如做了负载均衡,需要调整一下应用配置。刚好改漏了一台机,就偶尔出现一些问题,排查起来也是很吃力的。
github: https://github.com/Qihoo360/QConf
QConf优点
-
一处修改,所有机器实时同步更新,通过zookeeper 的推送,而不是轮训查询服务器的配置变化,没有无效请求。
-
相同代码,不同环境,配置不同,在业务运行时,我们开发通常会遇到Test、Beta、Online环境,即使是线上环境也可能需要有多个不同集群,针对这种情况,qconf 保证用户的代码是完全一样,但是不同环境,获取的配置值不同。
-
高效读取配置,客户端读取配置直接从共享内存获取,性能高。
-
安装部署方便,使用简单
-
服务器宕机、网络中断、集群迁移等异常情况,QConf都能保证数据的正确,对用户透明
-
支持c/c++、php、go、java、shell、luajit、node.js、perl、python 等语言
QConf架构
QConf 由3部分组成,zookeeper 服务、agent、各种语言SDK。
zookeeper
zookeeper 服务器用来存储所有的配置信息。它以节点树的形式来组织所有数据,类似于文件系统的目录结构,一个节点有名称和值两个属性,节点下又可以建立若干个子节点,如/a、/b/c、/d/e/f等都是合法的节点名。我们使用节点名代表配置项的名称,如username、timeout等,使用节点值代表配置项的值,如jack、5等。另外它以至少3台服务器组成集群,以提供高可用,它的数据是强一致性。
agent
agent相当于 ZooKeeper 客户端,与zookeeper 保持长链接,获取、维护zookeeper里的配置信息,并将配置写入本地共享内存,在每台需要用到 qconf 的机器上都需要安装。
为防止在网络中断的同时机器重启(此时共享内存内容为空,也无法通过网络去zookeeper上取值;同时会打印相关错误日志信息),agent会定期把共享内存里的所有内容持久化到磁盘上的一个dump文件里,保证在上述情况下可以取到上次备份的配置信息。
SDK
SDK封装了操作共享内存的逻辑,为用户提供读取配置值的接口。
QConf现在提供多种语言的SDK,包括C/C++、Java、PHP、Python、Lua、Go 等等。
zookeeper 安装
因为QConf 依赖zookeeper,所以我们首先来安装zookeeper
网上找个 zookeeper 安装教程,一大堆。
创建配置节点
[root@gzapi: ~]# zkCli.sh
[zk: localhost:2181(CONNECTED) 0] create /demo demo
[zk: localhost:2181(CONNECTED) 1] create /demo/confs confs
[zk: localhost:2181(CONNECTED) 2] create /demo/confs/conf1 test11111111
[zk: localhost:2181(CONNECTED) 3] create /demo/confs/conf2 test22222222
[zk: localhost:2181(CONNECTED) 4] create /demo/confs/conf3 test33333333
QConf安装部署
安装QConf 有如下两种方式可以安装QConf,可以根据自己的情况来决定:
1. 使用源码安装
git clone https://github.com/Qihoo360/QConf.git
cd QConf
mkdir build && cd build
cmake ..
make
make install
默认安装路径为 /usr/local/qconf,通过 cmake .. -DCMAKE_INSTALL_PREFIX=/opt/qconf 可以指定安装路径。
如果安装过程中遇到的 missing aclocal-1.14 的问题参考: https://github.com/Qihoo360/QConf/wiki/FAQ
2.使用rpm 包安装
1) 在 https://github.com/Qihoo360/QConf/releases 根据不同系统下载rpm包
2) rpm -ivh QConf-1.2.1-1.el6.x86_64.rpm
默认安装在 /usr/local/qconf 目录下。
使用QConf
qconf agent 配置
[root@gzapi: ~]# cd /usr/local/qconf/conf
[root@gzapi: /usr/local/qconf/conf]# ls
agent.conf idc.conf localidc
如上进入 qconf配置文件:
agent.conf - 是agent的一些基础设置。
localidc - 可以认为是存储本机所在集群的名称。
[root@gzapi: /opt/qconf/conf]# cat localidc
test
idc.conf - 可以认为是用于配置本机需要访问的QConf所在的集群,如下,该机器可以访问 localidc=test 和 localidc=online 的两个集群, agent 会通过配置的 ip:host 去与相应集群的zookeeper沟通。
############################################################################
# QCONF config #
############################################################################
# all the zookeeper host configuration.
#[zookeeper]
zookeeper.test=192.168.20.10:2181,192.168.20.11:2181,192.168.20.12:2181
zookeeper.online=10.10.20.10:2181,10.10.20.11:2181,10.10.20.12:2181
启动 qconf agent
cd /usr/local/qconf
cd bin && sh agent-cmd.sh start
export PATH=$PATH:/usr/local/qconf/bin
shell命令获取配置值
[root@gzapi: /opt/qconf/bin]# qconf get_conf /demo/confs/conf1
test11111111
[root@gzapi: /opt/qconf/bin]# qconf get_batch_keys /demo/confs
conf1
conf2
conf3
QConf管理界面安装
为了完成对zk节点的crud操作,考虑到zookeeper的命令行操作不很友好,为了方面快速使用体验QConf功能,QConf提供了管理端界面来方便操作,QConf 只需要安装在一台机器上即可。
安装
界面本身使用c++编写,同样采用cmake的构建方式。(CMake 版本 2.6及以上)
https://github.com/Qihoo360/QConf/tree/master/manager
进入 manager 目录,通过下面命令安装:
cd QConf/manager
mkdir build && cd build
cmake ..
make
make install
默认的安装目录为 /usr/local/qconf/manage,使用 cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/qconf_manager 指定安装路径。
使用
进入安装目录,启动web server,默认端口为 8080, 可以通过listening_port 设定
./web_server -listening_port 8080
配置文件中配置zookeeper集群地址,配置文件位置:www/conf/idc.conf
############################################################################
# QCONF config #
############################################################################
# all the zookeeper host configuration.
#[zookeeper]
zookeeper.test=192.168.20.10:2181,192.168.20.11:2181,192.168.20.12:2181
zookeeper.online=10.10.20.10:2181,10.10.20.11:2181,10.10.20.12:2181
通过浏览器访问 [SERVER_IP]:8080/qconf_manage.cgi 可以看到如下管理界面:
在上图,我们看到了配置的节点,以及在 www/conf/idc.conf 配置的集群idc列表。
- QConf Node Infomation 中可以对Zookeeper 上的节点进行添删改查操作,Path输入要操作的节点;Idc选择机房,机房信息对应于www/conf/idc.conf配置文件中的key值;Value显示"Check"后的当前值,并可以修改为新值,并在"Add Or Modify"后生效;“Delete”用来删除节点,前提是没有子节点存在
- Children Nodes 显示当前节点的所有子节点信息,点击“View”查看详情
- Parent Node 显示父节点,点击“View”查看详情
PHP SDK 扩展
安装
如下命令编译安装 php 扩展,支持 php 7,其中 --with-libqconf-dir 和 LDFLAGS 指向的是qconf安装目录下的头文件和静态库。
cd QConf/driver/php
/path/to/phpize #path to is your PHP install dir
./configure --with-php-config=/path/to/php-config --with-libqconf-dir=/usr/local/qconf/include --enable-static LDFLAGS=/usr/local/qconf/lib/libqconf.a
make
make install
API 函数
getConf
getConf(key, idc, get_flag)
Description
获取配置值,最常用
Parameters
key - 配置的key,也就是 zookeeper 的节点路径
idc - 可选,默认是 localidc 文件里指定的本机所在集群,否则到 /usr/local/qconf/conf/idc.conf下配置的idc去取值
get_flag - 可选,set get_标志为0时,如果配置尚未在共享内存中,qconf将等待直到超时,key不存在或第一次获取key时会发生。如果为1,qconf立即返回空,默认get_标志为0
Return Value
成功返回配置值,失败返回NULL
Example
$value = Qconf::getConf("/demo/confs/conf1");
getBatchKeys
getBatchKeys(key, idc, get_flag);
Description
获取所有字节点的 key
Parameters
与 getConf 相同
Return Value
成功返回子节点所有 key 的数组,失败返回NULL
Example
$children_keys = Qconf::getBatchKeys("/demo/confs");
getBatchConf
getBatchConf(key, idc, get_flag);
Description
获取所有字节点的 key 和 value
Parameters
与 getConf 相同
Return Value
成功返回子节点所有 key/value 的数组,失败返回NULL
Example
$children_conf = Qconf::getBatchConf("/demo/confs");
getAllHost
getAllHost(key, idc, get_flag);
Description
获取指定key下的所有可用服务
Parameters
与 getConf 相同
Return Value
成功返回所有host的数组,失败返回NULL
Example
$hosts = Qconf::getAllHost("demo/hosts");
getHost
getHost(key, idc, get_flag);
Description
获取指定key下的一个可用的服务
Parameters
与 getConf 相同
Return Value
成功返回可用的host,失败返回NULL
Example
$host = Qconf::getHost("demo/hosts");
分集群配置 - 不同环境,不同配置
在业务运行时,有可能遇到 测试环境,开发环境,线上环境等等,即使是线上环境也可能需要有多个不同集群,针对这种情况,qconf 保证用户的代码是完全一样,需要做的是,
1)针对不同的环境搭建各自的集群环境,然后在 idc.conf 配置文件中添加相应的服务器信息, 如下 idc.conf:
# QCONF config #
############################################################################
# all the zookeeper host configuration.
#[zookeeper]
zookeeper.test=127.0.0.1:2181,192.168.20.10:2181,192.168.20.11:2181
zookeeper.online=10.10.20.10:2181,10.10.20.11:2181,10.10.20.12:2181
2)再将每个环境下的localidc指定为对应的集群名称,如测试环境修改为test,线上环境修改为online。
3)在管理平台的配置文件 /usr/local/qconf/manage/demo/www/conf/idc.conf 把两个集群的也配置上。
# QCONF config #
############################################################################
# all the zookeeper host configuration.
#[zookeeper]
zookeeper.test=127.0.0.1:2181,192.168.20.10:2181,192.168.20.11:2181
zookeeper.online=10.10.20.10:2181,10.10.20.11:2181,10.10.20.12:2181
4)然后在管理后台,将online环境idc集群的节点 /demo/confs/conf1 值修改如下:
5) 在两个环境验证:
//test.php
$value = Qconf::getConf("/demo/confs/conf1");
var_dump($value);
从上图我们可以看到,相同的代码,两个环境获取的配置值是不同的,原理就是 agent 根据配置 /usr/local/qconf/conf/localidc 配置的本机所在idc集群,然后到 /usr/local/qconf/conf/idc.conf 中相应idc集群下获取qconf配置。
6)获取其他idc集群配置
当然,我们在Test环境也是可以获取 Online 环境配置的,通过指定idc 如下:
$value = Qconf::getConf("/demo/confs/conf1", "online");
var_dump($value);
从上面可以看到测试环境下的节点取值为 online11111111, 该配置能够成功获取的前提是,本地 /usr/local/qconf/conf/idc.conf 文件中配置了 online idc集群的信息: zookeeper.online=10.10.20.10:2181,10.10.20.11:2181,10.10.20.12:2181
与YCRoute框架集成 - db/redis配置化
文件读取配置方式
YCRoute 是我写的一个MVC 框架。
https://blog.csdn.net/caohao0591/article/details/87072298
database、redis 在框架中都有各自的代理层, 分别从 framework/application/config/ 目录下 database.php 和 redis.php 读取配置。
//database.php
$db['default']['host'] = '127.0.0.1';
$db['default']['username'] = 'root';
$db['default']['password'] = 'test123123';
$db['default']['dbname'] = 'userinfo';
$db['default']['pconnect'] = FALSE;
$db['default']['db_debug'] = TRUE;
$db['default']['char_set'] = 'utf8';
$db['default']['dbcollat'] = 'utf8_general_ci';
$db['default']['autoinit'] = FALSE;
$db['default']['port'] = 3306;
//redis.php
$redis_conf['userinfo']['host'] = '127.0.0.1';
$redis_conf['userinfo']['port'] = 6379;
qconf读取方式
以上配置模式在单机情况下,是比较好用,但是在集群情况下,并不算灵活,而且文件IO效率低,远不如共享内存的性能高,
如果采用 qconf 配置,在集群模式下,不仅更加灵活,而且还有这非常高的性能,同时,针对测试环境、线上环境等不同环境,一套代码可以设置不同的配置。
在 YCRoute 中只需将framework中的index.php 中 USE_QCONF 置为 true,然后就可以用Loader::config("/config/user/database"); 即可加载QConf 配置的 database 和 redis,
//index.php
...
define("USE_QCONF", true);
...
管理平台配置
使用方式
class UserinfoModel extends Core_Model {
public function __construct() {
$this->db = Loader::database('/config/user/database');
$this->util_log = Logger::get_instance('userinfo_log');
}
...
public function getUserByName($nickname) {
return $this->db->query("select * from user_info where nickname like '%$nickname%'");
}
}
原理代码
function &DBLoader($params = '')
{
if(USE_QCONF) {
$config_str = Qconf::getConf($params);
$config = json_decode($config_str, true);
if(empty($config_str)) {
show_error('You have specified an invalid database connection group.');
}
} else {
//config/database.php文本获取配置
...
$config = $db[$params];
}
require_once(BASEPATH.'/ycdb/YCDB_Driver.php');
$DB = new YCDB_Driver($config);
if ($DB->autoinit == TRUE) {
$DB->initialize();
}
return $DB;
}
Redis的QConf配置
同database 的配置
灰度发布
敬请期待。。。