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

基于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{} = data
	for _, 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: yuan
  age: 27
  city: 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

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

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

相关文章

WhatsApp API号注册平台价格对比:帮你选择性价比最高的服务

WhatsApp作为全球使用人数众多的即时通讯工具,推出的API服务为企业提供了强大的客户互动能力。然而面对众多提供WhatsApp API号注册的平台,企业在选择时很容易感到困惑。这篇文章将会对目前市面上比较主流的WhatsApp API号注册平台进行价格对比&#xff…

三、加载路径对桁架的影响

加载路径: \color{green}加载路径: 加载路径: 材料在受力时所经历的应力和应变变化路径。在塑性力学中,加载路径对材料的变形行为和力学性能有着重要影响。 案例分析 \color{green}案例分析 案例分析 如图所示,理想弹…

Linux——基础IO

目录 前言 C语言文件操作 stdin & stdout & stderr 系统文件IO open close write read 文件描述符fd 重定向 dup2 Linux下一切皆文件 缓冲区 简易缓冲区 文件系统 磁盘 创建文件 删除文件 查看文件 软硬链接 软链接 硬链接 动静态库 静态库 …

40. 【Linux教程】文件系统介绍

从本小节我们将要开始 Linux 中的文件系统,在 Linux 系统中,文件系统都是基于硬盘创建的,Linux 系统支持多种不同类型的文件系统管理文件和目录,本小节介绍几种基本常见的文件系统。 Linux 文件系统中的文件是数据的集合&#xf…

算法沉淀——动态规划之两个数组的 dp(上)(leetcode真题剖析)

算法沉淀——动态规划之两个数组的 dp 01.最长公共子序列02.不相交的线03.不同的子序列04.通配符匹配 01.最长公共子序列 题目链接:https://leetcode.cn/problems/longest-common-subsequence/ 给定两个字符串 text1 和 text2,返回这两个字符串的最长 …

医院床旁交互系统概述 -智慧护理-全视通

全视通床旁交互系统是一种先进的医疗信息技术解决方案,旨在改善病患与医疗团队之间的沟通与交流。该系统通过集成多种高科技设备,为病患在病床边提供了一站式的信息交互平台,从而优化了医疗服务流程,提升了医疗体验。 首先&#x…

C++引入

引用不是新定义一个变量,而是给已经存在的变量取一个别名,编译器不会为了引用变量开辟内存空间,它和它引用的变量公用同一块内存空间。如李白被称为诗仙。李白和诗仙都是同一个人。 语法: 类型& 引用变量名(对象名)引用实体; 特性: 引用在…

coppeliasi4.0版本中使用循迹小车跟随路径时问题汇总

加入循迹小车,设置好路径后运行 发现报错,小车直线行驶不跟随设置好的路径移动 观察仿真中可知小车左右中传感器并不工作全是黑色,观察报错语句 Lua runtime error: [string "CUSTOMIZATION SCRIPT LeftSensor"]:12: Invalid hand…

基于SpringBoot的医护人员排班系统(代码+数据库+文档)

** 🍅点赞收藏关注 → 私信领取本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目 希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅** 目录 一、研究背景 1.…

Vue 项目重复点击菜单刷新当前页面

需求:“在当前页面点击当前页面对应的菜单时,也能刷新页面。” 由于 Vue 项目的路由机制是路由不变的情况下,对应的组件是不重新渲染的。所以重复点击菜单不会改变路由,然后页面就无法刷新了。 方案一 在vue项目中,…

探索Python编程世界:从入门到精通

一.Python 从入门到精通 随着计算机科学的发展,编程已经成为了一种必备的技能。而 Python 作为一种简单易学、功能强大的编程语言,越来越受到人们的喜爱。本文将为初学者介绍 Python 编程的基础知识,帮助他们踏入 Python 编程的大门&#xf…

网络安全: Kali Linux 使用 MSF 渗透测试

目录 一、实验 1.环境 2.登录MSF(Metasploit Framework)控制台 3.MSF初始化 4.MSF 管理工作区 5.Kali Linux (2024.1) 对Windows server 进行网址目录扫描 6.Kali Linux (2022.4) 对Ubuntu进行网址目录扫描 7.Kali Linux (2024.1) 对Windows ser…

Java 的七种垃圾收集器

了解 Java 中的内存管理。 用 C 或 C 这样的编程语言写一个应用时,需要编写代码来销毁内存中不再需要的对象。当应用程序扩展得越来越复杂时,未使用对象被忽略释放的可能性就越大。这会导致内存泄露,最终内存耗尽,在某个时刻将没有…

Matlab/Simulink验证MAB建模规范

前言 为什么MAB? MathWorks Advisory Board(MAB)是由MathWorks公司设立的一个咨询委员会,旨在提供有关MathWorks产品和服务的反馈、建议和意见。MAB成员通常是来自学术界、工业界和其他领域的专业人士,他们在各自领域…

【Sql Server】C#通过拼接代码的方式组合添加sql语句,会出现那些情况,参数化的作用

欢迎来到《小5讲堂》,大家好,我是全栈小5。 这是《Sql Server》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对…

【C++从0到王者】第四十七站:最小生成树

文章目录 一、最小生成树的概念1.概念2.最小生成树的构造方法 二、Kruskal算法1.算法思想2.代码实现 三、Prim算法1.算法思想2.代码实现3.试试所有节点为起始点 一、最小生成树的概念 1.概念 连通图:在无向图中,若从顶点v1到顶点v2有路径,则…

这本书太好了!150页就能让你上手大模型应用开发

如果问个问题:有哪些产品曾经创造了伟大的奇迹?ChatGPT 应该会当之无愧入选。 仅仅发布 5 天,ChatGPT 就吸引了 100 万用户——当然,数据不是关键,关键是其背后的技术开启了新的 AI 狂潮,成为技术变革的点火…

强势改进!基于改进多目标灰狼算法的冷热电联供型微电网运行优化程序代码!

适用平台:MatlabYalmipCplex 程序以综合能源系统/微电网为研究对象,将微电网的运行费用和环境污染成本作为优化目标,考虑冷热电负荷和设备运行要求的约束,建立的微电网的多目标优化模型,使用改进多目标灰狼算法算法进…

有个朋友被骗了,大家要擦亮眼睛

1.引言 大家好,我是Leo哥🫣🫣🫣,昨天凌晨有个粉丝朋友找到Leo哥,咨询一些问题,现在的朋友们真卷呐,大半夜还在挑灯夜战。可无奈Leo哥12点之前已经睡了,身体为重&#xf…

智慧社区养老:Java与SpringBoot的技术融合

✍✍计算机毕业编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java、…