头图

背景

Leader:A系统的业务参数都写在配置文件中,虽然能提单让运维人员灵活调整,但是你知道的,我们公司这流程审批有多麻烦,而且改配置文件需要重启应用,重启时间也是有限制的,业务部门有点意见,要我们优化,你看能否做到实时更新业务参数?
Coder:那可以把参数加载到Zookeeper,并监听Zookeeper节点的值的变化,再给业务整个前端页面可以修改参数,一旦刷新Zookeeper节点的值,就触发Zookeeper去更新内存中的参数值,同步将配置文件中的值也改了,搞定。

知识储备

Watcher监听机制是Zookeeper中非常重要的特性,对于Zookeeper上创建的节点,可以绑定监听事件,监听节点数据变更、节点删除、子节点状态变更等事件,通过这个事件机制,可以实现实时更新配置。
我们导入依赖:

<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.11</version>
</dependency>

zkclient在原生API的基础上进行了封装,简化了Zookeeper的操作,我们可以使用subscribeDataChanges方法监听节点数据的变化,实现IZkDataListener接口,重写handleDataChange(String path, Object data)方法(节点数据改变时触发)和handleDataDeleted(String path)方法(节点删除时触发),注意该接口只会监听path节点的数据变化,其子节点的数据变化不会被监控到。

实操

1、订阅Zookeeper,监听节点的变化触发更新内存和配置文件中的参数值。

zkClient.subscribeDataChanges(path, new IZkDataListener() {
    @Override
    public void handleDataChange(String path1, Object data1) throws Exception {
        System.out.println("节点 " + path1 + " 数据更新: " + data1);
        servletContext.setAttribute(path1.substring(path1.lastIndexOf("/") + 1), data1);

        try {
            String configPath = servletContext.getRealPath("/config.properties");
            Properties prop = new Properties();
            prop.load(this.getClass().getResourceAsStream("/config.properties"));
            OutputStream fos = new FileOutputStream(this.getClass().getResource("/config.properties").getFile());
            prop.setProperty(path1.substring(path1.lastIndexOf("/") + 1), (String) data1);
            prop.store(fos, "Update value");
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void handleDataDeleted(String path1) throws Exception {
        System.out.println("节点数据已删除");
    }
});

2、写个简单页面,展现参数,支持修改。

3、页面修改certType的值为103,查看日志提示“/zookeeper/API001/certType”节点值变为103。

2024-01-11 17:04:11.686  INFO 21004 --- [nio-8080-exec-7] org.apache.zookeeper.ZooKeeper           : Initiating client connection, connectString=127.0.0.1:2181 sessionTimeout=30000 watcher=org.I0Itec.zkclient.ZkClient@64ccb8a8
2024-01-11 17:04:11.686  INFO 21004 --- [-127.0.0.1:2181] org.I0Itec.zkclient.ZkEventThread        : Starting ZkClient event thread.
2024-01-11 17:04:11.688  INFO 21004 --- [nio-8080-exec-7] org.I0Itec.zkclient.ZkClient             : Waiting for keeper state SyncConnected
2024-01-11 17:04:11.689  INFO 21004 --- [d(eureka1:2181)] org.apache.zookeeper.ClientCnxn          : Opening socket connection to server eureka1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
2024-01-11 17:04:11.689  INFO 21004 --- [d(eureka1:2181)] org.apache.zookeeper.ClientCnxn          : Socket connection established to eureka1/127.0.0.1:2181, initiating session
2024-01-11 17:04:11.691  INFO 21004 --- [d(eureka1:2181)] org.apache.zookeeper.ClientCnxn          : Session establishment complete on server eureka1/127.0.0.1:2181, sessionid = 0x1000fe25736002b, negotiated timeout = 30000
2024-01-11 17:04:11.692  INFO 21004 --- [c-7-EventThread] org.I0Itec.zkclient.ZkClient             : zookeeper state changed (SyncConnected)
节点 /zookeeper/API001/certType 数据更新: 103

查看Zookeeper中值确实变成了103,配置文件config.properties文件中也更新了值。


背风
1 声望0 粉丝

引用和评论

0 条评论