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

news/2024/4/24 18:27:44/文章来源:https://blog.csdn.net/qq_32238611/article/details/136455745

基于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
@SpringBootApplication
public 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?name=my.name,http://localhost:8777/config?name=my.age ok
在这里插入图片描述
在这里插入图片描述

结语

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_998124.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch:向量相似度计算 - 可笑的速度

作者:Chris Hegarty 任何向量数据库的核心都是距离函数,它确定两个向量的接近程度。 这些距离函数在索引和搜索期间执行多次。 当合并段或在图表中导航最近邻居时,大部分执行时间都花在比较向量的相似性上。 对这些距离函数进行微观优化是值…

MySQL 的基础操作

数据库的基础操作 1. 库操作2. 表的操作3. 数据类型 数据库是现代应用程序中至关重要的组成部分,通过数据库管理系统(DBMS)存储和管理数据。 1. 库操作 创建数据库 创建数据库是开始使用数据库的第一步。下面是一些常见的创建数据库的示例&a…

Redis与 Memcache区别

Redis与 Memcache区别 1 , Redis 和 Memcache 都是将数据存放在内存中,都是内存数据库。不过 Memcache 还可用于缓存 其他东西,例如图片、视频等等。 2 , Memcache 仅支持key-value结构的数据类型,Redis不仅仅支持简单的key-value类型的数据&…

【Vue】探究 Vue 2 与 Vue 3 生命周期:变化与延续

💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…

springboot245科研项目验收管理系统

科研项目验收管理系统 摘 要 使用旧方法对科研项目信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在科研项目信息的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问题。这次…

docker学习进阶

一、dockerfile解析 官方文档: Dockerfile reference | Docker Docs 1.1、dockfile是什么? dockerfile是用来构建docker镜像的文本文件,由一条条构建镜像所需的指令和参数构成的脚本。 之前我们介绍过通过具体容器反射构建镜像(docker comm…

SpringBoot+Ajax+redis实现隐藏重要接口地址

🏡浩泽学编程:个人主页 🔥 推荐专栏:《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 🛸学无止境,不骄不躁,知行合一 文章目录 …

【Pytorch】论文复现 Vision Transformer (ViT)

文章目录 0. 进行设置1. 获取数据2. 创建Dataset和DataLoader3. 复现 ViT 论文:概述4. Equation 1: 将数据拆分为 patch 并创建类、位置和 patch 嵌入5. Equation 2: Multi-Head Attention (MSA)6. Equation 3: Multilayer Perceptron (MLP)7. 创建 Transformer 编码…

双链表的实现(数据结构)

链表总体可以分为三大类 一、无头和有头 二、单向和双向 三、循环和不循环 从上面分类得知可以组合成8种不同类型链表,其中单链表最为简单,双联表最为复杂,两种链表都实现后其余链表都不成问题。 我们前期博客已将完成了单向无头不循环链表…

【Python】进阶学习:pandas--read_excel()函数的基本使用

【Python】进阶学习:pandas–read_excel()函数的基本使用 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程👈 希…

ABAP 函数模块的异常抛出

函数模块的异常抛出 *&---------------------------------------------------------------------* *& Report Z_TEST_EXCEPTIONS_LHY *&---------------------------------------------------------------------* *& TYPE:Report *& Descriptio…

浅显易懂:WinForms、WPF和Electron的区别和优缺点

在开发桌面应用的时候,WinForms、WPF和Electron是绕不过去的三个技术栈,本文就详细据介绍了三者的区别和优缺点,帮助老铁们做个抉择。 一、winform wpf Electron 三者区别 WinForms、WPF和Electron是三种不同的框架和技术,用于开…

RabbitMQ架构详解

文章目录 概述架构详解核心组件虚拟主机(Virtual Host)RabbitMQ 有几种广播类型 概述 RabbitMQ是⼀个高可用的消息中间件,支持多种协议和集群扩展。并且支持消息持久化和镜像队列,适用于对消息可靠性较高的场合 官网https://www.…

零难度!台式电脑如何连接蓝牙耳机?简单几步完成

在当今数字化的生活中,蓝牙耳机因其无线便携性和高品质音效,成为了许多人喜爱的音频配件。对于台式电脑用户而言,或许一开始连接蓝牙耳机会让人感到陌生,但实际上,这一过程远比想象中简单。台式电脑如何连接蓝牙耳机&a…

常用css样式大全以及css属性代码大全

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 往期热门专栏回顾 专栏…

Ubuntu中,重命名文件夹下所有带有空格的文件名,将空格替换为其他字符

Ubuntu中,重命名文件夹下所有带有空格的文件名,将空格替换为其他字符 问题 运行网络训练报错,原因是数据集文件名存在空格,导致读取失败 解决方法 在Ubuntu中,您可以使用终端和一些简单的命令来重命名文件夹下所有…

啤酒:精酿啤酒与炖汤的温暖整合

在寒冷的冬夜,没有什么比一碗热腾腾的炖汤更能温暖人心。而当炖汤与Fendi Club啤酒相遇,这种温暖便达到了理想。它们在舌尖上演绎了一场美妙的交响曲,让人感受到无尽的舒适与满足。 Fendi Club啤酒,以其与众不同的麦香和细腻的泡沫…

微信小程序用户隐私保护指引设置

场景:开发小程序时,有时候需要获取用户隐私信息,在提交小程序审核时,需要填写一份隐私保护协议,经常由于填写不规范导致审核不通过,在网上找到了一份模块可供参考 步骤:小程序后台-》设置-》服…

一键清除JavaScript代码中的注释:使用正则表达式实现

这个正则表达式可以有效地匹配 JavaScript 代码中的各种注释&#xff0c;并且跳过了以 http: 或 https: 开头的链接。 /\/\*[\s\S]*?\*\/|\/\/[^\n]*|<!--[\s\S]*?-->|(?<!http:|https:)\/\/[^\n]*/gvscode 实战&#xff0c;ctrlF 调出查找替换工具&#xff0c;点…

在vue3中封装一个文件上传组件

因为在使用场景中可能会用到多个文件上传&#xff0c;如果每个都一个一个写慢慢就堆成ss了&#xff0c; 使用方法直接在父组件中v-model就可以简单使用 话不多说&#xff0c;直接上代码 <template><el-upload v-model:file-list"fileList" class"upl…