配置持久化框架diamond简介及高阶应用
Posted 星力量
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了配置持久化框架diamond简介及高阶应用相关的知识,希望对你有一定的参考价值。
配置持久化框架diamond简介及高阶应用
前言
一、简介
二、特点
三、应用场景
四、server搭建
五、发布配置数据
六、简单应用
七、高阶应用
八、spring动态集成diamond
结束语
前言
配置持久化框架diamond 为淘宝内部使用的一个管理持久配置的系统,本次分享除介绍diamond的简单应用外,还将介绍更高级的应用场景。
一、简介
diamond为应用系统提供了获取配置的服务,应用不仅可以在启动时从diamond获取相关的配置,而且可以在运行中对配置数据的变化进行感知并获取变化后的配置数据.
diamond的源代码:http://code.taobao.org/svn/diamond/trunk
二、特点
diamond的特点是简单、可靠、易用:
简单:整体结构非常简单,从而减少了出错的可能性。
可靠:应用方在任何情况下都可以启动,在承载阿里核心系统并正常运行多年来,没有出现过任何重大故障。
易用:客户端使用只需要两行代码,暴露的接口都非常简单,易于理解。
三、应用场景
应用场景:
1.分表分库的DB服务器地址.
2.中间件的服务地址.
3.经常变化的开关,配置.
四、server搭建
(1)mysql
安装mysql-server的步骤请参考mysql官方文档,安装完毕后,建立数据库,然后建立两张表,建表语句分别如下:
create table config_info (
`id` bigint(64) unsigned NOT NULL auto_increment,
`data_id` varchar(255) NOT NULL default ’ ’,
`group_id` varchar(128) NOT NULL default ’ ’,
`content` longtext NOT NULL,
`md5` varchar(32) NOT NULL default ’ ’,
`src_ip` varchar(20) default NULL,
`src_user` varchar(20) default NULL,
`gmt_create` datetime NOT NULL default ’2010-05-05 00:00:00′,
`gmt_modified` datetime NOT NULL default ’2010-05-05 00:00:00′,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_config_datagroup` (`data_id`,`group_id`)
);
create table group_info (
`id` bigint(64) unsigned NOT NULL auto_increment,
`address` varchar(70) NOT NULL default ’ ’,
`data_id` varchar(255) NOT NULL default ’ ’,
`group_id` varchar(128) NOT NULL default ’ ’,
`src_ip` varchar(20) default NULL,
`src_user` varchar(20) default NULL,
`gmt_create` datetime NOT NULL default ’2010-05-05 00:00:00′,
`gmt_modified` datetime NOT NULL default ’2010-05-05 00:00:00′,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_address` (`address`,`data_id`,`group_id`)
);
建表完成后,请将数据库的配置信息添加到diamond-server工程的src/resources/jdbc.properties文件中。
(2)tomcat
tomcat是diamond server的运行容器。
tomcat的安装请参考tomcat官方文档,建议使用tomcat7
不需要对tomcat进行任何改动。
(3)diamond server
在diamond-server源代码根目录下,执行mvn clean package -Dmaven.test.skip,成功后会在diamond-server/target目录下生成diamond-server.war(如果没有安装maven,请参考maven官方文档进行安装)。
打包完成后,将diamond-server.war放在tomcat的webapps目录下。
(4)http server
http server用来存放diamond server等地址列表,可以选用任何http server,这里以tomcat为例。
安装tomcat的步骤请参开tomcat官方文档,注意,如果http server和diamond server安装在一台机器上,请修改http server的端口,避免冲突。
修改完端口后,请将diamond-utils工程下的com.taobao.diamond.common.Constants类中的DEFAULT_PORT常量修改成对应的端口号。
安装完成后,请在tomcat的webapps下建立文件夹diamond-server和pushit-server,diamond-server中再建立diamond文件,文件内容是diamond-server的地址列表,一行一个地址,地址为ip;pushit-server中也建立diamond文件,文件内容是pushit-server的地址列表,一行一个地址,地址为ip:port(pushit后文会进行叙述)
(5)pushit
pushit是一个轻量级的消息通知服务组件,用来为diamond做实时通知服务,通知客户端数据的变化,它也是CS的结构,服务端搭建步骤如下:
在pushit源代码根目录下,执行mvn clean package assembly:assembly -Dmaven.test.skip命令,成功后会在pushit/target目录中看到pushit-pushit.tar.gz包。
执行tar -xzvf pushit-pushit.tar.gz,进行解压。
进入pushit目录,建立logs目录,在logs目录中建立pushit.log文件。
进入pushit/bin目录,执行./pushit-startup.sh ../conf/server.properties命令,启动pushit-server
(6)redis
redis用来存放一些跟统计相关的信息。
redis的安装请参考redis的官方文档。
安装完成后,请在diamond-server的配置文件redis.properties中填写对应的信息。
完成以上6步后,server端的搭建就完成了。
五、发布配置数据
diamond发布数据通过手工的方式进行。
修改diamond-server的配置文件user.properties,以k=v的方式添加登录diamond-server的用户名和密码。
在浏览器中输入http://ip:port/diamond-server/,ip和port为server搭建的第(2)步中的地址和端口,登录后进入后台管理界面,然后点击“配置信息管理”—— “添加配置信息”,在输入框中输入dataId、group、内容,最后点击“提交”即可。
成功后,可以在“配置信息管理”中查询到发布的数据。
六、简单应用
diamond客户端API主要提供了订阅数据的功能.
(1)客户端获取服务端地址
获取服务端地址对客户端是透明的,客户端仅仅需要在本地进行如下域名绑定即可:
domain ip
其中,domain的值与diamond-utils工程下的com.taobao.diamond.common.Constants类中的DEFAULT_DOMAINNAME和DAILY_DOMAINNAME的值相同,ip为server搭建第(4)步中的http server地址。
(2)创建订阅者
DiamondManager manager = new DefaultDiamondManager(group, dataId, new ManagerListener()
public void receiveConfigInfo(String configInfo)
// TODO:客户端处理数据的逻辑
);
参数的说明:
group和dataId为String类型,二者结合为diamond-server端保存数据的惟一key
ManagerListener 是客户端注册的数据监听器, 它的作用是在运行中接受变化的配置数据,然后回调receiveConfigInfo()方法,执行客户端处理数据的逻辑。如果要在运行中对变化的配置数据进行处理,就一定要注册ManagerListener
(3)获取配置数据
String configInfo = manager.getAvailableConfigInfomation(timeout);
diamond-server端保存的配置全都为文本类型,返回给客户端的配置数据为java.lang.String类型,timeout为从网络获取配置数据的超时时间。客户端调用每次调用该方法,都能够保证获取一份最新的可用的配置数据。
七、高阶应用
通过 AbstractDynamicConfig 实例化时注册 RemoteConfigManagerListener 来绑定diamond监听,来实现实例对象通过感知远程数据配置变更而动态变更自身的目的.
核心代码:
DynamicConfig
import org.oschina.config.dynamic.source.ConfigSource;
/**
* 动态配置组件
*
*/
public interface DynamicConfig extends IProperties
/**
* 分组
* @return
*/
public String getGroup();
/**
* 配置名称(默认取类全名)
* @return
*/
public String getName();
/**
* 配置文件properties路径
* @return
*/
public String getConfigPath();
/**
* 加载配置文件列表
* @return
*/
public ConfigSource[] getSources();
/**
* 初始化 配置(由实例外面来调用 , 或由容器实例化对象后调用)
* @return
*/
public boolean init();
/**
* 退出系统之前的所做的操作(由容器来调用)
*/
public void destroy();
/**
* 根据 文本内容 初始化配置组件属性
* @param content
* @return
*/
public boolean dynamicChangeConfig(String content);
/**
* 动态变更配置组件属性值
* @param field
* @param value
* @return
*/
public boolean dynamicChangeConfig(String field ,String value);
AbstractDynamicConfig
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.oschina.config.dynamic.enums.MethodTypeEnum;
import org.oschina.config.dynamic.listener.RemoteConfigManagerListener;
import org.oschina.config.dynamic.source.ConfigSource;
import org.oschina.config.dynamic.source.SourceTypeEnum;
import org.oschina.config.dynamic.utils.DynamicConfigUtils;
import org.oschina.config.dynamic.utils.IOUtils;
/**
* 动态配置组件(实现了基本的功能方法)
* - initConfig(sources); -- 由外部来调用
-
*
- setRemoteConfigManagerListener(remoteConfigManagerListener); -- 由外部来调用
-
*
*/
public abstract class AbstractDynamicConfig implements DynamicConfig
protected Log logger = LogFactory.getLog(this.getClass());
protected Set
supportedSourceTypes;//支持的资源类型(默认为 properties)
protected ConfigSource[] sources;//资源列表
protected Properties resultProp = new Properties();
protected boolean initFlag = false;//初始化标识
protected Map
initParams = null;//初始化时参数配置
protected String defaultGroup = "defaultGroup";
protected RemoteConfigManagerListener remoteConfigManagerListener;//监听器
public RemoteConfigManagerListener getRemoteConfigManagerListener()
return remoteConfigManagerListener;
public void setRemoteConfigManagerListener(RemoteConfigManagerListener remoteConfigManagerListener)
logger.info("setRemoteConfigManagerListener(" + remoteConfigManagerListener + ")...");
if(!initFlag)
logger.warn("setRemoteConfigManagerListener(" + remoteConfigManagerListener + ")...init()");
this.init();
if(null != this.remoteConfigManagerListener)
this.remoteConfigManagerListener.unregister(this,getInitParams());
logger.info("[" + this.remoteConfigManagerListener + "] unregister(" + this + ")");
//重设监听器
this.remoteConfigManagerListener = remoteConfigManagerListener;
if(null != this.remoteConfigManagerListener)
this.remoteConfigManagerListener.register(this,getInitParams());
logger.info("[" + this.remoteConfigManagerListener + "] register(" + this + ")");
/**
* 支持的资源类型(默认为 properties)
* @return
*/
public Set
getSupportedSourceTypes()
if(null == supportedSourceTypes)
supportedSourceTypes = new HashSet
();
if(supportedSourceTypes.isEmpty())
supportedSourceTypes.add(SourceTypeEnum.properties);
return supportedSourceTypes;
public void setSupportedSourceTypes(Set
supportedSourceTypes) this.supportedSourceTypes = supportedSourceTypes; public Map
getInitParams() return initParams; public void setInitParams(Map
initParams) this.initParams = initParams; /** * 构造(子类必须隐式或显示调用) */ public AbstractDynamicConfig() super(); if(logger.isDebugEnabled()) logger.debug("AbstractDynamicConfig[" + this.getConfigPath() + "] instanced."); /* * (non-Javadoc) */ public boolean init() boolean flag = false; if(initFlag) logger.warn("initConfig repeat -- sources=[" + sources + "]"); return false; ConfigSource[] sources = getSources(); if(null != sources) for(ConfigSource source : sources) try Properties localProp = new Properties(); localProp.load(IOUtils.getInputStream(source.getPath())); updateProperties(localProp); catch (Exception e) logger.error("dynamicChangeConfig loadProperties and updateProperties["+ e.toString() + "]"); logger.info("initConfig[" + flag + "] -- sources=[" + sources + "]"); initFlag = true; return flag; public void updateProperties(Properties prop) Enumeration
以上是关于配置持久化框架diamond简介及高阶应用的主要内容,如果未能解决你的问题,请参考以下文章