当前位置: 首页 > news >正文

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

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:latestcontainer_name: nacos-standaloneenv_file:- ./config.envvolumes:- ./standalone-logs/:/home/nacos/logsports:- "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 mainimport ("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 ServerConfigsc := []constant.ServerConfig{*constant.NewServerConfig("127.0.0.1", 8848, constant.WithContextPath("/nacos")),}//create ClientConfigcc := *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 clientclient, err := clients.NewNamingClient(vo.NacosClientParam{ClientConfig:  &cc,ServerConfigs: sc,},)if err != nil {panic(err)}// RegisterregisterServiceInstance(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, clustersgetService(client, vo.GetServiceParam{ServiceName: "demo.go",GroupName:   "tt",// Clusters:    []string{"cluster-a"},})//wait for client pull change from servertime.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_GROUPgetAllService(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 ipPort:        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 mainimport ("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 ServerConfigsc := []constant.ServerConfig{*constant.NewServerConfig("127.0.0.1", 8848, constant.WithContextPath("/nacos")),}//create ClientConfigcc := *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 clientclient, err := clients.NewConfigClient(vo.NacosClientParam{ClientConfig:  &cc,ServerConfigs: sc,},)if err != nil {panic(err)}//get configcontent, 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 的拆解,目前只是拿出来分析
  • 在真实使用的场合中,需要进行合适的封装来达到生产使用

相关文章:

  • 云计算-使用Java访问S3 (Accessing S3 using Java)
  • 爬虫案例-亚马逊反爬流程分析梳理(验证码突破)(x-amz-captcha)
  • C# 集合(三) —— Stack/BitArray类
  • 【C语言回顾】编译和链接
  • 云部署最简单python web
  • 【SpringBoot】SpringBoot中防止接口重复提交(单机环境和分布式环境)
  • sqlites数据库读取,仅适用于数据少的数据库查询【改进版】
  • RedisTemplateAPI:List
  • 经常碰到的20个等待事件
  • Android firebase消息推送集成 FCM消息处理
  • I.MX6ULL Linux C语言开发环境搭建(点灯实验)
  • Python项目:数据可视化_下载数据【笔记】
  • hive初始化失败报错:Error: Duplicate key name ‘PCS_STATS_IDX‘ (state=42000,code=1061)
  • 2024年弘连网络FIC大会竞赛题线下决赛题
  • vue-img-cutter 图片裁剪详解
  • 时间复杂度分析经典问题——最大子序列和
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 【译】理解JavaScript:new 关键字
  • Android系统模拟器绘制实现概述
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • CEF与代理
  • IDEA常用插件整理
  • java中具有继承关系的类及其对象初始化顺序
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • React-生命周期杂记
  • Redux系列x:源码分析
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 程序员最讨厌的9句话,你可有补充?
  • 代理模式
  • 服务器从安装到部署全过程(二)
  • 构建二叉树进行数值数组的去重及优化
  • 关于List、List?、ListObject的区别
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 使用common-codec进行md5加密
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 思否第一天
  • 为什么要用IPython/Jupyter?
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • 回归生活:清理微信公众号
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​TypeScript都不会用,也敢说会前端?
  • ​力扣解法汇总946-验证栈序列
  • # Panda3d 碰撞检测系统介绍
  • $.ajax()参数及用法
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (7)STL算法之交换赋值
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (强烈推荐)移动端音视频从零到上手(下)
  • (三)mysql_MYSQL(三)
  • (四)模仿学习-完成后台管理页面查询
  • (正则)提取页面里的img标签
  • (转载)利用webkit抓取动态网页和链接