基于Golang客户端实现Nacos服务注册发现和配置管理

背景

最近需要把Golang实现的一个web项目集成到基于Spring Cloud Alibaba的微服务体系中,走Spring Cloud Gateway网关路由实现统一的鉴权入口。

软件版本

组件名称组件版本
Nacos2.2.0
Go1.21.0
Ginv1.9.1
Nacos-sdk-gov2.2.5
Spring Cloud2021.0.2
Spring Cloud Alibaba2021.0.1.0

服务注册发现

项目图示

服务注册和发现

Golang客户端的注册发现使用的Nacos官方仓库里面的一个实现:https://github.com/nacos-group/nacos-sdk-go,我这边的实现大多数也是参考的官方提供的样例。

首先,初始化clientConfig和serverConfig的配置

sc := []constant.ServerConfig{*constant.NewServerConfig("localhost", 8848, constant.WithContextPath("/nacos")),}cc := *constant.NewClientConfig(constant.WithNamespaceId("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),constant.WithTimeoutMs(5000),constant.WithNotLoadCacheAtStart(true),constant.WithLogDir("/tmp/nacos/log"),constant.WithCacheDir("/tmp/nacos/cache"),constant.WithUsername("nacos"),constant.WithPassword("nacos"),)

创建服务发现客户端

client, _ := clients.NewNamingClient(vo.NacosClientParam{ClientConfig:&cc,ServerConfigs: sc,},)

服务注册

// 注册服务registerServiceInstance(client, vo.RegisterInstanceParam{Ip:getHostIp(),Port:8777,ServiceName: ServiceName,Weight:10,Enable:true,Healthy: true,Ephemeral: true,})// 注册服务func registerServiceInstance(nacosClient naming_client.INamingClient, param vo.RegisterInstanceParam) {success, err := nacosClient.RegisterInstance(param)if !success || err != nil {panic("register Service Instance failed!")}}// 获取本机ip地址func getHostIp() string {conn, err := net.Dial("udp", "8.8.8.8:53")if err != nil {fmt.Println("get current host ip err: ", err)return ""}addr := conn.LocalAddr().(*net.UDPAddr)ip := strings.Split(addr.String(), ":")[0]return ip}

启动服务,验证ok

客户端负载均衡

作为Go语言初学者,没有详细去了解Go中类似@LoadBalanced或者Feign的框架(后续可能会补充一下),然后我这边就是获取实例解析IP和端口信息,然后直接使用Go原生的http库进行的调用。

获取实例方法

// 获取一个健康的实例func selectOneHealthyInstance(client naming_client.INamingClient, serviceName string) (instance *model.Instance) {instances, err := client.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{ServiceName: serviceName,})if err != nil {panic("SelectOneHealthyInstance failed!")}return instances}

具体调用

func hello(c *gin.Context) {name := c.Param("name")instance := selectOneHealthyInstance(NamingClient, "server-java")url := fmt.Sprintf("http://%s:%d/hello/%s", instance.Ip, instance.Port, name)resp, _ := http.Get(url)defer resp.Body.Close()body, _ := io.ReadAll(resp.Body)c.String(http.StatusOK, string(body))}

在server-java中,提供了一个rest接口

/** * 启动类 * * @author yuanzhihao * @since 2024/3/4 */@RestController@RequestMapping@SpringBootApplicationpublic class Application {@GetMapping("/hello/{name}")public String hello(@PathVariable("name") String name) {return "Hello " + name;}public static void main(String[] args) {SpringApplication.run(Application.class, args);}}

请求 http://localhost:8777/hello/yuan, 调用成功

配置管理

图示

第一步和注册发现一样,初始化clientConfig和serverConfig的配置,略

创建动态配置客户端

configClient, _ := clients.NewConfigClient(vo.NacosClientParam{ClientConfig:&cc,ServerConfigs: sc,},)

拉取指定data-id的配置

config, _ := ConfigClient.GetConfig(vo.ConfigParam{DataId: ServiceName,})fmt.Printf("config is " + config)

我这边写了一个rest的接口,可以指定获取某个具体配置的值

// 初始化服务端func ServerSetup() {r := gin.Default()r.GET("/hello/:name", hello)r.GET("/config", getSpecifiedConfig)r.Run(":8777")}// 获取指定的配置func getSpecifiedConfig(c *gin.Context) {param := c.DefaultQuery("name", "")config, _ := ConfigClient.GetConfig(vo.ConfigParam{DataId: ServiceName,})fmt.Printf("config is " + config)// 解析YAML数据var data map[string]interface{}err := yaml.Unmarshal([]byte(config), &data)if err != nil {fmt.Println("error unmarshalling YAML", err)}value := getValue(data, param)c.String(http.StatusOK, "param [ "+param+" ] value is "+value)}func getValue(data map[string]interface{}, keyPath string) string {keys := strings.Split(keyPath, ".")var value interface{} = datafor _, key := range keys {if v, ok := value.(map[string]interface{}); ok {value = v[key]} else {return ""}}if v, ok := value.(string); ok {return v}return fmt.Sprintf("%v", value)}

配置client-go如下

my:name: yuanage: 27city: Nanjing

调用请求 http://localhost:8777/config” />

结语

参考地址:https://github.com/nacos-group/nacos-sdk-go

代码地址:https://github.com/yzh19961031/blogDemo/tree/master/go-nacos