nacos做注册注册中心go语言实战教程(服务的注册与获取)

背景

随着访问量的逐渐增大,单体应用结构渐渐不满足需求,在微服务出现之后引用被拆分为一个个的服务,服务之间可以互相访问。初期服务之间的调用只要知道服务地址端口即可,而服务会出现增减、故障、升级等变化导致端口和ip也变化,被调用者的变化也会导致调用者变化。这样很不方便。

注册中心就诞生了,注册中心就像DNS服务器,注册中心是C/S架构,服务调用者通过Client调用服务名称,被调用者通过Client上传服务名称和ip并发送心跳检测该服务的健康状态。注册中心为server端保存服务名称和服务的ip地址及端口,这样不论被调用者服务如何变化,只要服务名称不变,调用者都不说影响。

常见的注册中心:

  • etcd
  • consul
  • eureka
  • nacos
  • zookeeper

go实现nacos注册中心

Nacos的核心API中定义了两个接口NamingService和ConfigService。服务注册与发现围绕着NamingService展开,而配置管理则围绕着ConfigService展开。

Nacos的4个核心特性:服务发现和服务健康监测、动态配置服务、动态DNS服务、服务及其元数据管理。

在这里插入图片描述

作为注册中心的功能来说,Nacos提供的功能与其他主流框架很类似,基本都是围绕服务实例注册、实例健康检查、服务实例获取这三个核心来实现的。

在这里插入图片描述

nacos注册中心基本流程:

  • 服务实例启动将自身注册到Nacos注册中心,随后维持与注册中心的心跳;
  • 心跳维持策略为每5秒向Nacos Server发送一次心跳,并携带实例信息(服务名、实例IP、端口等);
  • Nacos Server也会向Client主动发起健康检查,支持TCP/Http;
  • 15秒内无心跳且健康检查失败则认为实例不健康,如果30秒内健康检查失败则剔除实例;
  • 服务消费者通过注册中心获取实例,并发起调用;

其中服务发现支持两种场景:第一,服务消费者直接向注册中心发送获取某服务实例的请求,注册中心返回所有可用实例,但一般不推荐此种方式;第二、服务消费者向注册中心订阅某服务,并提交一个监听器,当注册中心中服务发生变化时,监听器会收到通知,消费者更新本地服务实例列表,以保证所有的服务均可用。

nacos数据模型

Nacos数据模型的Key由三元组唯一确定,Namespace默认是空串,公共命名空间(public),分组默认是DEFAULT_GROUP

在这里插入图片描述
在这里插入图片描述Nacos基于namespace的设计是为了做多环境以及多租户数据(配置和服务)隔离的。如果用户有多套环境(开发、测试、生产等环境)。

一个服务模型如下:

在这里插入图片描述

在这里插入图片描述

图片来源官方网站:nacos.io

服务注册

go nacos SDK

首先需要有一个rpc框架例如Zero,kit,grpc,kitex等,生成rpc服务的代码来模拟服务注册与获取。如下所示使用kitex框架生成rpc service,这里使用nacos官方go语言的sdk和rpc框架无关联,任选框架即可。

本项目demo

server端:
在这里插入图片描述

client直接连接:

import ("github.com/cloudwego/kitex/client""order/rpc/orderclient"
)func Client() orderclient.RPCClient {rpcClient, err := orderclient.NewRPCClient("orderserver", client.WithHostPorts("192.168.5.118:10000"))if err != nil {panic(err)}return rpcClient
}

在上述的代码中添加nacos配置中心,首先区别存在一个运行的nacos服务,如下:

在这里插入图片描述

go连接nacos实现服务注册参考go-nacos-example

公网域名连接参考

包装工具库简化连接注册配置的方法

服务注册在启动类连接nacos注册中心,注册服务,如下:

package mainimport (..."github.com/flairamos/go-component/nacos"...
)
func main() {opts := kitexInit()svr := orderservice.NewServer(new(OrderServiceImpl), opts...)param := vo.RegisterInstanceParam{Ip:          "127.0.0.1",Port:        8848,Enable:      true,Healthy:     true,Weight:      10,Metadata:    map[string]string{"version": "1.0"},ClusterName: "test",GroupName:   "dev_food_platform",Ephemeral:   true,ServiceName: "test_app",}config := nacos.DefaultClient("public", "mysql", "dev_food_platform", nil)service := nacos.RegisterService(config, param)if !service {log.Println("nacos register failed")return}log.Println("nacos register success")err := svr.Run()if err != nil {klog.Error(err.Error())}
}

代码中的nacos是小编封装的包,sdk源码参考nacos-go-sdk,如下:

// 官方源码
success, err := namingClient.RegisterInstance(vo.RegisterInstanceParam{Ip:          "10.0.0.11",Port:        8848,ServiceName: "demo.go",Weight:      10,Enable:      true,Healthy:     true,Ephemeral:   true,Metadata:    map[string]string{"idc":"shanghai"},ClusterName: "cluster-a", // 默认值DEFAULTGroupName:   "group-a",   // 默认值DEFAULT_GROUP
})

启动服务:
在这里插入图片描述
nacso注册中心查看:
在这里插入图片描述

注册配置如下:

"github.com/nacos-group/nacos-sdk-go/vo"vo.RegisterInstanceParam{Ip:          "127.0.0.1",Port:        8848,Enable:      true,Healthy:     true,Weight:      10,Metadata:    map[string]string{"version": "1.0"},ClusterName: "test",GroupName:   "dev.food_platform",Ephemeral:   true,ServiceName: "test_app",}

在这里插入图片描述
在上述过程中服务已经注册到nacso注册中心了,完成了第一步。

服务健康检查

nacos服务健康检查是客户端进行的,通过配置来开启,无需手敲发送心跳,判断活跃,更新服务,剔除亚健康实例等代码。

Nacos中临时实例会定时发送心跳维持活性,基本的健康检查流程基本如下:Nacos客户端会维护一个定时任务,每隔5秒发送一次心跳请求,以确保自己处于活跃状态。Nacos服务端在15秒内如果没收到客户端的心跳请求,会将该实例设置为不健康,在30秒内没收到心跳,会将这个临时实例摘除。

这些都不需要开发者手敲代码,在nacos中有一个github.com/nacos-group/nacos-sdk-go/vo.RegisterInstanceParam配置参数,在服务注册的时候需要用到,其中Ephemeral属性表示临时实例,将其设置为true则开启服务心跳模式。

这个维护心跳的模式的线程是基于主函数的,主要主函数服务一直运行,发送心跳就会一直进行下去。

如果把他设置为false,如下:

在这里插入图片描述

不管服务有没有正常启动这个记录都在注册中心,只能通过代码注销实例:


success, err := namingClient.DeregisterInstance(vo.DeregisterInstanceParam{Ip:          "127.0.0.1",Port:        8848,ServiceName: "test_app",Ephemeral:   true,Cluster:     "test", // 默认值DEFAULTGroupName:   "dev_food_platform",   // 默认值DEFAULT_GROUP
})

多服务实例注册

注意区分服务与实例的区别,一个服务包含若干实例,如user服务可能在不同主机注册那么该服务包含若干ip地址。

如果只有一个实例,该实例宕机系统就崩了,多实例通过服务名获取健康实例提高了系统稳定性。

为了系统的稳定性服务一般都是集群部署,因此在注册的时候可以看到,如下配置:


success, err := namingClient.RegisterInstance(vo.RegisterInstanceParam{Ip:          "10.0.0.11",Port:        8848,ServiceName: "demo.go",Weight:      10,Enable:      true,Healthy:     true,Ephemeral:   true,Metadata:    map[string]string{"idc":"shanghai"},ClusterName: "cluster-a", // 默认值DEFAULTGroupName:   "group-a",   // 默认值DEFAULT_GROUP
})

在这里插入图片描述
在nacos注册时首先由配置信息确定集群Cluster,再去更具服务实例的信息查找如namespace,group,servicename等信息定位服务。注册阶段没有dataId,dataid在注册阶段就是servicename。

多个服务注册重复调用注册方法即可:


success, err := namingClient.RegisterInstance(vo.RegisterInstanceParam{Ip:          "10.0.0.11",Port:        8848,ServiceName: "demo.go",Weight:      10,Enable:      true,Healthy:     true,Ephemeral:   true,Metadata:    map[string]string{"idc":"shanghai"},ClusterName: "cluster-a", // 默认值DEFAULTGroupName:   "group-a",   // 默认值DEFAULT_GROUP
})

注意事项:

  • 没有使用集群(ClusterName),自定义字符串即可但同一名称的服务要保持一致。
  • 注册时的配置ip与端口并没有验证,可以随意写,在不同机器上需要获取实际值。
  • 不同主机注册同一服务服务名称(ServiceName)和组(GroupName)必须一致

开发的不同阶段以namespace区分如dev,prod;不同的项目以GroupName区分,如order,user;不同的实例以ServiceName区分,如demo服务可能有,192.168.5.117:8000与192.168.5.118:8000两个实例。

同一服务不同实例的表现形式如下:

在这里插入图片描述
在这里插入图片描述
记录了服务的两个实例的信息。

获取服务

rpc服务也是基于c/s架构的,在之前的章节中通过nacos client注册服务,该服务处于运行状态nacos server会维护该服务的活性。接下来就是服务的获取了。

服务获取也是基于nacos client的,而且是在rpc 的client。在很多的rpc框架如grpc等框架rpc的客户端与服务端都是生成式的,通过生成的方法创建服务端与客户端。这种方式也被称为直连方式。如下:

import ("github.com/cloudwego/kitex/client""order/rpc/orderclient"
)
// order/rpc/orderclient是框架生成的创建客户端对的目录
// 调用生成方法创建客户端实例
// 传入服务名与ip端口地址
func Client() orderclient.RPCClient {rpcClient, err := orderclient.NewRPCClient("orderserver", client.WithHostPorts("192.168.5.118:10000"))if err != nil {panic(err)}return rpcClient
}

其实上述代码的服务名没起作用,传入空字符串也可以,关键是ip与端口。

这种直连的方式弊端也很明显,打那个传入的ip:port宕机后,该客户端也无法使用,其所在服务也受影响。当然也可以将所有ip配置,形成ip列表,使用一些算法获取其中一个作为参数创建客户端实例等一些方法解决,但是了注册中心是目前最好的方法。

引入nacos后,任然需要使用生成的方法,但是此时地址就不在是通过ip:port获取了,而是nacos client通过服务名称获取,nacos client通过namespace,servicename,cluster,group等信息获取一个服务或者一个服务实例列表,当然最好是获取一个健康的正在运行的实例,将其ip:port传递,即完成调用。

这样一来,服务调用者不用保存任何ip信息,提前约定服务名称即可,十分方便。

在这里插入图片描述
图片显示的是nacos-go-sdk提供的获取实例的方法。最好直接使用获取一个健康的实例的方法(免去开发者筛选),如下:

// SelectOneHealthyInstance将会按加权随机轮询的负载均衡策略返回一个健康的实例
// 实例必须满足的条件:health=true,enable=true and weight>0
instance, err := namingClient.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{ServiceName: "demo.go",GroupName:   "group-a",             // 默认值DEFAULT_GROUPClusters:    []string{"cluster-a"}, // 默认值DEFAULT
})
// "github.com/nacos-group/nacos-sdk-go/model"
// model.Instance
type Instance struct {Valid       bool              `json:"valid"`Marked      bool              `json:"marked"`InstanceId  string            `json:"instanceId"`Port        uint64            `json:"port"`Ip          string            `json:"ip"`Weight      float64           `json:"weight"`Metadata    map[string]string `json:"metadata"`ClusterName string            `json:"clusterName"`ServiceName string            `json:"serviceName"`Enable      bool              `json:"enabled"`Healthy     bool              `json:"healthy"`Ephemeral   bool              `json:"ephemeral"`
}

获取的实例对象如上,将其ip与端口作为参数传递给rpc client即可。


import ("fmt""github.com/cloudwego/kitex/client""github.com/flairamos/go-component/nacos""github.com/nacos-group/nacos-sdk-go/vo""order/rpc/orderclient"
)// 直接连接
func Client() orderclient.RPCClient {rpcClient, err := orderclient.NewRPCClient("orderserver", client.WithHostPorts("192.168.5.118:10000"))if err != nil {panic(err)}return rpcClient
}// nacos注册中心连接
func ClientFormNacos() orderclient.RPCClient {var param = vo.SelectOneHealthInstanceParam{Clusters:    []string{"test"},ServiceName: "test_app1",GroupName:   "dev_food_platform",}config := nacos.DefaultClient("public", "mysql", "dev_food_platform", nil)instance, err := nacos.SelectOneHealthyInstance(config, param)if err != nil {panic(err)}addr := fmt.Sprintf("%s:%d", instance.Ip, instance.Port)rpcClient, err := orderclient.NewRPCClient("test_app1", client.WithHostPorts(addr))return rpcClient
}

在这里插入图片描述

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

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

相关文章

法规解读 | 坚持总体国家安全观,新修订的《保守国家秘密法》今年5月1日起施行!

2024年2月27日,第十四届全国人大常委会第八次会议表决通过新修订的《中华人民共和国保守国家秘密法》(以下简称保密法),自2024年5月1日起施行。 本次保密法修订坚持总体国家安全观,统筹发展与安全。 一方面吸收了一些工…

雅特力AT32A403开发板评测 05 0.96寸 IIC接口 OLED模块显示

雅特力AT32A403开发板评测 05 0.96寸 IIC接口 OLED模块显示 1.软硬件平台 软硬件平台 AT32A403A Board开发板 MDK-ARM Keil 0.96寸 IIC接口 OLED显示模块 2.IIC总线 处理器和芯片间的通信可以形象的比喻成两个人讲话:1、你说的别人得能听懂:双方…

OPPO后端二面,凉了!

这篇文章的问题来源于一个读者之前分享的 OPPO 后端凉经,我对比较典型的一些问题进行了分类并给出了详细的参考答案。希望能对正在参加面试的朋友们能够有点帮助! Java String 为什么是不可变的? public final class String implements java.io.Seri…

4.MAC平台Python的下载、安装(含Python2.7+Python3.12双版本环境变量配置)——《跟老吕学Python编程》

4.MAC平台Python的下载、安装(含Python2.7Python3.12双版本环境变量配置)——《跟老吕学Python编程》)——跟老吕学Python编程 一、下载MAC版Python1.Python官网2.MAC版Python下载网址 二、在MAC安装Python1.在MAC安装Python2.阅读Python重要…

JVM之调优(一)

背景:生产环境由于堆内存较大,fullgc 垃圾回收导致程序卡顿问题(假死) 目录 一、程序卡顿导致的影响 前端页面空白后端数据重复 二、解决方法 降低堆内存大小使用合适的垃圾回收器(可以尝试,还未进行测试…

ROS 语音交互(三) tts

目录 一、模型选择 二、流程 三、核心代码展示 一、模型选择 科大讯飞超拟人识别 二、流程 超拟⼈合成协议 | 讯飞开放平台文档中心 (xfyun.cn) 三、核心代码展示 # coding: utf-8 import _thread as thread import os import time import base64import base64 import …

雅特力车规级MCU-AT32A403A开发板评测 06 GC9A01 SPI-LCD 1.28圆形屏幕

雅特力车规级MCU-AT32A403A开发板评测 06 GC9A01 SPI-LCD 1.28圆形屏幕 硬件平台 AT32A403A Board开发板 1.28寸圆形彩色TFT显示屏高清IPS 模块240X240 SPI接口GC9A01 产品介绍 推荐一个屏幕资料参考网站 http://www.lcdwiki.com/1.28inch_IPS_Module 1.28寸圆形IPS彩屏&…

2 配置虚拟机

1.打开VM,主页的界面如下,点击"创建新的虚拟机" 2.选择“自定义(高级)”,然后点击下一步,如下图所示: 3.下图直接点击“下一步” 4.下图的界面上,注意,不要选择…

Windows如何同时登录两个OneDrive个人版账号

初级代码游戏的专栏介绍与文章目录-CSDN博客 目前为止,onedrive只支持同时登录一个账号(据说onedrive business支持同时登录多个账号,不过这属于另一个产品了),但是,并非没有别的办法曲线实现,下…

解释器模式(Interpreter Pattern)

解释器模式 说明 解释器模式(Interpreter Pattern)属于行为型模式,是指给定一门语言,定义它的语法(文法)的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。是一…

在ubuntu20通过docker部署zabbix6

部署Zabbix 6.x服务器在Ubuntu 20.04 LTS系统上使用Docker的方式可以简化安装过程并实现容器化管理。以下是一个简化的步骤指南: 步骤1:安装Docker和Docker Compose 确保你的Ubuntu系统已经安装了Docker和Docker Compose。如果没有,请执行以…

项目中日志采集实践:技术、工具与最佳实践

✨✨谢谢大家捧场,祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天开心哦!✨✨ 🎈🎈作者主页: 喔的嘛呀🎈🎈 目录 引言 一. 选择合适的日志框架 二. 配置日志框架 三. 使用…