Go微服务: Nacos的搭建和基础API的使用

news2024/11/23 17:39:47

Nacos 概述

  • 文档:https://nacos.io/docs/latest/what-is-nacos/
  • 搭建:https://nacos.io/docs/latest/quickstart/quick-start-docker/
  • 有很多种搭建方式,我们这里使用 docker 来搭建

Nacos 的搭建

  • 这里,我们选择单机模式,简单些,仅仅做一些示例
  • 创建 docker-compose.yaml
    version: "3.8"
    services:
      nacos:
        image: nacos/nacos-server:latest
        container_name: nacos-standalone
        env_file:
          - ./config.env
        volumes:
          - ./standalone-logs/:/home/nacos/logs
        ports:
          - "8848:8848"
          - "9848:9848"
        restart: always
    
    • 这里我们可知,依赖 standalone-logs 目录和 config.env 文件
    • 前者创建即可,后者我们来看下
  • config.env
    PREFER_HOST_MODE=hostname  
    MODE=standalone  
    NACOS_AUTH_IDENTITY_KEY=serverIdentity  
    NACOS_AUTH_IDENTITY_VALUE=security  
    NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789
    
  • 以上这些,都是基于官方文档中,改造过来的
  • 先拉取镜像 $ docker pull nacos/nacos-server
  • 运行 $ docker-compose up -d
  • 访问:http://127.0.0.1:8848/nacos/
  • 用户名/密码:nacos/nacos, 登录后可进行自行修改
  • 创建一个命名空间, 命名为: dev,创建完成后会生成一个命名空间ID
  • 在配置列表的 dev 下,新建配置
    • Data ID: test.json
    • Group: tt
    • 配置内容: { "name": "abc" }

Nacos V2 功能展示

  • 文档:https://github.com/nacos-group/nacos-sdk-go
  • 文档上面有相关示例和说明

1 )注册服务和获取服务

package main

import (
	"fmt"
	"time"

	"github.com/nacos-group/nacos-sdk-go/v2/clients"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"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 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 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)
}

func main() {
	//create ServerConfig
	sc := []constant.ServerConfig{
		*constant.NewServerConfig("127.0.0.1", 8848, constant.WithContextPath("/nacos")),
	}

	//create ClientConfig
	cc := *constant.NewClientConfig(
		constant.WithNamespaceId("ff2e8758-33c1-4a88-8005-142cbee91be9"),
		constant.WithTimeoutMs(5000),
		constant.WithNotLoadCacheAtStart(true),
		constant.WithLogDir("nacos/log"),
		constant.WithCacheDir("nacos/cache"),
		constant.WithLogLevel("debug"),
	)

	// create naming client
	client, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &cc,
			ServerConfigs: sc,
		},
	)

	if err != nil {
		panic(err)
	}

	// Register
	registerServiceInstance(client, vo.RegisterInstanceParam{
		Ip:          "127.0.0.1",
		Port:        8848,
		ServiceName: "demo.go",
		GroupName:   "tt",
		// ClusterName: "cluster-a",
		Weight:    10,
		Enable:    true,
		Healthy:   true,
		Ephemeral: true,
		Metadata:  map[string]string{"idc": "shanghai"},
	})

	time.Sleep(1 * time.Second)

	//Get service with serviceName, groupName, clusters
	getService(client, vo.GetServiceParam{
		ServiceName: "demo.go",
		GroupName:   "tt",
		// Clusters:    []string{"cluster-a"},
	})

	//wait for client pull change from server
	time.Sleep(3 * time.Second)

	//GeAllService will get the list of service name
	//NameSpace default value is public.If the client set the namespaceId, NameSpace will use it.
	//GroupName default value is DEFAULT_GROUP
	getAllService(client, vo.GetAllServiceInfoParam{
		GroupName: "tt",
		PageNo:    1,
		PageSize:  10,
	})
	time.Sleep(300000 * time.Second)
}
  • 上面示例实现了注册服务,获取服务的示例, 后续如果需要,可以进行封装
  • 效果如下

可见注册和获取成功

2 )服务相关的其他功能

2.1 批量注册示例

//BatchRegister
batchRegisterServiceInstance(client, vo.BatchRegisterInstanceParam{
	ServiceName: "demo.go",
	GroupName:   "tt",
	Instances: []vo.RegisterInstanceParam{{
		Ip:          "127.0.0.1",
		Port:        8848,
		Weight:      10,
		Enable:      true,
		Healthy:     true,
		Ephemeral:   true,
		// ClusterName: "cluster-a",
		Metadata:    map[string]string{"idc": "shanghai"},
	}, {
		Ip:          "127.0.0.1",
		Port:        8848,
		Weight:      7,
		Enable:      true,
		Healthy:     true,
		Ephemeral:   true,
		// ClusterName: "cluster-a",
		// Metadata:    map[string]string{"idc": "shanghai"},
	}},
})

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)
}

2.2 更新服务

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)
}

updateServiceInstance(client, vo.UpdateInstanceParam{
	Ip:          "127.0.0.1", //update ip
	Port:        8848,
	ServiceName: "demo.go",
	GroupName:   "tt",
	// ClusterName: "cluster-a",
	Weight:      10,
	Enable:      true,
	Healthy:     true,
	Ephemeral:   true,
	Metadata:    map[string]string{"idc": "beijing1"}, //update metadata
})

2.3 订阅服务和取消服务订阅

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

func unSubscribe(client naming_client.INamingClient, param *vo.SubscribeParam) {
	client.Unsubscribe(param)
}

//Subscribe key=serviceName+groupName+cluster
//Note:We call add multiple SubscribeCallback with the same key.
subscribeParam := &vo.SubscribeParam{
	ServiceName: "demo.go",
	GroupName:   "tt",
	SubscribeCallback: func(services []model.Instance, err error) {
		fmt.Printf("callback return services:%s \n\n", util.ToJsonString(services))
	},
}
subscribe(client, subscribeParam)

// UnSubscribe
unSubscribe(client, subscribeParam)

2.4 获取服务实例

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)
}

//SelectAllInstance
//GroupName=DEFAULT_GROUP
selectAllInstances(client, vo.SelectAllInstancesParam{
	ServiceName: "demo.go",
	GroupName:   "tt",
	Clusters:    []string{"cluster-a"},
})


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)
}

//SelectInstances only return the instances of healthy=${HealthyOnly},enable=true and weight>0
//ClusterName=DEFAULT,GroupName=DEFAULT_GROUP
selectInstances(client, vo.SelectInstancesParam{
	ServiceName: "demo.go",
	GroupName:   "tt",
	// Clusters:    []string{"cluster-a"},
	HealthyOnly: true,
})

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)
}

//SelectOneHealthyInstance return one instance by WRR strategy for load balance
//And the instance should be health=true,enable=true and weight>0
//ClusterName=DEFAULT,GroupName=DEFAULT_GROUP
selectOneHealthyInstance(client, vo.SelectOneHealthInstanceParam{
	ServiceName: "demo.go",
	GroupName:   "tt",
	// Clusters:    []string{"cluster-a"},
})

3 ) 配置相关

  • 先在 nacos 的配置文件中,进行数据的配置
  • 再进行编码获取

    package main
    
    import (
    	"fmt"
    	"time"
    
    	"github.com/nacos-group/nacos-sdk-go/v2/clients"
    	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
    	"github.com/nacos-group/nacos-sdk-go/v2/vo"
    )
    
    func main() {
    	//create ServerConfig
    	sc := []constant.ServerConfig{
    		*constant.NewServerConfig("127.0.0.1", 8848, constant.WithContextPath("/nacos")),
    	}
    	//create ClientConfig
    	cc := *constant.NewClientConfig(
    		constant.WithNamespaceId("ff2e8758-33c1-4a88-8005-142cbee91be9"),
    		constant.WithTimeoutMs(5000),
    		constant.WithNotLoadCacheAtStart(true),
    		constant.WithLogDir("nacos/log"),
    		constant.WithCacheDir("nacos/cache"),
    		constant.WithLogLevel("debug"),
    	)
    	// create config client
    	client, err := clients.NewConfigClient(
    		vo.NacosClientParam{
    			ClientConfig:  &cc,
    			ServerConfigs: sc,
    		},
    	)
    	if err != nil {
    		panic(err)
    	}
    
    	//get config
    	content, err := client.GetConfig(vo.ConfigParam{
    		DataId: "test.json",
    		Group:  "tt",
    	})
    	fmt.Println("GetConfig,config :" + content)
    	time.Sleep(100000000 * time.Second)
    }
    
  • 查看输出

4 )配置相关的其他功能

4.1 监听配置

//Listen config change,key=dataId+group+namespaceId.
err = client.ListenConfig(vo.ConfigParam{
	DataId: "test.json",
	Group:  "tt",
	OnChange: func(namespace, group, dataId, data string) {
		fmt.Println("config changed group:" + group + ", dataId:" + dataId + ", content:" + data)
	},
})

4.2 移除监听

//cancel config change
err = client.CancelListenConfig(vo.ConfigParam{
	DataId: "test.json",
	Group:  "tt",
})

4.3 发布配置

	_, err = client.PublishConfig(vo.ConfigParam{
		DataId:  "test-data",
		Group:   "test-group",
		Content: "hello world!",
	})
	if err != nil {
		fmt.Printf("PublishConfig err:%+v \n", err)
	}

4.4 删除配置

_, err = client.DeleteConfig(vo.ConfigParam{
	DataId:  "test-data",
	Group:   "test-group",
})

4.5 搜索配置

searchPage, _ := client.SearchConfig(vo.SearchConfigParam{
	Search:   "blur",
	DataId:   "", // 自定义
	Group:    "", // 自定义
	PageNo:   1,
	PageSize: 10,
})
fmt.Printf("Search config:%+v \n", searchPage) // 格式:&{TotalCount:0 PageNumber:1 PagesAvailable:0 PageItems:[]}

总结

  • 以上是官方提供的一些 example 的拆解,目前只是拿出来分析
  • 在真实使用的场合中,需要进行合适的封装来达到生产使用

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java实现图书系统源码

建包和类: Book Book: package Book;public class Book {private String name;private String author;private int price;private String type;private boolean isBorrowed;public Book(String name, String author, int price, String type) {this.name name;this.author …

【Qnx 】Qnx IPC通信PPS

Qnx IPC通信PPS Qnx自带PPS服务,PPS全称Persistent Publish/Subscribe Service,就是常见的P/S通信模式。 Qnx PPS的通信模式是异步的,Publisher和Subscriber也无需关心对方是否存在。 利用Qnx提供的PPS服务,Publisher可以通知多…

OrangePi KunPengPro | 开发板开箱测评之学习与使用

OrangePi KunPengPro | 开发板开箱测评之学习与使用 时间:2024年5月23日20:51:12 文章目录 OrangePi KunPengPro | 开发板开箱测评之学习与使用概述1.参考2.资料、工具3.使用3-1.通过串口登录系统3-2.通过SSH登录系统3-3.安装交叉编译工具链3-4.复制文件到设备3-5.第…

Android 使用 ActivityResultLauncher 申请权限

前面介绍了 Android 运行时权限。 其中,申请权限的步骤有些繁琐,需要用到:ActivityCompat.requestPermissions 函数和 onRequestPermissionsResult 回调函数,今天就借助 ActivityResultLauncher 来简化书写。 步骤1:创…

攻防世界[GoodRe]

攻防世界[GoodRe] 学到知识: 逆向的精髓:三分懂,七分蒙。TEA 算法快速识别(蒙): 数据处理的形式:进入加密时的数据和加密结束后的数据,处理时数据的分组等等,都能用来…

AtCoder Beginner Contest 355 A~F

A.Who Ate the Cake?(思维) 题意 已知有三个嫌疑人,有两个证人,每个证人可以指出其中一个嫌疑人不是罪犯,如果可以排除两个嫌疑人来确定犯人,输出犯人的身份,如果无法确定,输出"-1"。 分析 …

Pytorch(Overview)

目标 如何利用pytorch完成学习系统? 理解神经网络(neural networks)和深度学习(deep learning)基础。 需要了解线性代数和概率论数理统计等相关关系,和python编程语言。 讨论理解 到底什么是human int…

vue3项目+TypeScript前端项目 ———— elemnet-plus,svg图标配置,sass,mock数据

一.集成element-plus 官网地址 安装 pnpm install element-plus 引入 // main.ts import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import App from ./App.vueconst app createApp(App)app.use(ElementPlus) app.…

esp32-idf 开发踩坑记录

现象 直接使用原始命令编译idf.py build 但是提示idf 版本错误 卸载旧版本 编译出错build 问题 然后删除编译文件后,重新编译,还是出错 解决方法1 最后发现是因为项目所在文件夹有中文目录,把项目迁移到英文目录后,重新编译&a…

重学java 46.集合 ① Collection集合

事常与人违,事总在人为 —— 24.5.26 集合 知识导航 1.集合的特点以及作用 2.使用collection接口中的方法 3.使用迭代器迭代集合 4.ArrayList以及LinkedList的使用 5.使用增强for遍历集合 一、单列集合框架的介绍 1.长度可变的容器:集合 2.集合的特点 a.…

TCP/IP协议(一)

一.报文和协议 协议有什么作用?协议定义通信实体间所交换报文的格式和次序,以及在报文发送和/或接收或者其他事件方面所采取的行动(响应)。 什么是报文?指在网络中传输的数据单元,网络通讯的基本单位。(HTTP报文、TCP报…

录屏技巧:win11怎么录屏?这5个电脑录屏方法快速了解下

无论您是想进行工作演示还是游戏直播,电脑录屏都有很大帮助。录制 Win 11 屏幕在很多方面都非常有效,因为它能让事情变得更简单。但 Win11怎么录屏呢?如果您仍有困惑,请查看本篇文章中列出的5个方法。在本文中,我们列出…

Python 获取当前IP地址(爬虫代理)

Python 获取当前IP地址(爬虫代理) 在Python中,获取当前的公网IP地址通常涉及到发送一个请求到外部服务,因为本地IP地址通常只在你的私有网络内部是可见的,而公网IP地址是由你的ISP(互联网服务提供商&#x…

猫抓(cat-catch)插件的常规用法

目录 1.1、前言1.2、抓取图片资源1.3、抓取音频资源1.4、抓取视频资源 1.1、前言 本文将介绍利用猫抓(cat-catch)插件如下抓取网页上的图片、音频、视频等资源,猫抓(cat-catch)插件的安装及设置请参考推荐一款媒体影音…

【网络技术】【Kali Linux】Wireshark嗅探(十五)SSDP(简单服务发现协议)报文捕获及分析

往期 Kali Linux 上的 Wireshark 嗅探实验见博客: 【网络技术】【Kali Linux】Wireshark嗅探(一)ping 和 ICMP 【网络技术】【Kali Linux】Wireshark嗅探(二)TCP 协议 【网络技术】【Kali Linux】Wireshark嗅探&…

picamera配opencv做发现移动物体后录像50秒

本来是想配合上一篇写的测距传感器数据打开摄像头录制个50秒实时画面,后来这个测距传感器(因为我是歪用,用来识别范围内的移动物体)给的数据,false alarming还是太高了。于是想到使用本人之前深恶痛绝的opencv来试一试…

如何使用Kimi和通义千问辅助快速阅读论文

说明 上一篇博文我介绍了最新阅读的一篇TinyML的论文。我有个习惯就是使用Google Schloar跟踪当前最新的论文,只要在Google Schloar中设置好关键字,它每天就把最新的相关论文的链接和摘要发送到邮箱里面。不过现在论文太多了,每篇都认真读取…

分享免费的手机清理软件app,一款国外开发的手机清理神器,让手机再战两年!

手机内存越来越大,软件却越来越占地方,就像微信这家伙,轻轻松松就吃了十几个G! 害得阿星8128G的手机,本来想换新的,结果用了这款Avast Cleanup软件,瞬间感觉手机还能再战两年! 注意…

让大模型变得更聪明三个方向

让大模型变得更聪明三个方向 随着人工智能技术的飞速发展,大模型在多个领域展现出了前所未有的能力,但它们仍然面临着理解力、泛化能力和适应性等方面的挑战。那么,如何让大模型变得更聪明呢? 方向一:算法创新 1.1算…

Generative Action Description Prompts for Skeleton-based Action Recognition

标题:基于骨架的动作识别的生成动作描述提示 源文链接:https://openaccess.thecvf.com/content/ICCV2023/papers/Xiang_Generative_Action_Description_Prompts_for_Skeleton-based_Action_Recognition_ICCV_2023_paper.pdfhttps://openaccess.thecvf.c…