最近频繁的系统上线,每次打包都要把配置文件替换为正式环境的配置文件,虽然说就是复制粘贴的事,架不住文件杂乱,而且多。

  期初的想法是有没有办法将配置文件与系统隔离开来,这样在更新时候,就只需要更新代码部分,配置文件不用去管了。查了不少资料,没找到什么好的实现方式,别人比较好的发布框架都是自己写的,也用了,干脆自己研究研究能不能使用zk做一个配置文件的管理中心,顺带实现动态加载配置文件而不需要重启系统(正式环境这种情况使用的应该很少,不过本地倒是用起来顺手很多)。

  

  1,在虚拟机上安装zk(需先安装jdk):下载tar文件,解压,修改 cp zoo_sample.cfg zoo.cfg,

  • tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
  • dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
  • clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。

  进入到bin目录下,sh zkServer.sh start

  进入zk客户端   sh zkCli.sh -server localhost:2181

  创建文件  create /fileName value

  2.java端引入zk客户端

  1).maven

   <!-- ZooKeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.9.0</version>
</dependency>
<!-- Zookeeper -->

  2).zookeeper.properties  

    zk.servers=192.168.3.252:2181
    zk.config.root.path=/conf

  3.我们在使用配置文件的时候,都是使用spring来托管,在项目启动的时候就加载到项目中去,zk有三种监听方式,为能够同时监听主目录及子目录的实时变化,选用TreeCacheListener。zk能够直接从服务端获取对应目录下的数据,并能够实时监听对应节点的变化以及变化之后的值,这里首先在项目启动加载配置文件的时候,用服务端的数据去覆盖项目中的数据,这样保证服务端有配置时以服务端为准,没有时则以项目中配置运行,然后实时监听对应节点,只要有服务端配置被修改,则覆盖项目中的原有配置,并刷新容器,使用最新的配置。

  核心代码:继承spring PropertyPlaceholderConfigurer 重写processProperties方法加载配置文件

  

@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException { InputStream in = ZooKeeperService.class.getClassLoader().getResourceAsStream("zookeeper.properties");
Properties pro = new Properties();
try{
pro.load(in);
}catch(Exception e){
logger.debug("zookeeper.properties读取错误!"+e.getMessage());
} this.zookeeperServers = pro.getProperty("zk.servers");
PATH = pro.getProperty("zk.config.root.path"); RetryPolicy retryPolicy = new ExponentialBackoffRetry(BASE_SLEEP_TIMEMS, MAX_RETRIES);
this.client = CuratorFrameworkFactory.builder().connectString(this.zookeeperServers).retryPolicy(retryPolicy).build();
client.start(); @SuppressWarnings("resource")
TreeCache cache = new TreeCache(this.client, PATH);
try {
cache.start(); TreeCacheListener listener = new TreeCacheListener() { @Override
public void childEvent(CuratorFramework client, TreeCacheEvent event)
throws Exception {
if(null != event && null != event.getData()){
logger.debug(event.getData().getPath().toString()+":"
+new String(event.getData().getData())); String[] arr = event.getData().getPath().toString().split("/");
String key = arr[arr.length-1];
String value = new String(event.getData().getData());
proMap.putAll(updateConf(key,value)); }
}
}; cache.getListenable().addListener(listener); } catch (Exception e) {
logger.debug(e.getMessage());
} try {
        //加载顺序问题,因为是一个监听的过程,所以没办法顺序执行,测试时这里直接使用了延时来保证先获取到服务端的数据然后在加载参数,没有想到其他好的方法解决,在尝试使用CountDownLatch来解决,后续修改
            Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
props.putAll(proMap);
super.processProperties(beanFactory, props);
}

  基本实现如此。待完善。

maven 插件方式拆分开发,测试,正式环境配置文件

  resources 文件夹下 创建 dev(开发) qa(测试) pre(预生产) prod(生产) 几个文件夹 并且把对应的配置丢到(公用的不用丢)对应的文件夹

修改pom.xml
在dependencies 下面增加
<!--定义不同的环境变量-->
  <profiles>
    <profile>
      <!--开发-->
      <id>dev</id>
      <properties>
        <env>dev</env>
      </properties>
    </profile>
    <profile>
      <!--测试-->
      <id>qa</id>
      <properties>
        <env>qa</env>
      </properties>
  <!--默认是测试,额外加参数可修改此项,例如: mvn clean package -Pdev 表示打包时使用开发环境-->
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
    </profile>
    <profile>
  <!--预生产-->
      <id>pre</id>
      <properties>
        <env>pre</env>
      </properties>
    </profile>
    <profile>
      <!--生产-->
      <id>prod</id>
      <properties>
        <env>prod</env>
      </properties>
    </profile>
  </profiles>

build 节点下增加
  <!-- 控制 复制到target\classes文件夹的资源 的情况 -->
  <resources>
  <!-- 资源根目录排除各环境的配置,使用单独的资源目录来指定,这一步复制公共的配置 -->
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
      <excludes>
        <exclude>dev/*</exclude>
        <exclude>qa/*</exclude>
        <exclude>pre/*</exclude>
        <exclude>prod/*</exclude>
      </excludes>
    </resource>
  <!-- 这一步复制指定环境的配置 -->
    <resource>
    <directory>src/main/resources/${env}</directory>
    </resource>
  </resources>

搞定

maven插件会自动将对应的配置文件build进去,避免每次修改配置文件

  

zookeeper配置文件共享中心的更多相关文章

  1. zookeeper配置中心实战--solrcloud zookeeper配置中心原理及源码分析

    程序的发展,需要引入集中配置: 随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关.参数的配置.服务器的地址…… 并且对配置的期望也越来越高,配置修改后实时生效,灰度发布,分环境.分集群管理配 ...

  2. Dubbo原理解析-注册中心之Zookeeper协议注册中心

    下面我们来看下开源dubbo推荐的业界成熟的zookeeper做为注册中心, zookeeper是hadoop的一个子项目是分布式系统的可靠协调者,他提供了配置维护,名字服务,分布式同步等服务.对于z ...

  3. springboot整合dubbo\zookeeper做注册中心

    springboot整合dubbo发布服务,zookeeper做注册中心.前期的安装zookeeper以及启动zookeeper集群就不说了. dubbo-admin-2.5.4.war:dubbo服 ...

  4. 以zookeeper为注册中心搭建spring cloud环境

    在spring cloud体系中,有多种手段实现注册中心,本例中采用zookeeper作为注册中心的角色.服务提供者向zookeeper注册,服务消费者从zookeeper中发现服务提供者的相关信息, ...

  5. Dubbo框架应用之(三)--Zookeeper注冊中心、管理控制台的安装及解说

    我是在linux下使用dubbo-2.3.3以上版本号的zookeeper注冊中心客户端. Zookeeper是Apache Hadoop的子项目,强度相对较好,建议生产环境使用该注冊中心. Dubb ...

  6. Zookeeper用作注册中心的原理

    RPC框架中有3个重要的角色: 注册中心 :保存所有服务的名字,服务提供者的ip列表,服务消费者的IP列表: 服务提供者: 提供跨进程服务: 服务消费者: 寻找到指定命名的服务并消费. 一:Zooke ...

  7. Dubbo配置注册中心设置application的name使用驼峰命名法存在的隐藏项目启动异常问题

    原创/朱季谦 首先,先提一个建议,在SpringBoot+Dubbo项目中,Dubbo配置注册中心设置的application命名name的值,最好使用xxx-xxx-xxx这样格式的,避免随便使用驼 ...

  8. Java开发机器上的配置及zookeeper配置

    Java开发机器上的配置及zookeeper配置 /etc/profile 文件的后面加入下面的内容: # jdk, zookeeper, kafka, ant, maven export APACH ...

  9. 新装kafka与zookeeper配置

    zookeeper配置 dataDir=/opt/kafka_2.11-2.0.0/data/zookeeper # 尽量不要放在tmp# the port at which the clients ...

随机推荐

  1. spring boot 错误处理总结

    在boot 中, 对404  和 异常 有了额外的处理. 当然,我们可以定制, 如何做呢? 1 写一个继承 ErrorController 的Controller 注意, 这里一定要继承 ErrorC ...

  2. phpexcel导入导出

    先下载类文件,将类文件放到lib下,然后到入口文件定义一个新的的路径,以便引入文件.    <?php namespace app\index\controller; use think\Con ...

  3. Python3 timeit的用法

    Python3中的timeit模块可以用来测试小段代码的运行时间 其中主要通过两个函数来实现:timeit和repeat,代码如下: def timeit(stmt="pass", ...

  4. myeclise 安装

    安装.破解步骤都在gaobo百度云/工具/开发工具 安装后配置环境变量:

  5. eclipse git(版本回退)

    https://www.cnblogs.com/duex/p/6389999.html

  6. java-web的请求和响应机制中的request请求

     1 Request对象和Response对象的原理 1.1  都是由服务器创建的  我们使用它 1.2 Request对象  是获取请求消息 response对象是响应 2 request 对象的继 ...

  7. 页面JS实现按钮点击增加输入框

    学习记录 https://www.tuicool.com/articles/byUf2qe

  8. FortiGate数据流分析 debug flow

    1.工具说明 在防火墙部署中,经常会遇到防火墙接收到了数据包,但并未进行转发.可以通过diagnose debug flow 命令来对数据包的处理过程进行跟踪,可以清晰查看数据包再各个功能模块内的处理 ...

  9. swift 警告框 - 自定义按钮颜色,图片

    1.封装 弹框http://www.hangge.com/blog/cache/detail_651.html import UIKit extension UIAlertController { / ...

  10. hibernate save数据的时候报错:ids for this class must be manually assigned before calling save()

    这个错误是因为eclipse  这种jpatools 自动生成的实体类内没把id 设置为自增,还有id的值在生成的时候默认为string 即使加上了也所以无法自增 ,所以还需要把string 换成In ...