You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by xi...@apache.org on 2022/06/28 09:33:19 UTC

[incubator-shenyu-client-golang] branch main updated: [feature: Integrate zk client] (#17)

This is an automated email from the ASF dual-hosted git repository.

xiaoyu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu-client-golang.git


The following commit(s) were added to refs/heads/main by this push:
     new dc92ac4  [feature: Integrate zk client] (#17)
dc92ac4 is described below

commit dc92ac421a31192832653310ac0e071538d4bc84
Author: Lisandro <li...@163.com>
AuthorDate: Tue Jun 28 17:33:14 2022 +0800

    [feature: Integrate zk client] (#17)
    
    * [feature: Integrate zk client]
    
    * [feature: Integrate zk_client_test]
    
    * [feature: Add about Zookeeper Document of README ZN CN.]
    
    * [feature: Add zk action.]
    
    * [feature: Adjust ci compose path.]
    
    * [feature: renamed zk example.]
    
    Co-authored-by: lishuo <li...@mesomia-tech.com>
---
 .github/workflows/build.yml                        |   3 +
 README.md                                          |  67 ++++++++
 README_CN.md                                       |  67 ++++++++
 clients/nacos_client/nacos_client.go               |   6 +-
 clients/zk_client/zk_client.go                     | 180 +++++++++++++++++++++
 clients/zk_client/zk_client_test.go                | 141 ++++++++++++++++
 docker-compose.yml                                 |  29 ++++
 example/zk_client/main.go                          | 100 ++++++++++++
 go.mod                                             |   7 +-
 go.sum                                             |   2 +
 ...ta_register.go => common_meta_data_register.go} |   2 +-
 11 files changed, 599 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index eba64d2..9eaa0b2 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -51,6 +51,9 @@ jobs:
       - name: Check out code
         uses: actions/checkout@v1
 
+      - name: Start docker compose
+        run: docker-compose -f  docker-compose.yml up -d
+
       - name: Run Unit tests.
         run: |
           go test `go list ./... | grep -v examples` -coverprofile=coverage.txt -covermode=atomic
diff --git a/README.md b/README.md
index 7d6a82c..8064ab0 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,8 @@ Gateway.
 
 * **Http type Register**
 * **Nacos type Register**
+* **Zookeeper type Register**
+
 ---
 
 ## Requirements
@@ -204,3 +206,68 @@ finish register metadata ,the result is-> true
 ,param:{Ip:10.0.0.10 Port:8848 Weight:10 Enable:true Healthy:true Metadata:map[contextPath:contextPath uriMetadata:{"protocol":"testMetaDataRegister","appName":"testURLRegister","contextPath":"contextPath","rpcType":"http","host":"127.0.0.1","port":"8080"}] ClusterName: ServiceName:demo.go GroupName: Ephemeral:true}
 
 ```
+
+
+
+---
+## The Zookeeper type Register
+
+**1.Fist make sure your Zookeeper env is correct,the set this necessary param.**
+```go
+    servers := []string{"127.0.0.1:2181"}         //require user provide
+        client, err := NewClient(servers, "/api", 10) //zkRoot require user provide
+        if err != nil {
+            panic(err)
+         }
+        defer client.Close()
+```
+
+**2. Prepare your service metaData to register**
+```go
+//metaData is necessary param, this will be register to shenyu gateway to use
+        //init MetaDataRegister
+        metaData1 := &model.MetaDataRegister{
+            AppName: "testMetaDataRegister", //require user provide
+            Path:    "your/path1",           //require user provide
+            Enabled: true,                   //require user provide
+            Host:    "127.0.0.1",            //require user provide
+            Port:    "8080",                 //require user provide
+        }
+```
+
+**3.use client to invoke RegisterNacosInstance**
+```go
+   //register multiple metaData
+    if err := client.RegisterNodeInstance(metaData1); err != nil {
+        panic(err)
+    }
+        //do your logic
+```
+
+**4.use client to invoke DeleteNodeInstance**
+```go
+    //your can chose to invoke,not require
+    err = client.DeleteNodeInstance(metaData1)
+     if err != nil {
+       panic(err)
+}
+```
+
+**5.use client to get zk nodes**
+```go
+    //range nodes
+    for index, node := range nodes {
+        nodeJson, err := json.Marshal(node)
+        if err == nil {
+        logger.Info("GetNodesInfo ,success Index", index, string(nodeJson))
+    }
+}
+```
+
+## Entire Success log
+```go
+2022-06-28 15:21:57 [INFO] [github.com/incubator-shenyu-client-golang/example/zk_client/zk_client.go:80] GetNodesInfo ,success Index 0 {"appName":"testMetaDataRegister","path":"your/path1","rpcType":"","enabled":true,"host":"127.0.0.1","port":"8080","pluginNames":null,"registerMetaData":false,"timeMillis":0}
+2022-06-28 15:21:57 [INFO] [github.com/incubator-shenyu-client-golang/example/zk_client/zk_client.go:80] GetNodesInfo ,success Index 1 {"appName":"testMetaDataRegister","path":"your/path3","rpcType":"","enabled":true,"host":"127.0.0.1","port":"8282","pluginNames":null,"registerMetaData":false,"timeMillis":0}
+2022-06-28 15:21:57 [INFO] [github.com/incubator-shenyu-client-golang/example/zk_client/zk_client.go:80] GetNodesInfo ,success Index 2 {"appName":"testMetaDataRegister","path":"your/path2","rpcType":"","enabled":true,"host":"127.0.0.1","port":"8181","pluginNames":null,"registerMetaData":false,"timeMillis":0}
+
+```
diff --git a/README_CN.md b/README_CN.md
index 68336f6..f0ccc88 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -15,6 +15,8 @@ Shenyu-client-golang是提供了Go语言访问ShenYu网关的功能,并支持
 ## 已支持注册到ShenYu网关的方式
 * **以Http方式注册**
 * **以Nacos方式注册**
+* **以Zookeeper方式注册**
+
 ---
 
 ## 要求
@@ -202,3 +204,68 @@ metaData := &model.URIRegister{
 ,param:{Ip:10.0.0.10 Port:8848 Weight:10 Enable:true Healthy:true Metadata:map[contextPath:contextPath uriMetadata:{"protocol":"testMetaDataRegister","appName":"testURLRegister","contextPath":"contextPath","rpcType":"http","host":"127.0.0.1","port":"8080"}] ClusterName: ServiceName:demo.go GroupName: Ephemeral:true}
 
 ```
+
+
+
+
+---
+## The Zookeeper type Register
+
+**1.首先确保你的Zookeeper环境是正确,然后设置这些Zookeeper必要的参数 .**
+```go
+    servers := []string{"127.0.0.1:2181"}             //需要用户提供
+        client, err := NewClient(servers, "/api", 10) //需要用户提供
+        if err != nil {
+            panic(err)
+         }
+        defer client.Close()
+```
+
+**2.  准备你要注册服务的元数据信息**
+```go
+//元数据是必要的参数,这将注册到shenyu网关使用
+        metaData1 := &model.MetaDataRegister{
+            AppName: "testMetaDataRegister", //需要用户提供
+            Path:    "your/path1",           //需要用户提供
+            Enabled: true,                   //需要用户提供
+            Host:    "127.0.0.1",            //需要用户提供
+            Port:    "8080",                 //需要用户提供
+        }
+```
+
+**3.使用客户端进行节点信息注册**
+```go
+   //可以进行多个实例注册
+    if err := client.RegisterNodeInstance(metaData1); err != nil {
+        panic(err)
+    }
+        //做你的逻辑处理
+```
+
+**4.使用客户端进行注册节点信息删除**
+```go
+    //选择性调用
+    err = client.DeleteNodeInstance(metaData1)
+     if err != nil {
+       panic(err)
+}
+```
+
+**5.使用客户端获取注册节点的信息**
+```go
+    //遍历节点
+    for index, node := range nodes {
+        nodeJson, err := json.Marshal(node)
+        if err == nil {
+        logger.Info("GetNodesInfo ,success Index", index, string(nodeJson))
+    }
+}
+```
+
+## 完整的成功日志
+```go
+2022-06-28 15:21:57 [INFO] [github.com/incubator-shenyu-client-golang/example/zk_client/zk_client.go:80] GetNodesInfo ,success Index 0 {"appName":"testMetaDataRegister","path":"your/path1","rpcType":"","enabled":true,"host":"127.0.0.1","port":"8080","pluginNames":null,"registerMetaData":false,"timeMillis":0}
+2022-06-28 15:21:57 [INFO] [github.com/incubator-shenyu-client-golang/example/zk_client/zk_client.go:80] GetNodesInfo ,success Index 1 {"appName":"testMetaDataRegister","path":"your/path3","rpcType":"","enabled":true,"host":"127.0.0.1","port":"8282","pluginNames":null,"registerMetaData":false,"timeMillis":0}
+2022-06-28 15:21:57 [INFO] [github.com/incubator-shenyu-client-golang/example/zk_client/zk_client.go:80] GetNodesInfo ,success Index 2 {"appName":"testMetaDataRegister","path":"your/path2","rpcType":"","enabled":true,"host":"127.0.0.1","port":"8181","pluginNames":null,"registerMetaData":false,"timeMillis":0}
+
+```
diff --git a/clients/nacos_client/nacos_client.go b/clients/nacos_client/nacos_client.go
index 5892d53..1ed9d6d 100644
--- a/clients/nacos_client/nacos_client.go
+++ b/clients/nacos_client/nacos_client.go
@@ -29,9 +29,9 @@ import (
  * NacosClientParam
  **/
 type NacosClientParam struct {
-	IpAddr      string //the nacos server address
-	Port        uint64 //the nacos server port
-	NamespaceId string // the namespaceId of Nacos.When namespace is public, fill in the blank string here.
+	IpAddr      string //the nacos server address require user provide
+	Port        uint64 //the nacos server port require user provide
+	NamespaceId string // the namespaceId of Nacos.When namespace is public, fill in the blank string here  require user provide.
 }
 
 /**
diff --git a/clients/zk_client/zk_client.go b/clients/zk_client/zk_client.go
new file mode 100644
index 0000000..dba1e4c
--- /dev/null
+++ b/clients/zk_client/zk_client.go
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package zk_client
+
+import (
+	"encoding/json"
+	"github.com/apache/incubator-shenyu-client-golang/model"
+	"github.com/samuel/go-zookeeper/zk"
+	"github.com/wonderivan/logger"
+	"time"
+)
+
+/**
+ * ServiceNode
+ **/
+type ServiceNode struct {
+	RootName string                  `json:"rootName"` // the register zk rootName  require user provide
+	MetaData *model.MetaDataRegister `json:"metaData"` // the register metaData  require user provide
+}
+
+/**
+ * zkServer
+ **/
+type zkServer struct {
+	zkServers []string // zkServers ex: 127.0.0.1
+	zkRoot    string   // zkClient Root
+	zkClient  *zk.Conn // zkClient
+}
+
+/**
+ * init NewClient
+ **/
+func NewClient(zkServers []string, zkRoot string, timeout int) (*zkServer, error) {
+	client := new(zkServer)
+	client.zkServers = zkServers
+	if len(zkRoot) == 0 {
+		logger.Fatal("The param zkRoot must set a value!")
+	}
+	client.zkRoot = zkRoot
+	conn, _, err := zk.Connect(zkServers, time.Duration(timeout)*time.Second)
+	if err != nil {
+		return nil, err
+	}
+	client.zkClient = conn
+	if err := client.ensureRoot(); err != nil {
+		client.Close()
+		return nil, err
+	}
+	return client, nil
+}
+
+/**
+ * close zkClient
+ **/
+func (s *zkServer) Close() {
+	s.zkClient.Close()
+}
+
+/**
+ * ensure zkRoot avoid create error
+ **/
+func (s *zkServer) ensureRoot() error {
+	exists, _, err := s.zkClient.Exists(s.zkRoot)
+	if err != nil {
+		return err
+	}
+	if !exists {
+		_, err := s.zkClient.Create(s.zkRoot, []byte(""), 0, zk.WorldACL(zk.PermAll))
+		if err != nil && err != zk.ErrNodeExists {
+			return err
+		}
+	}
+	return nil
+}
+
+/**
+ * RegisterNodeInstance zk node
+ **/
+func (s *zkServer) RegisterNodeInstance(metaData *model.MetaDataRegister) error {
+	if err := s.ensureName(metaData.AppName); err != nil {
+		return err
+	}
+	path := s.zkRoot + "/" + metaData.AppName + "/n"
+	data, err := json.Marshal(metaData)
+	if err != nil {
+		return err
+	}
+	_, err = s.zkClient.CreateProtectedEphemeralSequential(path, data, zk.WorldACL(zk.PermAll))
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+/**
+ * DeleteNodeInstance
+ **/
+func (s *zkServer) DeleteNodeInstance(metaData *model.MetaDataRegister) error {
+	if err := s.ensureName(metaData.AppName); err != nil {
+		return err
+	}
+	path := s.zkRoot + "/" + metaData.AppName
+	childs, stat, err := s.zkClient.Children(path)
+	if err != nil {
+		return err
+	}
+	for _, child := range childs {
+		fullPath := path + "/" + child
+		err := s.zkClient.Delete(fullPath, stat.Version)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+/**
+ *  * ensure zkRoot&nodeName
+ **/
+func (s *zkServer) ensureName(name string) error {
+	path := s.zkRoot + "/" + name
+	exists, _, err := s.zkClient.Exists(path) //avoid create error
+	if err != nil {
+		return err
+	}
+	if !exists {
+		_, err := s.zkClient.Create(path, []byte(""), 0, zk.WorldACL(zk.PermAll))
+		if err != nil && err != zk.ErrNodeExists {
+			return err
+		}
+	}
+	return nil
+}
+
+/**
+ * get zk nodes metaData
+ **/
+func (s *zkServer) GetNodesInfo(name string) ([]*model.MetaDataRegister, error) {
+	path := s.zkRoot + "/" + name
+	childs, _, err := s.zkClient.Children(path)
+	if err != nil {
+		if err == zk.ErrNoNode {
+			return []*model.MetaDataRegister{}, nil //default return empty MetaDataRegister
+		}
+		return nil, err
+	}
+	var nodes []*model.MetaDataRegister
+	for _, child := range childs {
+		fullPath := path + "/" + child
+		data, _, err := s.zkClient.Get(fullPath)
+		if err != nil {
+			if err == zk.ErrNoNode {
+				continue
+			}
+			return nil, err
+		}
+		node := new(model.MetaDataRegister)
+		err = json.Unmarshal(data, node)
+		if err != nil {
+			return nil, err
+		}
+		nodes = append(nodes, node)
+	}
+	return nodes, nil
+}
diff --git a/clients/zk_client/zk_client_test.go b/clients/zk_client/zk_client_test.go
new file mode 100644
index 0000000..2d4ec0e
--- /dev/null
+++ b/clients/zk_client/zk_client_test.go
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package zk_client
+
+import (
+	"github.com/apache/incubator-shenyu-client-golang/model"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+/**
+ * TestInitZkClient
+ **/
+func TestInitZkClient(t *testing.T) {
+	servers := []string{"127.0.0.1:2181"}         //require user provide
+	client, err := NewClient(servers, "/api", 10) //zkRoot require user provide
+	if err != nil {
+		panic(err)
+	}
+	defer client.Close()
+	assert.Nil(t, err)
+}
+
+/**
+ * TestRegisterNodeInstanceAndPrint
+ **/
+func TestRegisterNodeInstanceAndPrint(t *testing.T) {
+	servers := []string{"127.0.0.1:2181"}         //require user provide
+	client, err := NewClient(servers, "/api", 10) //zkRoot require user provide
+	if err != nil {
+		panic(err)
+	}
+	defer client.Close()
+	assert.Nil(t, err)
+
+	//init MetaDataRegister
+	metaData1 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path1",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8080",                 //require user provide
+	}
+
+	metaData2 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path2",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8181",                 //require user provide
+	}
+
+	metaData3 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path3",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8282",                 //require user provide
+	}
+
+	//register multiple metaData
+	if err := client.RegisterNodeInstance(metaData1); err != nil {
+		panic(err)
+	}
+	if err := client.RegisterNodeInstance(metaData2); err != nil {
+		panic(err)
+	}
+	if err := client.RegisterNodeInstance(metaData3); err != nil {
+		panic(err)
+	}
+
+	nodes, err := client.GetNodesInfo("testMetaDataRegister")
+	if err != nil {
+		panic(err)
+	}
+
+	assert.NotNil(t, nodes)
+}
+
+/**
+ * TestDeleteNodeInstance
+ **/
+func TestDeleteNodeInstance(t *testing.T) {
+	servers := []string{"127.0.0.1:2181"}         //require user provide
+	client, err := NewClient(servers, "/api", 10) //zkRoot require user provide
+	if err != nil {
+		panic(err)
+	}
+	defer client.Close()
+	assert.Nil(t, err)
+
+	//init MetaDataRegister
+	metaData1 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path1",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8080",                 //require user provide
+	}
+
+	metaData2 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path2",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8181",                 //require user provide
+	}
+
+	metaData3 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path3",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8282",                 //require user provide
+	}
+
+	err = client.DeleteNodeInstance(metaData1)
+	assert.Nil(t, err)
+
+	err = client.DeleteNodeInstance(metaData2)
+	assert.Nil(t, err)
+
+	err = client.DeleteNodeInstance(metaData3)
+	assert.Nil(t, err)
+
+}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..6c9aacb
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+version: "3.9"
+services:
+  shenyu-zk:
+    container_name: shenyu-zk
+    image: zookeeper:3.5
+    restart: always
+    ports:
+      - "2181:2181"
+    networks:
+      - shenyu
+
+networks:
+  shenyu:
+    name: shenyu
diff --git a/example/zk_client/main.go b/example/zk_client/main.go
new file mode 100644
index 0000000..d87eb0f
--- /dev/null
+++ b/example/zk_client/main.go
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+	"encoding/json"
+	"github.com/apache/incubator-shenyu-client-golang/clients/zk_client"
+	"github.com/apache/incubator-shenyu-client-golang/model"
+	"github.com/wonderivan/logger"
+)
+
+func main() {
+	servers := []string{"127.0.0.1:2181"}                   //require user provide
+	client, err := zk_client.NewClient(servers, "/api", 10) //zkRoot require user provide
+	if err != nil {
+		panic(err)
+	}
+	defer client.Close()
+
+	//init MetaDataRegister
+	metaData1 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path1",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8080",                 //require user provide
+	}
+
+	metaData2 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path2",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8181",                 //require user provide
+	}
+
+	metaData3 := &model.MetaDataRegister{
+		AppName: "testMetaDataRegister", //require user provide
+		Path:    "your/path3",           //require user provide
+		Enabled: true,                   //require user provide
+		Host:    "127.0.0.1",            //require user provide
+		Port:    "8282",                 //require user provide
+	}
+
+	//register multiple metaData
+	if err := client.RegisterNodeInstance(metaData1); err != nil {
+		panic(err)
+	}
+	if err := client.RegisterNodeInstance(metaData2); err != nil {
+		panic(err)
+	}
+	if err := client.RegisterNodeInstance(metaData3); err != nil {
+		panic(err)
+	}
+
+	nodes, err := client.GetNodesInfo("testMetaDataRegister")
+	if err != nil {
+		panic(err)
+	}
+
+	//range nodes
+	for index, node := range nodes {
+		nodeJson, err := json.Marshal(node)
+		if err == nil {
+			logger.Info("GetNodesInfo ,success Index", index, string(nodeJson))
+		}
+	}
+
+	//your can chose to invoke,not require
+	err = client.DeleteNodeInstance(metaData1)
+	if err != nil {
+		panic(err)
+	}
+
+	err = client.DeleteNodeInstance(metaData2)
+	if err != nil {
+		panic(err)
+	}
+
+	err = client.DeleteNodeInstance(metaData3)
+	if err != nil {
+		panic(err)
+	}
+
+}
diff --git a/go.mod b/go.mod
index 2e7294b..874ed7d 100644
--- a/go.mod
+++ b/go.mod
@@ -5,21 +5,26 @@ go 1.17
 require (
 	github.com/nacos-group/nacos-sdk-go v1.1.1
 	github.com/pkg/errors v0.9.1
+	github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414
+	github.com/stretchr/testify v1.5.1
 	github.com/wonderivan/logger v1.0.0
 )
 
 require (
 	github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 // indirect
 	github.com/buger/jsonparser v1.1.1 // indirect
+	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/go-errors/errors v1.0.1 // indirect
 	github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
 	github.com/json-iterator/go v1.1.6 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
 	go.uber.org/atomic v1.6.0 // indirect
 	go.uber.org/multierr v1.5.0 // indirect
 	go.uber.org/zap v1.15.0 // indirect
 	golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect
 	gopkg.in/ini.v1 v1.42.0 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
-)
\ No newline at end of file
+	gopkg.in/yaml.v2 v2.2.2 // indirect
+)
diff --git a/go.sum b/go.sum
index 6446e60..4bc1302 100644
--- a/go.sum
+++ b/go.sum
@@ -40,6 +40,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414 h1:AJNDS0kP60X8wwWFvbLPwDuojxubj9pbfK7pjHw0vKg=
+github.com/samuel/go-zookeeper v0.0.0-20201211165307-7117e9ea2414/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
diff --git a/model/http_meta_data_register.go b/model/common_meta_data_register.go
similarity index 97%
rename from model/http_meta_data_register.go
rename to model/common_meta_data_register.go
index d518ead..9a8b9a1 100644
--- a/model/http_meta_data_register.go
+++ b/model/common_meta_data_register.go
@@ -18,7 +18,7 @@
 package model
 
 /**
- * The ShenYu Http MetaDataRegister
+ * The ShenYu common MetaDataRegister
  **/
 type MetaDataRegister struct {
 	AppName          string        `json:"appName"`