ZooKeeper学习笔记—配置管理

为什么80%的码农都做不了架构师?>>>   hot3.png

    最近在工作中,为了完善公司集群服务的架构,提高可用性,降低运维成本,因此开始学习ZooKeeper。
    至于什么是ZooKeeper?它能做什么?如何安装ZooKeeper?我就不一一介绍了,类似这些资料网上到处都是。我主要是把在开发过程中,以及个人对ZooKeeper的一些了解记录下来,大家如果遇到类似场景时,希望我的文章能够给你提供一些思路。

    我使用的ZooKeeper(以下简称:ZK)客户端是Curator Framework,是Apache的项目,它主要的功能是为ZK的客户端使用提供了高可用的封装。在Curator Framework基础上封装的curator-recipes,实现了很多经典场景。比如:集群管理(Leader选举)、共享锁、队列、Counter等等。可以总结Curator主要解决以下三类问题:
  • 封装ZK Client与Server之间的连接处理; 
  • 提供了一套Fluent风格的操作API; 
  • 提供ZK各种应用场景的抽象封装;

   本文主要完成的目标是:Spring PropertyPlaceholderConfigurer配置文件加载器集成ZooKeeper来实现远程配置读取。

    配置管理(Configuration Management)。
    在集群服务中,可能都会遇到一个问题:那就是当需要修改配置的时候,必须要对每个实例都进行修改,这是一个很繁琐的事情,并且易出错。当然可以使用脚本来解决,但这不是最好的解决办法。

OK,Let's go!

我们先看看项目结构



ZooKeeperPropertyPlaceholderConfigurer.java

继承org.springframework.beans.factory.config.PropertyPlaceholderConfigurer,重写processProperties(beanFactoryToProcess, props)来完成远端配置加载的实现

package org.bigmouth.common.zookeeper.config.spring;import java.io.UnsupportedEncodingException;
import java.util.Properties;import org.apache.commons.lang.StringUtils;
import org.bigmouth.common.zookeeper.config.Config;
import org.bigmouth.common.zookeeper.config.ZooKeeperConfig;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;public class ZooKeeperPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {public static final String PATH = "zoo.paths";@Overrideprotected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)throws BeansException {super.processProperties(beanFactoryToProcess, props);try {fillCustomProperties(props);System.out.println(props);}catch (Exception e) {// Ignoree.printStackTrace();}}private void fillCustomProperties(Properties props) throws Exception {byte[] data = getData(props);fillProperties(props, data);}private void fillProperties(Properties props, byte[] data) throws UnsupportedEncodingException {String cfg = new String(data, "UTF-8");if (StringUtils.isNotBlank(cfg)) {// 完整的应该还需要处理:多条配置、value中包含=、忽略#号开头String[] cfgItem = StringUtils.split(cfg, "=");props.put(cfgItem[0], cfgItem[1]);}}private byte[] getData(Properties props) throws Exception {String path = props.getProperty(PATH);Config config = new ZooKeeperConfig();return config.getConfig(path);}}



Config.java

配置操作接口 
package org.bigmouth.common.zookeeper.config;public interface Config {byte[] getConfig(String path) throws Exception;
}



Startup.java

程序启动入口


package org.bigmouth.common.zookeeper.config;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Startup {public static void main(String[] args) {new ClassPathXmlApplicationContext("classpath:/config/applicationContext.xml");}}




ZooKeeperConfig.java

配置操作接口ZooKeeper的实现


package org.bigmouth.common.zookeeper.config;import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.data.Stat;public class ZooKeeperConfig implements Config {@Overridepublic byte[] getConfig(String path) throws Exception {CuratorFramework client = ZooKeeperFactory.get();if (!exists(client, path)) {throw new RuntimeException("Path " + path + " does not exists.");}return client.getData().forPath(path);}private boolean exists(CuratorFramework client, String path) throws Exception {Stat stat = client.checkExists().forPath(path);return !(stat == null);}}




ZooKeeperFactory.java

管理ZooKeeper客户端连接


package org.bigmouth.common.zookeeper.config;import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;public class ZooKeeperFactory {public static final String CONNECT_STRING = "172.16.3.42:2181,172.16.3.65:2181,172.16.3.24:2181";public static final int MAX_RETRIES = 3;public static final int BASE_SLEEP_TIMEMS = 3000;public static final String NAME_SPACE = "cfg";public static CuratorFramework get() {RetryPolicy retryPolicy = new ExponentialBackoffRetry(BASE_SLEEP_TIMEMS, MAX_RETRIES);CuratorFramework client = CuratorFrameworkFactory.builder().connectString(CONNECT_STRING).retryPolicy(retryPolicy).namespace(NAME_SPACE).build();client.start();return client;}
}


applicationContext.xml

配置加载器使用我们自己创建的ZooKeeperPropertyPlaceholderConfigurer,因为它重写了processProperties方法。这个方法里会去读取远程配置。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans><bean class="org.bigmouth.common.zookeeper.config.spring.ZooKeeperPropertyPlaceholderConfigurer"><property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /><property name="ignoreResourceNotFound" value="true" /><property name="locations"><list><value>classpath:application.properties</value></list></property></bean></beans>


application.properties

项目配置文件,里面除了配置ZooKeeper服务器地址和读取的节点以外,其他所有的配置都应该保存在ZooKeeper中。

zoo.paths=/properties

设置ZooKeeper数据

登录ZooKeeper中为节点 /cfg/properties 添加一条配置项:


如图所示:我创建了一个节点 /cfg/properties 并设置内容为:jdbc.driver=org.postgresql.Driver

运行Startup.java

OK 了,zoo.paths是本地application.properties文件中的,jdbc.driver是远程ZooKeeper服务器中的。


项目中需要依赖的jar包


<dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.4</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>3.0.3.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>3.0.3.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>3.0.3.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>3.0.3.RELEASE</version>
</dependency><!-- ZooKeeper -->
<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.6</version>
</dependency>
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>2.4.2</version>
</dependency>
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>2.4.2</version>
</dependency>

相关资料:

Apache Curator Framework

Apache ZooKeeper



博主,问个zk值被刷了的问题。

假设,我们现在配置的数据,都是从zk中获取的,但是某个值被刷新了,我们有个watch监控到了,但是这个值怎么刷入到内存中,或者说重新注册那个bean?

有没有这方面的解决思路,我有点迷惑

ZKClient 可以轻松监听到配置什么时候变化,但变化后该怎么做?
如果你用了spring,或许这篇文章能帮到你:https://github.com/jamesmorgan/ReloadablePropertiesAnnotation

转载于:https://my.oschina.net/boltwu/blog/464149

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544691.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# Winform 窗体美化(六、双层窗体)

六、双层窗体 大概情况 双层床体是为了平滑的创建异形窗体的一个解决方案&#xff0c;找了很多资料&#xff0c;整理了一下。 双层窗体的逻辑是建立在 UpdateLayeredWindow 不能绘制控件的基础上&#xff0c;上层再添加一个专门放置控件的层&#xff1b;这样就可以在上层“控…

批处理框架 Spring Batch 这么强,你会用吗?

来源&#xff1a;blog.csdn.net/topdeveloperr/article/details/84337956spring batch简介Spring Batch架构介绍Spring Batch核心概念介绍chunk 处理流程批处理操作指南spring batch简介 spring batch是spring提供的一个数据处理框架。企业域中的许多应用程序需要批量处理才能在…

Android Bundle类别

即使在今天发现自己Bundle类不明确&#xff0c;因此&#xff0c;花时间去研究了一下。 依据google官方文件&#xff08;http://developer.android.com/reference/android/os/Bundle.html&#xff09; Bundle类是一个key-value对&#xff0c;“A mapping from String values to …

C# Winform 窗体美化(七、Win7 Aero 毛玻璃效果)

七、Win7 Aero 毛玻璃效果 在 Win7 上有一种 Aero 效果&#xff0c;毛玻璃透明效果&#xff0c;搭配不同风格的颜色&#xff0c;效果很好。在学习 Winform 美化的时候顺便看到的这种效果&#xff0c;也整理进来了。 注意&#xff1a;Win7 上想看到这种效果需要开启并使用 Aer…

非导向传输媒体| 计算机网络

Transmission media can be categorized in two ways, 传输媒体可以通过两种方式进行分类&#xff1a; Guided Transmission Media 引导传输媒体 Unguided Transmission Media 非引导传输媒体 1)非引导传输媒体 (1) Unguided Transmission Media) It is also called wireless …

面霸篇:MQ 的 5 大关键问题详解

最近mq越来越火&#xff0c;很多公司在用&#xff0c;很多人在用&#xff0c;其重要性不言而喻。但是如果我让你回答下面的这些问题&#xff1a;我们为什么要用mq&#xff1f;引入mq会多哪些问题&#xff1f;如何解决这些问题&#xff1f;你心中是否有答案了呢&#xff1f;本文…

C# Winform 窗体美化(八、Icon)

八、Icon 之前 Winform 项目也有在 Icon 上遇到些问题&#xff08;这里的 Icon 指的是 .ico 类型的文件&#xff09;&#xff0c;比如刚开始不知道怎么让自己的程序 Icon 和其他软件一样可以放大&#xff0c;还有放大之后在音量合成器中会出现比较奇葩的效果之类的问题&#x…

MyBatis 的执行流程,学废了!

作者&#xff1a;双子孤狼来源&#xff1a;blog.csdn.net/zwx900102/article/details/108455514MyBatis可能很多人都一直在用&#xff0c;但是MyBatis的SQL执行流程可能并不是所有人都清楚了&#xff0c;那么既然进来了&#xff0c;通读本文你将收获如下&#xff1a;1、Mapper接…

C# Winform 窗体美化(九、嵌入窗体)

九、嵌入窗体 还是关于 Winform 窗体的一些操作问题&#xff0c;这次是研究了一个嵌入窗体&#xff0c;这次学习纯属偶然&#xff0c;项目中确实没遇到过这种需求。就是把别人的程序嵌入到自己的程序中&#xff0c;就像这样&#xff1a; 这里我嵌入了测试显示器的程序 [外链图…

SpringBoot 优雅的参数效验!

引言 不知道大家平时的业务开发过程中 controller 层的参数校验都是怎么写的&#xff1f;是否也存在下面这样的直接判断&#xff1f;public String add(UserVO userVO) {if(userVO.getAge() null){return "年龄不能为空";}if(userVO.getAge() > 120){return &quo…

NTFS Change Journal(USN Journal)详解

写在前面 最近又用了一下usn日志来获取所有文件列表&#xff0c;在分多次加载文件列表的时候发现有文件丢失的情况&#xff0c;后来发现一篇文章比较详细的讲了usn。 用cmd来读取usn日志 如图&#xff1a; 以下是转载内容&#xff1a; 还是那个文件监控的应用&#xff0c;…

绝,Java 中创建对象的 5 种方法!

我们日常生活中会创建很多对象&#xff0c;但是这个对象和你理解的那么对象不一样&#xff0c;因为作者不是女娲&#xff0c;不能造人。作者只是程序员&#xff0c;他只能在 Java 中创建对象。那么我问你一个问题&#xff0c;你知道 Java 中如何创建对象吗&#xff1f;这个问题…

C# Winform 窗体美化(十、自定义窗体)

十、自定义窗体 写在前面 最近在做 winform 应用程序&#xff0c;需要自定义一种窗口的样式&#xff0c;所以就随便搞了一个简单的窗口。 效果图 有两种样式&#xff0c;界面如下&#xff1a; 无标题&#xff1a; 有标题&#xff1a; 关键词 1、黑色描边边框 对于…

SpringBoot时间格式化的5种方法!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;在我们日常工作中&#xff0c;时间格式化是一件经常遇到的事儿&#xff0c;所以本文我们就来盘点一下 Spring Boot 中时间格…

C#文件加密和解密

下载 CSDN下载&#xff1a;https://download.csdn.net/download/myinc/9913318 Github&#xff1a;GitHub 如果没有积分&#xff0c;也可以关注我获取哟~【文件加密】 // * 最近看了一下加密算法&#xff0c;对加密文件突然很感兴趣&#xff0c;就研究了一下&#xff1a;…

SpringBoot 如何统一后端返回格式?老鸟们都是这样玩的!

大家好&#xff0c;我是磊哥。今天我们来聊一聊在基于SpringBoot前后端分离开发模式下&#xff0c;如何友好的返回统一的标准格式以及如何优雅的处理全局异常。首先我们来看看为什么要返回统一的标准格式&#xff1f;为什么要对SpringBoot返回统一的标准格式在默认情况下&#…

zabbix企业应用之监控docker容器资源情况

关于docker的监控&#xff0c;无论开源的CAdvisor、Data Dog还是我自己写的监控&#xff08;http://dl528888.blog.51cto.com/2382721/1635951&#xff09;&#xff0c;不是通过docker的stats api就是使用socket来进行。单独看一个主机的监控项还行&#xff0c;比如只查看容器t…

使用了synchronized,竟然还有线程安全问题!

线程安全问题一直是系统亘古不变的痛点。这不&#xff0c;最近在项目中发了一个错误使用线程同步的案例。表面上看已经使用了同步机制&#xff0c;一切岁月静好&#xff0c;但实际上线程同步却毫无作用。关于线程安全的问题&#xff0c;基本上就是在挖坑与填坑之间博弈&#xf…

序列图| 软件工程

什么是时序图&#xff1f; (What is Sequence Diagram?) Sequence Diagram is a "Connection Diagram" that represents a single structure or storyline executing in a system. It is the second most used UML diagram behind the class diagram. Sequence Diag…

终极解密输入网址按回车到底发生了什么?

详解输入网址点击回车&#xff0c;后台到底发生了什么。透析 HTTP 协议与 TCP 连接之间的千丝万缕的关系。掌握为何是三次握手四次挥手&#xff1f;time_wait 存在的意义是什么&#xff1f;全面图解重点问题&#xff0c;再也不用担心面试问这个问题。大致流程URL 解析&#xff…