一、目标

一个乞丐版自更新配置中心,更新配置后,能在各个服务器实现更新

二、架构

三、角色

  • config-web: 配置后台,主要用于管理配置,增改配置
  • config-agent: 监听配置,遇到变动后,自动拉取最新文件到本地
  • config-sdk: 业务集成该sdk,用于读取配置

3.1 config-web 配置后台

  1. 持久存储为MySQL,也可以加一层缓存Redis,设置一个唯一的业务KEY,对应的ZK里的ZNode

    • 对于配置节点的操作,最终必须落盘,持久化存储于MySQL
  2. 持久存储成功后,将配置的内容写入ZK集群中

以下是create节点的代码,set的同,这是简单的操作

package main

import (
"fmt"
. "go-zk/connect" "github.com/samuel/go-zookeeper/zk"
) func main() {
conn := Connect()
defer conn.Close() flags := int32(zk.FlagSequence)
acl := zk.WorldACL(zk.PermAll) // create node
path := PathConfig.ZNodePath +"/"+ "huodong-"
data := []byte(`{"num":6.13,"strs":["a","b"]}`)
createPath, err := conn.Create(path, data, flags, acl)
if err != nil {
panic(err)
}
} 复制代码

3.2 config-agent 监控

  1. 由于ZK的特性,能保持集群的一致性,以及提供了监听机制,在节点内容被改变时能提供回调
  2. 在config-agent监听对应的业务节点
  3. 监听的变动时,会有通知,例如,更改节点内容时,获取节点的内容,然后进行落盘,或者存到内存中都
package main

import (
"fmt"
"github.com/samuel/go-zookeeper/zk"
. "go-zk/connect"
"os"
"sync"
)
type Watch struct { } func (this *Watch)ZkChildrenWatch(c *zk.Conn, path string) {
for {
v, _, get_ch, err := c.ChildrenW(path)
if err != nil {
fmt.Println(err)
} fmt.Printf("value of path[%s]=[%s].\n", path, v) for {
select {
case ch_event := <-get_ch:
{
fmt.Printf("%+v\n", ch_event) if ch_event.Type == zk.EventNodeCreated {
fmt.Printf("has new node[%d] create\n", ch_event.Path)
} else if ch_event.Type == zk.EventNodeDeleted {
fmt.Printf("has node[%s] detete\n", ch_event.Path)
} else if ch_event.Type == zk.EventNodeDataChanged {
this.Callback(c, ch_event.Path)
} else if ch_event.Type == zk.EventNodeChildrenChanged {
fmt.Printf("children node change%+v\n", ch_event.Path)
}
}
}
break
}
}
} func (this *Watch)ZkNodeWatch(c *zk.Conn, path string) {
for {
v, _, get_ch, err := c.GetW(path)
if err != nil {
fmt.Println(err)
} fmt.Printf("value of path[%s]=[%s].\n", path, v) for {
select {
case ch_event := <-get_ch:
{
if ch_event.Type == zk.EventNodeCreated {
fmt.Printf("has new node[%d] create\n", ch_event.Path)
} else if ch_event.Type == zk.EventNodeDeleted {
fmt.Printf("has node[%s] detete\n", ch_event.Path)
} else if ch_event.Type == zk.EventNodeDataChanged {
this.Callback(c, ch_event.Path)
}
}
}
break
}
}
} func (this *Watch)Callback(c *zk.Conn, path string) {
data, _, err := c.Get(path)
if err != nil {
fmt.Println(err)
} // create file
fileName := PathConfig.LocalPath + path + ".json"
os.Create(fileName)
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC, 0600)
defer f.Close()
if err != nil {
fmt.Println(err.Error())
} else {
_,err=f.Write([]byte(data))
fmt.Println(err)
return
} fmt.Print("Write File OK !!!")
} func main() {
conn := Connect() // 监听所有子节点变化
children, _, err := conn.Children(PathConfig.ZNodePath)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", children) w := Watch{} var wg sync.WaitGroup
wg.Add(1)
go func(path string) {
w.ZkChildrenWatch(conn, path)
}(PathConfig.ZNodePath)
wg.Wait() // 监听节点内容变化
//var wg sync.WaitGroup
//wg.Add(len(children))
//
//for _, path := range children{
// path = PathConfig.ZNodePath + "/" + path
// go func(path string) {
// defer wg.Done()
// log.Print("Zookeeper Watcher Starting, ", path)
// w.ZkNodeWatch(conn, path)
// }(path)
//}
//wg.Wait() }
复制代码

3.3 config-sdk 客户端加载配置

读取配置的方式很多样,两种思路:

  1. 直接读取文件,由业务方直接读取,.json 、 .ini 、 .toml等
  2. sdk可以与config-agent结合,如果读取文件加载配置失败,利用agent,重新主动拉一次文件到本地,实现文件的懒加载

四、效果展示

# This is Zookeeper config file.

title = "Zookeeper config file"

[zookeeper]
servers = ["10.00.85.70:2181", "10.00.80.191:2181", "10.00.97.239:2181"]
port = 2181
session_timeout = 500
enabled = true [path]
znode_path = "/huodong/conf"
local_path = "/tmp/zookeeper"
复制代码
  1. 由于在本地测试,嫌麻烦就没有部署到服务器了,将locah_path分别改成"/tmp/zookeeper"、"/tmp/zookeeper1"、"/tmp/zookeeper2",起三个进程

  2. 连接到zk服务器,修改节点的内容 set /huodong/conf/huodong-0000000001 '{"num":6.13,"strs":["a","b"]}'

  3. 看下本地文件就会生成对应的配置文件

作者:知否专栏
链接:https://juejin.im/post/5cdcbf02f265da037129c3c7
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Zookeeper 应用实现-配置中心的更多相关文章

  1. 基于zookeeper实现分布式配置中心(二)

    上一篇(基于zookeeper实现分布式配置中心(一))讲述了zookeeper相关概念和工作原理.接下来根据zookeeper的特性,简单实现一个分布式配置中心. 配置中心的优势 1.各环境配置集中 ...

  2. 基于zookeeper实现分布式配置中心(一)

    最近在学习zookeeper,发现zk真的是一个优秀的中间件.在分布式环境下,可以高效解决数据管理问题.在学习的过程中,要深入zk的工作原理,并根据其特性做一些简单的分布式环境下数据管理工具.本文首先 ...

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

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

  4. ZooKeeper系列(2)--基于ZooKeeper实现简单的配置中心

    ZooKeeper节点的类型分为以下几类:  1. 持久节点:节点创建后就一直存在,直到有删除操作来主动删除该节点 2. 临时节点:临时节点的生命周期和创建该节点的客户端会话绑定,即如果客户端会话失效 ...

  5. 基于ZK构建统一配置中心的方案和实践

    背景: 近期使用Zk实现了一个简单的配置管理的小东西,在此开源出来,有兴趣的希望提出您的宝贵意见.如果恰巧您也使用或者接触过类似的东西, 也希望您可以分享下您觉得现在这个项目可以优化和改进的地方. 项 ...

  6. .Net配置中心-简介

    系统简介 最近做了一个.Net配置中心,本质就是将原本放在各个站点下AppSettings中的配置统一管理,可以实现一次更改,自动更新,这里提供了两个版本, 一个是心跳版,一个是zookeeper版. ...

  7. SrpingCloud 之SrpingCloud config分布式配置中心

    Config架构 当一个系统中的配置文件发生改变的时候,我们需要重新启动该服务,才能使得新的配置文件生效,spring cloud config可以实现微服务中的所有系统的配置文件的统一管理,而且还可 ...

  8. ASP.Net Core 中使用Zookeeper搭建分布式环境中的配置中心系列一:使用Zookeeper.Net组件演示基本的操作

    前言:马上要过年了,祝大家新年快乐!在过年回家前分享一篇关于Zookeeper的文章,我们都知道现在微服务盛行,大数据.分布式系统中经常会使用到Zookeeper,它是微服务.分布式系统中必不可少的分 ...

  9. springcloud集成zookeeper,并使用configserver作为服务的配置中心

    1.springcloud集成zookeeper: 做法: 出现问题: 版本不一致导致出现keepError: 解决:服务器的zookeeper要与客户端的zookeeper一致,才可以. 2.使用c ...

随机推荐

  1. 清华大学教学内核ucore学习系列(1) bootloader

    ucore是清华大学操作系统课程的实验内核,也是一个开源项目,是不可多得的非常好的操作系统学习资源 https://github.com/chyyuu/ucore_lab.git, 各位同学可以使用g ...

  2. 「2019.7.22 考试」AC和WA0一步之遥

    这卷子还是答的挺惨的. 第一题5min写完了,自认为AC(其实WA了80),第二题推了半天CRT的公式老出错结果发现是程序打错了.第三题打模拟150行结果数组没开够,开大就是0->60的转变.状 ...

  3. CSPS模拟 41

    说不会鸽就不会鸽的 虽然是炸裂的一场 T1没读懂题,T23交了两个无脑暴力 (公式懒得打了 latex过于感人) T1 点阵内不重合的直线有多少条? 枚举斜率,那么“后继”不在点阵内的点可以作出一个贡 ...

  4. 复制/etc/profile至/tmp/目录,用查找替换命令删除/tmp/profile文件中的 行首的空白字符及在vim中设置tab缩进为4个字符

    1.复制/etc/profile至/tmp/目录,用查找替换命令删除/tmp/profile文件中的 行首的空白字符 在命令模式下,使用正则表达式匹配 行首有空白字符行的模式:^[[:space:]] ...

  5. one of neural network

    map source:https://github.com/microsoft/ai-edu Fundamental Principle inputs: characteristic value th ...

  6. 一分钟带你学会利用mybatis-generator自动生成代码!

    目录 一.MyBatis Generator简介 二.使用方式 三.实战 之前的文章<SpringBoot系列-整合Mybatis(XML配置方式)>介绍了XML配置方式整合的过程,本文介 ...

  7. java VS c#,异同点

    因工作安排,后期需要维护一个java项目.所以稍微熟悉下java,开此篇记录下java与c#的区别点,方便增强自己学习效果.肯定是不全的,可能是有错的,欢迎批评指正. 一.关键字 描述 C# Java ...

  8. pat 1011 World Cup Betting(20 分)

    1011 World Cup Betting(20 分) With the 2010 FIFA World Cup running, football fans the world over were ...

  9. nyoj 48-小明的调查作业(set)

    48-小明的调查作业 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:15 submit:29 题目描述: 小明的老师布置了一份调查作业,小明想在学校 ...

  10. poj 3974 Palindrome (manacher)

    Palindrome Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 12616   Accepted: 4769 Desc ...