super-diamond服务器搭建及应用
Super-diamond是在淘宝diamond基础上改良而来,是一套优秀的配置管理服务器,由于工作中需要用到,就简单学习了一下,并将其记录下来,源码地址点击这里下载先上一张服务流程图,画的简陋请包涵 主要功能配置管理系统提供系统参数配置管理,例如数据库的配置信息等,配置参数修改以后可以实时推送到客户端(基于netty4), 方便系统动态修改运行参数。可以建多个项目,每个项目分为三种pro
Super-diamond是在淘宝diamond基础上改良而来,是一套优秀的配置管理服务器,由于工作中需要用到,就简单学习了一下,并将其记录下来,源码地址点击这里下载
先上一张服务流程图,画的简陋请包涵
- 主要功能
- 配置管理系统提供系统参数配置管理,例如数据库的配置信息等,配置参数修改以后可以实时推送到客户端(基于netty4), 方便系统动态修改运行参数。
- 可以建多个项目,每个项目分为三种profile场景(development、test、production)。
- 所有参数均由development profile配置,test和production profile继承development profile配置,也可以覆盖其配置。 test和production profile只提供修改功能。
- client 备份配置信息到本地文件系统,如果server不可用,可以使用本地备份。client 能够定时重连server,保证client高可用。
- client 提供ConfigurationListener,当某个属性发生变化(add、update、clear), ConfigurationListener能够接收到ConfigurationEvent,作相应的触发事件进行处理。
- server 备份配置文件系统系统,如果数据库不用,能够保证对客户端提供数据(待完善)。 - 目录结构
导入编辑器后,目录结构如下
一个是客户端,一个是服务端,客户端即在你需要的项目pom文件中加入依赖,前提是你需要先将其安装到maven仓库中,可以在项目根目录下执行
mvn clean install
如果得到的就是jar包,可以执行命令进行安装到本地仓库
mvn install:install-file -DgroupId=com.github.diamond -DartifactId=super-diamond-client -Dversion=1.2.1-SNAPSHOT -Dpackaging=jar -Dfile="你的jar所在全路径"
然后加入依赖:
如果懒得安装,也可以放在WEB-INF的lib文件夹下,在依赖中加入引用,例如
<dependency>
<groupId> com.github.diamond </groupId >
<artifactId> super-diamond-client </artifactId >
<version> 1.2.1-SNAPSHOT </version >
<scope> system </scope >
<systemPath> ${basedir}/src/main/webapp/WEB-INF/lib/super-diamond-client-1.2.1-SNAPSHOT.jar
</systemPath >
</dependency>
这是客户端,服务端你可以打包后安装在某服务器上提供服务,下面再具体说下怎么应用。
- 服务端安装
- super-diamond-server 安装
- 进入super-diamond目录,构建super-diamond父工程: mvn install,同时客户端也安装到了本地仓库。
- super-diamond-server中嵌入jetty运行,构建部署包:mvn install assembly:single -Pproduction,生成super-diamond-server-${version}-bin.tar.gz文件,放上服务器进行解压,运行bin/server.sh start命令。
- 在conf\META-INF\scripts目录中,提供mysql和oracle建表脚本,理论也支持其它数据库,在conf\META-INF\res\config-production.properties文件中修改数据库配置。
- 在conf_user表中添加用户admin,密码000000的加密值为:670b14728ad9902aecba32e22fa4f6bd, mysql脚本:
insert into conf_user(id,USER_code,USER_NAME,PASSWORD,CREATE_TIME) values(1,‘admin’,‘admin’,‘670b14728ad9902aecba32e22fa4f6bd’,current_timestamp() );
commit; - 访问super-diamond-server,jetty默认端口为8090,可以在:conf/META-INF/res/jetty.properties中修改。
http://localhost:8090/superdiamond
启动的时候如果提示端口占用,可以修改默认端口,比如我将jetty默认端口(8090)修改为8000(上述第五条有告诉在哪修改),将netty的默认端口(8283)修改为8284,在配置文件config-production.properties中修改。
当然我是部署后发现端口被占用才改的,你们如果没有这个问题可以忽略上述。
打包后,得到
再部署服务器上进行解压运行
tar -xvf super-diamond-server-1.1.0-SNAPSHOT-bin.tar.gz
访问地址:http://localhost:8000/superdiamond(注意端口,此处是我修改后的)
- super-diamond-client 客户端定义服务端参数的几种方式
客户端测试涉及到连接到diamond服务端参数怎么初始化的问题,现在提供了以下几种方式:
- 固定在diamond客户端配置文件中,但这种方式显然不好,因为diamond客户端是以jar的形式被其他项目所依赖,修改配置比较麻烦,每次都累重新打包,还得需要源码
- 通过环境变量和jvm参数两种方式设置,避免固定在工程配置中
export SUPERDIAMOND_PROJCODE=javademo
export SUPERDIAMOND_PROFILE=production
export SUPERDIAMOND_MODULES=jdbc,common #多个模块之用逗号分隔,可以设置为空,获取所有模块配置。
export SPUERDIAMOND_HOST=192.168.0.1
export SPUERDIAMOND_PORT=8283
或者
-Dsuperdiamond.projcode=my-test1 -Dsuperdiamond.profile=production -Dsuperdiamond.modules=模块1 -Dspuerdiamond.host=127.0.0.1 -Dspuerdiamond.port=8284
本人本地测试选择第二种方式,如:
,如果后面项目部署在服务器上,可以放在tomcat启动脚本里,如:
JAVA_OPTS="$JAVA_OPTS -Dsuperdiamond.projcode=desktop -Dsuperdiamond.host=172.31.7.176 -Dsuperdiamond.port=8283 -Dsuperdiamond.profile=test"
3.spring配置文件加载,道理和第1种一样,不推荐,测试阶段可以有。
<bean id="propertiesConfiguration" class="com.github.diamond.client.PropertiesConfigurationFactoryBean">
<constructor-arg index="0" value="192.168.58.127" />
<constructor-arg index="1" value="8284" />
<constructor-arg index="2" value="my-test1" />
<constructor-arg index="3" value="production" />
<constructor-arg index="4" value="模块1" />
</bean>
连接服务参数搞清楚后,我们就可以测试了,在super-diamond-client里test目录下有详细测试方法,我就简单验证下远程参数获取,和参数改变触发的自定义监听事件
-
服务测试
-
远程参数获取
这是服务端配置的
下面是客户端获取参数测试
上面的是主动调用属性配置器的get方法进行获取,下面也可以通过将自定义的属性配置器(需要实现FactoryBean)放入PropertySourcesPlaceholderConfigurer的property 属性中(该属性是个数组,支持多条配置文件加载),通过${key}方式获取,如:
上图配置文件bean为testBean的url属性在加载初始化入spring容器中时,通过${config-jdbc.url}获取了远程配置的值,运行结果如下:
注:PropertyPlaceholderConfigurer是个bean工厂后置处理器的实现,也就是 BeanFactoryPostProcessor接口的一个实现。
PropertyPlaceholderConfigurer可以将上下文(配置文 件)中的属性值放在另一个单独的标准java Properties文件中去。
在XML文件中用${key}替换指定的properties文件中的值。这样的话,只需要对properties文件进 行修改,而不用对xml配置文件进行修改
- 触发监听事件
首先我们启动客户端
什么都没有发生,当前config-jdbc.url我们配置的值是127.0.0.1,现在去服务端操作界面,将其改为127.0.0.2
再来看下客户端发生了什么:
客户端会得知参数被修改了并自动触发事件,至于事件做什么可以根据需求自定义。下面我简单解读了下代码,不关注原理的话这篇文章看到这就可以了。
通过对netty的研究,我们可以知道服务修改后为什么客户端会有触发,其实主要归功于netty的SimpleChannelInboundHandler这个请求的处理类,在netty服务端启动的时候会指定一个处理器
,这个处理器我们可以自定义,通过重写netty的channelRead0方法,我们可以自定义一些逻辑处理,该方法支持获取每次请求的通道上下文和请求参数,通过定义变量clients和channels
public static ConcurrentHashMap<ClientKey /*projcode+profile*/, List<ClientInfo> /*client address*/> clients =
new ConcurrentHashMap<ClientKey, List<ClientInfo>>();
private ConcurrentHashMap<String /*client address*/, ChannelHandlerContext> channels =
new ConcurrentHashMap<String, ChannelHandlerContext>();
来存储每次请求的客户端信息,如ip,请求参数(即projCode、modules等)等,这样,在修改配置时可以匹配到相应的客户端进行通知。
并且,ChannelInboundHandlerAdapter类的另一个方法channelInactive,可以实现在客户端与服务端将要断开连接时,删除相应的的客户端信息,避免无谓的通知。
同时,客户端在启动的时候也会加载一个处理器
这个ClientChannelInitializer在通道初始化时选择的处理事件用的的是自定义的Netty4ClientHandler,看一下该类的构造
最后再配和项目启动时初始化PropertiesConfiguration这个bean时,构造器初始化时会启动对服务端的连接,
这个方法在启动时会初始化一个单线程化的线程池,是一个死循环不断的读取上面说的阻塞队列,获取后进行一些操作,如触发自定义的监听事件,从而实现了服务端改个参数,有关联的客户端都会收到更新消息,及执行自定义的一些事件。
ok,关于 super-diamond就了解到这,这个服务是基于淘宝的diamond进行改造来的,有一些特性,我也没介绍了,比如说服务配置信息的本地化,如果数据库连不上服务端可以正常读取参数,或者服务端连不上,客户端也会对原先在本地存储的配置信息文件进行读取
其他还有什么问题,大家可以下载源码进行解读。
See you in the next article !
更多推荐
所有评论(0)