介绍

Apache ZooKeeper 是 Apache 软件基金会的一个软件项目,他为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。ZooKeeper 曾经是 Hadoop 的一个子项目,但现在是一个独立的顶级项目。

ZooKeeper 的架构通过冗余服务实现高可用性。因此,如果第一次无应答,客户端就可以询问另一台 ZooKeeper 主机。ZooKeeper 节点将它们的数据存储于一个分层的命名空间,非常类似于一个文件系统或一个前缀树结构。客户端可以在节点读写,从而以这种方式拥有一个共享的配置服务。更新是全序的。

安装

Mac 系统,安装 zookeeper 只需要在终端运行如下命令:

brew install zookeeper

启动 zookeeper:

zkserver start

关闭 zookeeper:

zkserver stop

Go 操作 zookeeper

Go 操作 zookeeper 需要依赖第三方库,这里介绍 samuel/go-zookeeper,GitHub 地址如下:
https://github.com/samuel/go-zookeeper

下面写个简单的例子来测试下基本的操作:

/*** 获取一个zk连接* @return {[type]}*/
func getConnect(zkList []string) (conn *zk.Conn) {conn, _, err := zk.Connect(zkList, 10*time.Second)if err != nil {fmt.Println(err)}return
}/*** 测试连接* @return*/
func test1() {zkList := []string{"localhost:2183"}conn := getConnect(zkList)defer conn.Close()conn.Create("/go_servers", nil, 0, zk.WorldACL(zk.PermAll))time.Sleep(20 * time.Second)
}/*** 测试临时节点* @return {[type]}*/
func test2() {zkList := []string{"localhost:2183"}conn := getConnect(zkList)defer conn.Close()conn.Create("/testadaadsasdsaw", nil, zk.FlagEphemeral, zk.WorldACL(zk.PermAll))time.Sleep(20 * time.Second)
}/*** 获取所有节点*/
func test3() {zkList := []string{"localhost:2183"}conn := getConnect(zkList)defer conn.Close()children, _, err := conn.Children("/go_servers")if err != nil {fmt.Println(err)}fmt.Printf("%v \n", children)
}func main() {test1()
}

分布式 server

目前分布式系统已经很流行了,一些开源框架也被广泛应用,如 dubbo、Motan 等。对于一个分布式服务,最基本的一项功能就是服务的注册和发现,而利用 zk 的 EPHEMERAL 节点则可以很方便的实现该功能。EPHEMERAL节点正如其名,是临时性的,其生命周期是和客户端会话绑定的,当会话连接断开时,节点也会被删除。下边我们就来实现一个简单的分布式server。

server:

  • 服务启动时,创建zk连接,并在go_servers节点下创建一个新节点,节点名为"ip:port",完成服务注册
  • 服务结束时,由于连接断开,创建的节点会被删除,这样client就不会连到该节点

client:

  • 先从zk获取go_servers节点下所有子节点,这样就拿到了所有注册的server
  • 从server列表中选中一个节点(这里只是随机选取,实际服务一般会提供多种策略),创建连接进行通信

为了演示,每次client连接server,获取server发送的时间后就断开。主要代码如下:

server.go

func main() {go starServer("127.0.0.1:8897")go starServer("127.0.0.1:8898")go starServer("127.0.0.1:8899")a := make(chan bool, 1)<-a
}func checkError(err error) {if err != nil {fmt.Println(err)}
}func starServer(port string) {tcpAddr, err := net.ResolveTCPAddr("tcp4", port)fmt.Println(tcpAddr)checkError(err)listener, err := net.ListenTCP("tcp", tcpAddr)checkError(err)//注册zk节点q// 链接zkconn, err := GetConnect()if err != nil {fmt.Printf(" connect zk error: %s ", err)}defer conn.Close()// zk节点注册err = RegistServer(conn, port)if err != nil {fmt.Printf(" regist node error: %s ", err)}for {conn, err := listener.Accept()if err != nil {fmt.Fprintf(os.Stderr, "Error: %s", err)continue}go handleCient(conn, port)}fmt.Println("aaaaaa")
}func handleCient(conn net.Conn, port string) {defer conn.Close()daytime := time.Now().String()conn.Write([]byte(port + ": " + daytime))
}
func GetConnect() (conn *zk.Conn, err error) {zkList := []string{"localhost:2181"}conn, _, err = zk.Connect(zkList, 10*time.Second)if err != nil {fmt.Println(err)}return
}func RegistServer(conn *zk.Conn, host string) (err error) {_, err = conn.Create("/go_servers/"+host, nil, zk.FlagEphemeral, zk.WorldACL(zk.PermAll))return
}func GetServerList(conn *zk.Conn) (list []string, err error) {list, _, err = conn.Children("/go_servers")return
}

client.go

func checkError(err error) {if err != nil {fmt.Println(err)}
}
func main() {for i := 0; i < 100; i++ {startClient()time.Sleep(1 * time.Second)}
}func startClient() {// service := "127.0.0.1:8899"//获取地址serverHost, err := getServerHost()if err != nil {fmt.Printf("get server host fail: %s \n", err)return}fmt.Println("connect host: " + serverHost)tcpAddr, err := net.ResolveTCPAddr("tcp4", serverHost)checkError(err)conn, err := net.DialTCP("tcp", nil, tcpAddr)checkError(err)defer conn.Close()_, err = conn.Write([]byte("timestamp"))checkError(err)result, err := ioutil.ReadAll(conn)checkError(err)fmt.Println(string(result))return
}func getServerHost() (host string, err error) {conn, err := GetConnect()if err != nil {fmt.Printf(" connect zk error: %s \n ", err)return}defer conn.Close()serverList, err := GetServerList(conn)if err != nil {fmt.Printf(" get server list error: %s \n", err)return}count := len(serverList)if count == 0 {err = errors.New("server list is empty \n")return}//随机选中一个返回r := rand.New(rand.NewSource(time.Now().UnixNano()))host = serverList[r.Intn(3)]return
}
func GetConnect() (conn *zk.Conn, err error) {zkList := []string{"localhost:2181"}conn, _, err = zk.Connect(zkList, 10*time.Second)if err != nil {fmt.Println(err)}return
}
func GetServerList(conn *zk.Conn) (list []string, err error) {list, _, err = conn.Children("/go_servers")return

先启动 server.go,再启动 client.go。

参考

https://www.kancloud.cn/liupengjie/go/745743

Go语言连接 zookeeper相关推荐

  1. 在VS下用C语言连接SQLServer2008

    在VS下用C语言连接SQLServer2008 原文:在VS下用C语言连接SQLServer2008 step1:启动SQLSERVER服务 step2:打建立数据库test,在test库中建立tes ...

  2. c语言 mysql_bind,C语言连接SQLSERVER数据库

    第一步:配置ODBC.在配置ODBC时有用户DSN.系统DSN.和文件DSN三种方法,为了稳妥起见,采用系统DSN. DSN的名字叫LocalServer,帐号:sa,密码123456 第二步:打开V ...

  3. php连接数据库语言,PHP语言连接MYSQL数据库实例代码

    本文主要向大家介绍了PHP语言连接MYSQL数据库实例代码,通过具体的内容向大家展示,希望对大家学习php语言有所帮助. 现在做的项目需要php连接mysql数据库,虽然之前学过,但是现在基本上都给忘 ...

  4. Zookeeper命令行操作(常用命令;客户端连接;查看znode路径;创建节点;获取znode数据,查看节点内容,设置节点内容,删除节点;监听znode事件;telnet连接zookeeper)

    8.1.常用命令 启动ZK服务 bin/zkServer.sh start 查看ZK服务状态 bin/zkServer.sh status 停止ZK服务 bin/zkServer.sh stop 重启 ...

  5. python中使用kazoo连接zookeeper(一)

    http://hi.baidu.com/eldersun/item/b9266e019da769f0f45ba6a4 python下连接zookeeper使用最多的是python 包装的zookeep ...

  6. C#语言连接Mysql数据库实现增删改查

    C#语言连接Mysql数据库实现增删改查 实现效果如图 在此之前先下载一个mysql.dll 库 如下 链接:https://pan.baidu.com/s/17Nv_1W3KbXfWgdOvWf_S ...

  7. c语言连接mysql_聊聊数据库MySQL、SqlServer、Oracle的区别,哪个更适合你?

    一.MySQL 优点: 体积小.速度快.总体拥有成本低,开源: 支持多种操作系统: 是开源数据库,提供的接口支持多种语言连接操作 : MySQL的核心程序采用完全的多线程编程.线程是轻量级的进程,它可 ...

  8. Windows下C语言连接Oracle数据库

    为什么80%的码农都做不了架构师?>>>    最近公司有个项目需要用到Oracle数据库,我负责前期的调研.由于项目要用到C和PHP两种语言,所以先收集这两种语言连接Oracle的 ...

  9. c语言sqlserver进行odbc编程,在VS下用C语言连接SQLServer2008

    原文: 在VS下用C语言连接SQLServer2008 step1:启动SQLSERVER服务 step2:打建立数据库test,在test库中建立test表(a varchar(200),b var ...

最新文章

  1. [转载]C#模拟键盘鼠标事件-SendKeys
  2. 防止接口数据出问题,前端假数据调试
  3. Python内置函数eval
  4. oc35--自定义构造方法
  5. 【数据结构与算法】之深入解析“完美矩形”的求解思路与算法示例
  6. HALCON示例程序stamp_catalogue.hdev分割图片与文字
  7. JS里的onclick事件
  8. 由浅入深CIL系列:5.抛砖引玉:判断string是否为空的四种方法的CIL代码看看效率如何?...
  9. 自动控制原理_电容补偿的作用与自动控制原理
  10. 洛谷 P4568 [JLOI2011]飞行路线
  11. (整理)RMAN备份详解
  12. HTML 标签的 target 属性
  13. JavaWeb新闻发布系统案例1
  14. 打印机服务器虚拟端口,Win7打印机服务器端口添加方法
  15. 企业微信hook接口,pc企业微信协议
  16. 模板库(七) - 字符串算法
  17. Python 调试Webservice接口
  18. SharePoint 2013 App Development读书笔记1
  19. 获取网页链接里的视频原件
  20. 支付宝沙箱开启以及配置

热门文章

  1. 中国AI又夺一冠!依图刷榜全球声纹识别挑战赛,刷新纪录,大比分夺魁
  2. 国产AI框架再进化!百度Paddle Lite发布:率先支持华为NPU在线编译,全新架构更多硬件支持...
  3. 前SAP全球VP加盟第四范式任总裁,戴文渊:加速多行业规模化扩展
  4. JBoss 系列八十一: jBPM 6 中使用 jbpm-console 创建执行 BPM 流程 - II
  5. Sublime Text 2 和 Verilog HDL
  6. bzoj1874: [BeiJing2009 WinterCamp]取石子游戏
  7. [怪谈]唯有数学不会因时代的变迁而没落
  8. Cocos2d-x 生成真正的随机数
  9. proftpd登陆速度慢的解决[转]
  10. 视频可以转换html,10 个免费的 HTML 视频转换工具