利用zookeeper的发布/订阅模式实现配置动态变更

??ZooKeeper的Watcher事件机制可以说分布式场景下的观察者模式的实现。基于这个watcher事件机制,配合注册到特定的ZNode节点,可以实现java应用的配置运行时的变更。在学习zookeeper之前,听同事说配置可以在运行时动态变更,觉得不可思议。研习了zookeeper之后,实现这个功能是很easy的。

??发布/订阅系统设计起来无非两种模式,推和拉。

1. 推模式,服务端负责把变更的数据推给订阅的客户端。Web即时通信里的Comet技术便可以实现这种功能。

2. 拉模式,也就是客户端定时轮询服务端。拉模式不仅有延迟,给服务端带来很大压力,而且十分低效。

??zookeeper采用的是推拉结合的模式

1. 客户端订阅znode节点

2. 被订阅的节点发生变化后,zookeeper服务端向客户端发生数据变更的watcher事件通知

3. 客户端接收到watcher通知后,主动从服务端拉取变更的数据

??阿里的配置变更中间件diamond,同样是基于推拉结合的模式来实现数据的动态变更。初学zookeeper,写了一个数据库配置动态变更的demo。zookeeper自带的Watcher注册后,数据变更一次便会自动取消注册。这个设计实在反人类,大多数的开发者的需求肯定是注册一次,服务终生。所以转向开源的ZkClient客户端

??首先本地需要启动一个zookeeper的服务端,并且有一个“/db”节点,我用这个节点存储数据库配置信息。

??客户端工程需要引入zookeeper和zkclient的依赖。

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.9</version>
</dependency>
<dependency>
    <groupId>com.github.adyliu</groupId>
    <artifactId>zkclient</artifactId>
    <version>2.1.1</version>
</dependency>

??客户端demo

import com.github.zkclient.IZkDataListener;
import com.github.zkclient.ZkClient;

import java.io.IOException;

/**
 * project  : zk
 * package  : PACKAGE_NAME
 * author   : lvsheng
 * date     : 2016/10/5 下午11:17
 */
public class ZkClientTest {

    public static void main(String[] args) {
        ZkClient zkClient = new ZkClient("127.0.0.1:2181");
        zkClient.subscribeDataChanges("/db", new IZkDataListener() {
            public void handleDataChange(String dataPath, byte[] data) throws Exception {
                System.out.println(new String(data));
            }

            public void handleDataDeleted(String dataPath) throws Exception {
                System.out.println(dataPath);
            }
        });

        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

??现在我们来测试这个功能,在控制台依次输入如下命令:

[zk: localhost:2181(CONNECTED) 48] set /db chat.jdbc.driver=com.mysql.jdbc.Driver|chat.jdbc.url=jdbc:mysql://192.168.146.120:3306/chat_test?useUnicode=true&amp;amp;characterEncoding=GBK|chat.jdbc.maxActive=5

[zk: localhost:2181(CONNECTED) 49] set /db chat.jdbc.driver=com.mysql.jdbc.Driver|chat.jdbc.url=jdbc:mysql://127.0.0.1:3306/chat_test?useUnicode=true&amp;amp;characterEncoding=GBK|chat.jdbc.maxActive=5

??观察Java代码的输出

chat.jdbc.driver=com.mysql.jdbc.Driver|chat.jdbc.url=jdbc:mysql://192.168.146.120:3306/chat_test?useUnicode=true&amp;amp;characterEncoding=GBK|chat.jdbc.maxActive=5
chat.jdbc.driver=com.mysql.jdbc.Driver|chat.jdbc.url=jdbc:mysql://127.0.0.1:3306/chat_test?useUnicode=true&amp;amp;characterEncoding=GBK|chat.jdbc.maxActive=5

??数据库配置的ip被成功的动态修改。

时间: 2024-07-30 10:07:53

利用zookeeper的发布/订阅模式实现配置动态变更的相关文章

异步编程解决方案之事件发布/订阅模式

时间监听模式是广泛用于异步编程的模式,是回调函数的事件化,又称不发订阅模式. nodejs的events模块就是发布订阅模式的一个简单实现,不存在preventDefault,stopPropagation,stopImmediatePropagation,等控制事件传递的方法. 它具有addListner/on(),once(),removeListner(),removeAllLisetner()和emit等基础监听事件方法. 事件发布/订阅十分简单,如下: //订阅 emitter.on(

RabbitMQ学习第三记:发布/订阅模式(Publish/Subscribe)

工作队列模式是直接在生产者与消费者里声明好一个队列,这种情况下消息只会对应同类型的消费者. 举个用户注册的列子:用户在注册完后一般都会发送消息通知用户注册成功(失败).如果在一个系统中,用户注册信息有邮箱.手机号,那么在注册完后会向邮箱和手机号都发送注册完成信息.利用MQ实现业务异步处理,如果是用工作队列的话,就会声明一个注册信息队列.注册完成之后生产者会向队列提交一条注册数据,消费者取出数据同时向邮箱以及手机号发送两条消息.但是实际上邮箱和手机号信息发送实际上是不同的业务逻辑,不应该放在一块处

ActiveMQ入门系列三:发布/订阅模式

在上一篇<ActiveMQ入门系列二:入门代码实例(点对点模式)>中提到了ActiveMQ中的两种模式:点对点模式(PTP)和发布/订阅模式(Pub & Sub),详细介绍了点对点模式并用代码实例进行说明,今天就介绍下发布/订阅模式. 一.理论基础 发布/订阅模式的工作示意图: 消息生产者将消息(发布)到topic中,可以同时有多个消息消费者(订阅)消费该消息. 和点对点方式不同,发布到topic的消息会被所有订阅者消费. 当生产者发布消息,不管是否有消费者,都不会保存消息. 一定要先

ActiveMQ简单简绍(“点对点通讯”和 “发布订阅模式”)

ActiveMQ简单简绍 MQ简介: MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们.消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术.排队指的是应用程序通过队列来通信.队列的使用除去了接收和发送应用程序同时执行的要求.其中较为成熟的MQ产品有IBMWEBSPHERE MQ. MQ特点: M

观察者模式和发布订阅模式

最近项目里,写了一个通知服务,具备处理短信.电邮.站内信的能力.但我做多了一点,就是可以通过配置选择它的能力,比如只具备处理短信或者具备点油.站内信的能力. 我画了一个简单的图 图中的 Dispatcher是一个Message的中转器,它负责投递给最终的 SMS.Email.Website处理器处理.但是 Dispatcher里,我使用了硬编码来内置 SMS.Email.Website处理器(尽管我加了些判断,来区别此能力是否开启),但它的耦合太高. 所以能够如何优化呢? 观察者模式 观察者模式

发布-订阅模式

1.什么是发布订阅模式 发布订阅模式 又叫观察者模式,他是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变,所有依赖他的对象都将得到通知. 在javascript开发中,我们一般用事件模型来替代传统的发布-订阅模式. 2.Dom事件 实际上,只要我们曾经在dom节点上绑定过事件函数,那么我们就曾经使用过发布-订阅模式. document.getElementById('test').addEventListener('click',function(){ alert(2)},fasle

C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命

使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠xxx" 一  双向耦合的代码 首先需要一个猫类Cat 一个老鼠类Rat 和一个测试类Program 老鼠类的代码如下 //老鼠类 public class Rat { public string Name { get; set; } //老鼠的名字 public Cat MyCat { get;

JavaScript设计模式与开发实践---读书笔记(8) 发布-订阅模式

发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 发布-订阅模式可以广泛应用于异步编程中,这是一种替代传递回调函数的方案. 可以取代对象之间硬编码的通知机制,一个对象不用再显式地调用另外一个对象的某个接口. 自定义事件 首先要指定好谁充当发布者: 然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者: 最后发布消息时,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数. 另外,我们还可以往回调函数里填入

观察者模式和发布/订阅模式的区别

在事件总线(EventBus)的架构设计中,用到了发布/订阅模式,但发现和观察者模式挺接近,有时容易发生混淆,现试图分清一下他们的关系. 观察者模式的角色为观察者(observer)和主题(subject)对象,observer需要观察subject时,需先到subject里面进行注册(subject对象持有observer对象的集合句柄),然后,当subject对象的内部状态发生变化时,把这个变化通知所有的观察者. 发布.订阅模式的角色为发布者(publisher)和订阅者(subscribe