背景
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文件中也更新了值。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。