go 集成nacos注册中心、配置中心

发布于:2024-12-18 ⋅ 阅读:(131) ⋅ 点赞:(0)

使用限制

Go>=v1.15

Nacos>2.x

安装

使用go get安装SDK:

go get -u github.com/nacos-group/nacos-sdk-go/v2

快速使用

  • 初始化客户端配置ClientConfig
constant.ClientConfig{
  TimeoutMs            uint64 // 请求Nacos服务端的超时时间,默认是10000ms
  NamespaceId          string // Nacos的命名空间Id
  Endpoint             string // 当使用地址服务器时,需要该配置. https://help.aliyun.com/document_detail/130146.html
  RegionId             string // Nacos&KMS的regionId,用于配置中心的鉴权
  AccessKey            string // Nacos&KMS的AccessKey,用于配置中心的鉴权
  SecretKey            string // Nacos&KMS的SecretKey,用于配置中心的鉴权
  OpenKMS              bool   // 是否开启kms,默认不开启,kms可以参考文档 https://help.aliyun.com/product/28933.html
                              // 同时DataId必须以"cipher-"作为前缀才会启动加解密逻辑
  CacheDir             string // 缓存service信息的目录,默认是当前运行目录
  UpdateThreadNum      int    // 监听service变化的并发数,默认20
  NotLoadCacheAtStart  bool   // 在启动的时候不读取缓存在CacheDir的service信息
  UpdateCacheWhenEmpty bool   // 当service返回的实例列表为空时,不更新缓存,用于推空保护
  Username             string // Nacos服务端的API鉴权Username
  Password             string // Nacos服务端的API鉴权Password
  LogDir               string // 日志存储路径
  RotateTime           string // 日志轮转周期,比如:30m, 1h, 24h, 默认是24h
  MaxAge               int64  // 日志最大文件数,默认3
  LogLevel             string // 日志默认级别,值必须是:debug,info,warn,error,默认值是info
}
  • ServerConfig
constant.ServerConfig{
  ContextPath string // Nacos的ContextPath,默认/nacos,在2.0中不需要设置
  IpAddr      string // Nacos的服务地址
  Port        uint64 // Nacos的服务端口
  Scheme      string // Nacos的服务地址前缀,默认http,在2.0中不需要设置
  GrpcPort    uint64 // Nacos的 grpc 服务端口, 默认为 服务端口+1000, 不是必填
}

 Note:我们可以配置多个ServerConfig,客户端会对这些服务端做轮询请求

Create client

// 创建clientConfig
clientConfig := constant.ClientConfig{
  NamespaceId:         "e525eafa-f7d7-4029-83d9-008937f9d468", // 如果需要支持多namespace,我们可以创建多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
  TimeoutMs:           5000,
  NotLoadCacheAtStart: true,
  LogDir:              "/tmp/nacos/log",
  CacheDir:            "/tmp/nacos/cache",
  LogLevel:            "debug",
}

// 创建clientConfig的另一种方式
clientConfig := *constant.NewClientConfig(
    constant.WithNamespaceId("e525eafa-f7d7-4029-83d9-008937f9d468"), //当namespace是public时,此处填空字符串。
    constant.WithTimeoutMs(5000),
    constant.WithNotLoadCacheAtStart(true),
    constant.WithLogDir("/tmp/nacos/log"),
    constant.WithCacheDir("/tmp/nacos/cache"),
    constant.WithLogLevel("debug"),
)

// 至少一个ServerConfig
serverConfigs := []constant.ServerConfig{
    {
        IpAddr:      "console1.nacos.io",
        ContextPath: "/nacos",
        Port:        80,
        Scheme:      "http",
    },
    {
      IpAddr:      "console2.nacos.io",
      ContextPath: "/nacos",
      Port:        80,
        Scheme:      "http",
    },
}

// 创建serverConfig的另一种方式
serverConfigs := []constant.ServerConfig{
    *constant.NewServerConfig(
        "console1.nacos.io",
        80,
        constant.WithScheme("http"),
        constant.WithContextPath("/nacos"),
    ),
    *constant.NewServerConfig(
        "console2.nacos.io",
        80,
        constant.WithScheme("http"),
        constant.WithContextPath("/nacos"),
    ),
}

// 创建服务发现客户端
_, _ := clients.CreateNamingClient(map[string]interface{}{
  "serverConfigs": serverConfigs,
  "clientConfig":  clientConfig,
})

// 创建动态配置客户端
_, _ := clients.CreateConfigClient(map[string]interface{}{
  "serverConfigs": serverConfigs,
  "clientConfig":  clientConfig,
})

// 创建服务发现客户端的另一种方式 (推荐)
namingClient, err := clients.NewNamingClient(
    vo.NacosClientParam{
        ClientConfig:  &clientConfig,
        ServerConfigs: serverConfigs,
    },
)

// 创建动态配置客户端的另一种方式 (推荐)
configClient, err := clients.NewConfigClient(
    vo.NacosClientParam{
        ClientConfig:  &clientConfig,
        ServerConfigs: serverConfigs,
    },
)

服务发现

  • 注册实例:RegisterInstance
success, err := namingClient.RegisterInstance(vo.RegisterInstanceParam{
    Ip:          "10.0.0.11",
    Port:        8848,
    ServiceName: "demo.go",
    Weight:      10,
    Enable:      true,
    Healthy:     true,
    Ephemeral:   true,
    Metadata:    map[string]string{"idc":"shanghai"},
    ClusterName: "cluster-a", // 默认值DEFAULT
    GroupName:   "group-a",   // 默认值DEFAULT_GROUP
})
  • 注销实例:DeregisterInstance
success, err := namingClient.DeregisterInstance(vo.DeregisterInstanceParam{
    Ip:          "10.0.0.11",
    Port:        8848,
    ServiceName: "demo.go",
    Ephemeral:   true,
    Cluster:     "cluster-a", // 默认值DEFAULT
    GroupName:   "group-a",   // 默认值DEFAULT_GROUP
})
  • 获取服务信息:GetService
services, err := namingClient.GetService(vo.GetServiceParam{
    ServiceName: "demo.go",
    Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
    GroupName:   "group-a",             // 默认值DEFAULT_GROUP
})
  • 获取所有的实例列表:SelectAllInstances
// SelectAllInstance可以返回全部实例列表,包括healthy=false,enable=false,weight<=0
instances, err := namingClient.SelectAllInstances(vo.SelectAllInstancesParam{
    ServiceName: "demo.go",
    GroupName:   "group-a",             // 默认值DEFAULT_GROUP
    Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
})
  • 获取实例列表 :SelectInstances
// SelectInstances 只返回满足这些条件的实例列表:healthy=${HealthyOnly},enable=true 和weight>0
instances, err := namingClient.SelectInstances(vo.SelectInstancesParam{
    ServiceName: "demo.go",
    GroupName:   "group-a",             // 默认值DEFAULT_GROUP
    Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
    HealthyOnly: true,
})
  • 获取一个健康的实例(加权随机轮询):SelectOneHealthyInstance
// SelectOneHealthyInstance将会按加权随机轮询的负载均衡策略返回一个健康的实例
// 实例必须满足的条件:health=true,enable=true and weight>0
instance, err := namingClient.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
    ServiceName: "demo.go",
    GroupName:   "group-a",             // 默认值DEFAULT_GROUP
    Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
})
  • 监听服务变化:Subscribe
// Subscribe key=serviceName+groupName+cluster
// 注意:我们可以在相同的key添加多个SubscribeCallback.
err := namingClient.Subscribe(vo.SubscribeParam{
    ServiceName: "demo.go",
    GroupName:   "group-a",             // 默认值DEFAULT_GROUP
    Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
    SubscribeCallback: func(services []model.Instance, err error) {
        log.Printf("\n\n callback return services:%s \n\n", utils.ToJsonString(services))
    },
})
  • 取消服务监听:Unsubscribe
err := namingClient.Unsubscribe(vo.SubscribeParam{
    ServiceName: "demo.go",
    GroupName:   "group-a",             // 默认值DEFAULT_GROUP
    Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
    SubscribeCallback: func(services []model.Instance, err error) {
        log.Printf("\n\n callback return services:%s \n\n", utils.ToJsonString(services))
    },
})
  • 获取服务名列表
serviceInfos, err := namingClient.GetAllServicesInfo(vo.GetAllServiceInfoParam{
    NameSpace: "0e83cc81-9d8c-4bb8-a28a-ff703187543f",
    PageNo:   1,
    PageSize: 10,
  }),

动态配置

  • 发布配置:PublishConfig
success, err := configClient.PublishConfig(vo.ConfigParam{
    DataId:  "dataId",
    Group:   "group",
    Content: "hello world!222222"})
  • 删除配置:DeleteConfig
success, err = configClient.DeleteConfig(vo.ConfigParam{
    DataId: "dataId",
    Group:  "group"})
  • 获取配置:GetConfig
content, err := configClient.GetConfig(vo.ConfigParam{
    DataId: "dataId",
    Group:  "group"})
  • 监听配置变化:ListenConfig
err := configClient.ListenConfig(vo.ConfigParam{
    DataId: "dataId",
    Group:  "group",
    OnChange: func(namespace, group, dataId, data string) {
        fmt.Println("group:" + group + ", dataId:" + dataId + ", data:" + data)
  },
})
  • 取消配置监听:CancelListenConfig
err := configClient.CancelListenConfig(vo.ConfigParam{
    DataId: "dataId",
    Group:  "group",
})
  • 搜索配置: SearchConfig
configPage,err := configClient.SearchConfig(vo.SearchConfigParam{
    Search:   "blur",
    DataId:   "",
    Group:    "",
    PageNo:   1,
    PageSize: 10,
})

工具

client

/*
 * Copyright 1999-2020 Alibaba Group Holding Ltd.
 *
 * Licensed 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 nacos

import (
	"fmt"

	"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"

	"github.com/nacos-group/nacos-sdk-go/v2/vo"
)

func RegisterServiceInstance(client naming_client.INamingClient, param vo.RegisterInstanceParam) {
	success, err := client.RegisterInstance(param)
	if !success || err != nil {
		panic("RegisterServiceInstance failed!" + err.Error())
	}
	fmt.Printf("RegisterServiceInstance,param:%+v,result:%+v \n\n", param, success)
}

func BatchRegisterServiceInstance(client naming_client.INamingClient, param vo.BatchRegisterInstanceParam) {
	success, err := client.BatchRegisterInstance(param)
	if !success || err != nil {
		panic("BatchRegisterServiceInstance failed!" + err.Error())
	}
	fmt.Printf("BatchRegisterServiceInstance,param:%+v,result:%+v \n\n", param, success)
}

func DeRegisterServiceInstance(client naming_client.INamingClient, param vo.DeregisterInstanceParam) {
	success, err := client.DeregisterInstance(param)
	if !success || err != nil {
		panic("DeRegisterServiceInstance failed!" + err.Error())
	}
	fmt.Printf("DeRegisterServiceInstance,param:%+v,result:%+v \n\n", param, success)
}

func UpdateServiceInstance(client naming_client.INamingClient, param vo.UpdateInstanceParam) {
	success, err := client.UpdateInstance(param)
	if !success || err != nil {
		panic("UpdateInstance failed!" + err.Error())
	}
	fmt.Printf("UpdateServiceInstance,param:%+v,result:%+v \n\n", param, success)
}

func GetService(client naming_client.INamingClient, param vo.GetServiceParam) {
	service, err := client.GetService(param)
	if err != nil {
		panic("GetService failed!" + err.Error())
	}
	fmt.Printf("GetService,param:%+v, result:%+v \n\n", param, service)
}

func SelectAllInstances(client naming_client.INamingClient, param vo.SelectAllInstancesParam) {
	instances, err := client.SelectAllInstances(param)
	if err != nil {
		panic("SelectAllInstances failed!" + err.Error())
	}
	fmt.Printf("SelectAllInstance,param:%+v, result:%+v \n\n", param, instances)
}

func SelectInstances(client naming_client.INamingClient, param vo.SelectInstancesParam) {
	instances, err := client.SelectInstances(param)
	if err != nil {
		panic("SelectInstances failed!" + err.Error())
	}
	fmt.Printf("SelectInstances,param:%+v, result:%+v \n\n", param, instances)
}

func SelectOneHealthyInstance(client naming_client.INamingClient, param vo.SelectOneHealthInstanceParam) {
	instances, err := client.SelectOneHealthyInstance(param)
	if err != nil {
		panic("SelectOneHealthyInstance failed!")
	}
	fmt.Printf("SelectOneHealthyInstance,param:%+v, result:%+v \n\n", param, instances)
}

func Subscribe(client naming_client.INamingClient, param *vo.SubscribeParam) {
	_ = client.Subscribe(param)
}

func UnSubscribe(client naming_client.INamingClient, param *vo.SubscribeParam) {
	_ = client.Unsubscribe(param)
}

func GetAllService(client naming_client.INamingClient, param vo.GetAllServiceInfoParam) {
	service, err := client.GetAllServicesInfo(param)
	if err != nil {
		panic("GetAllService failed!")
	}
	fmt.Printf("GetAllService,param:%+v, result:%+v \n\n", param, service)
}

config

/*
 * Copyright 1999-2020 Alibaba Group Holding Ltd.
 *
 * Licensed 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 nacos

import (
	"fmt"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
	"github.com/nacos-group/nacos-sdk-go/v2/model"
	"github.com/nacos-group/nacos-sdk-go/v2/vo"
)

func PublishConfig(client config_client.IConfigClient, param vo.ConfigParam) {
	//publish config
	//config key=dataId+group+namespaceId
	_, err := client.PublishConfig(param)
	if err != nil {
		fmt.Printf("PublishConfig err:%+v \n", err)
	}
}

func DeleteConfig(client config_client.IConfigClient, param vo.ConfigParam) {
	_, err := client.DeleteConfig(param)
	if err != nil {
		fmt.Printf("DeleteConfig err:%+v \n", err)
	}
}

func GetConfig(client config_client.IConfigClient, param vo.ConfigParam) string {
	//get config
	content, err := client.GetConfig(param)
	if err != nil {
		fmt.Printf("GetConfig err:%+v \n", err)
	} else {
		fmt.Println("GetConfig,config :" + content)
	}
	return content
}

func ListenConfig(client config_client.IConfigClient, param vo.ConfigParam) {
	//Listen config change,key=dataId+group+namespaceId.
	err := client.ListenConfig(vo.ConfigParam{
		DataId: "test-data",
		Group:  "test-group",
		OnChange: func(namespace, group, dataId, data string) {
			fmt.Println("config changed group:" + group + ", dataId:" + dataId + ", content:" + data)
		},
	})
	if err != nil {
		fmt.Printf("PublishConfig err:%+v \n", err)
	}
}

func CancelListenConfig(client config_client.IConfigClient, param vo.ConfigParam) {
	//cancel config change
	err := client.CancelListenConfig(param)
	if err != nil {
		fmt.Printf("CancelListenConfig err:%+v \n", err)
	}
}

func SearchConfig(client config_client.IConfigClient, param vo.SearchConfigParam) *model.ConfigPage {
	searchPage, err := client.SearchConfig(param)
	if err != nil {
		fmt.Printf("SearchConfig err:%+v \n", err)
	} else {
		fmt.Printf("SearchConfig:%+v \n", searchPage)
	}
	return searchPage
}