go-zero微服务实战——etcd服务注册与发现

news2024/10/6 16:17:47

etcd简介

浅谈etcd服务注册与发现

etcd官网

etcd中文文档

apt安装etcd,启动命令十分简单etcd

在这里插入图片描述

etcd分为v2版本和v3版本,命令有所不一样,使用命令etcdctl h查看

在这里插入图片描述
如上图所示并没有出现API的版本,此时是使用默认的v2版本,但是v2版本很多命令使用不了,因此切换为v3版本,命令如下:

# 设置命令为v3
export ETCDCTL_API=3

# 查看所有的key,会出现两行,第一行key,第二行value
etcdctl get --prefix ""

在这里插入图片描述

etcd是一个k-v存储的格式和redis类似,使用etcdctl set k v存储数据,使用etcdctl get k获取数据。

在这里插入图片描述

go中使用etcd

安装

go get go.etcd.io/etcd/clientv3

客户端代码

package main

import (
	"context"
	"fmt"
	"go.etcd.io/etcd/clientv3"
	"time"
)
// etcd client put/get demo
// use etcd/clientv3

func main() {
	cli, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"127.0.0.1:2379"},
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		// handle error!
		fmt.Printf("connect to etcd failed, err:%v\n", err)
		return
	}
	fmt.Println("connect to etcd success")
	defer cli.Close()
	//put
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	_, err = cli.Put(ctx, "zhangsan", "yes")
	cancel()
	if err != nil {
		fmt.Printf("put to etcd failed, err:%v\n", err)
		return
	}
	// get
	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	resp, err := cli.Get(ctx, "zhangsan")
	cancel()
	if err != nil {
		fmt.Printf("get from etcd failed, err:%v\n", err)
		return
	}
	for _, ev := range resp.Kvs {
		fmt.Printf("%s:%s\n", ev.Key, ev.Value)
	}
}

启动etcd服务器

etcd --listen-client-urls 'http://0.0.0.0:2379' --advertise-client-urls 'http://0.0.0.0:2379'

不要直接etcd启动,会报错context deadline exceeded

在这里插入图片描述

运行客户端代码
在这里插入图片描述
可以看出etcd是键值对存储的。

go-zero使用etcd

etcd最具特色的功能是订阅与发布监测变更,在etcd作为服务注册与查找时,etcd提供了检测功能,开启该功能后会持续想etcd服务器发送心跳,如果服务停掉或者心跳停止,etcd服务器就会删除该次记录(服务器自主完成)。

一般来说,rpc服务连接etcd服务器发送心跳,实现服务到服务调度中心的注册,服务名称和地址被存储到etcd服务器,另一个服务调用时不是直接连接rpc服务器,而是先根据服务名称在etcd中找到ip地址,在通过ip地址调用服务。这样以来服务名称和其对于的地址就与源代码解耦,在部署到不同ip的服务器时无需修改源代码。

  1. 开启etcd服务器

etcd --listen-client-urls 'http://0.0.0.0:2379' --advertise-client-urls 'http://0.0.0.0:2379'
在这里插入图片描述

  1. key存储并开启心跳检测
package main

import (
	"context"
	"fmt"
	"go.etcd.io/etcd/clientv3"
	"time"
)

func main() {
	config := clientv3.Config{
		Endpoints:   []string{"localhost:2379"},
		DialTimeout: 5 * time.Second,
	}

	client, err := clientv3.New(config)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer client.Close()

	lease := clientv3.NewLease(client)                      // 创建一个心跳检测
	leaseResp, err := lease.Grant(context.Background(), 10) // 配置检测超时 10秒,查过检测时间etcd服务器自动删除k-v键值对
	if err != nil {
		fmt.Println(err)
		return
	}
	leaseRespChan, _ := lease.KeepAlive(context.Background(), leaseResp.ID) // 通过keeplive方法定期发送心跳

	kv := clientv3.NewKV(client)
	key := fmt.Sprintf("/services/http/%d", leaseResp.ID)
	value := `{"host": "localhost", "port": 2379}`
	fmt.Println("key", key)

	// 绑定带有心跳的服务并将自身服务信息put到etcd中心
	_, err = kv.Put(context.Background(), key, value, clientv3.WithLease(leaseResp.ID))
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("register service success")

	for {
		select {
		case i := <-leaseRespChan:
			fmt.Println("heart beat", i.String()) // 心跳信息
		}
	}
}

请添加图片描述

如上图所示,服务etcd心跳会一直发送到etcd服务器,那么可以在rpc服务下启动一个心跳,一直检测服务的状态,rpc服务如果宕机心跳停止,etcd服务器就会删除该服务的k-v记录。

etcd服务器的心跳检测时etcd服务器自动完成的,开发者只需要配置心跳时间,调用心跳方法就可以了,服务器会根据心跳自动管理数据。

在go-zero中已经集成了etcd,通过配置文件的形式,在goctl下都会有,如下配置:

Etcd:
  Hosts:
  - 127.0.0.1:2379
  Key: rpcservice.rpc

该部分配置etcd服务器的接口和key。配置etcd服务器后需要设置心跳,如下步骤:

  1. 下载etcd客户端
go get  go.etcd.io/etcd/clientv3
  1. 配置客户端调用心跳函数
//etcd服务端启动
etcdConfig := clientv3.Config{
	Endpoints:   []string{"localhost:2379"},
	DialTimeout: 5 * time.Second,
}
//etcd客户端
etcdClient, err := clientv3.New(etcdConfig)
if err != nil {
	println(err)
	return
}
defer etcdClient.Close()

//配置心跳
lease := clientv3.NewLease(etcdClient)
lgr, err := lease.Grant(context.Background(), 10) //10秒发送一次心跳
if err != nil {
	println(err)
	return
}
c2, _ := lease.KeepAlive(context.Background(), lgr.ID)

//通过客户端获取k-v存储对象
k := clientv3.NewKV(etcdClient)
key := "order.rpc"        //可以同配置文件中获取
value := "localhost:2379" //不同服务器的ip不一样,这里设置为localhost或者通过方法获取本机ip也可以
k.Put(context.Background(), key, value, clientv3.WithLease(lgr.ID))

//打印心跳检测返回的数据
for {
	if len(c2) != 0 {
		fmt.Println("heart beat ", <-c2)
	}
}

报错如下:

# github.com/coreos/etcd/clientv3/balancer/picker
C:\Users\sspaas\go\pkg\mod\github.com\coreos\etcd@v3.3.27+incompatible\clientv3\balancer\picker\err.go:37:53: undefined: balancer.PickOptions
C:\Users\sspaas\go\pkg\mod\github.com\coreos\etcd@v3.3.27+incompatible\clientv3\balancer\picker\roundrobin_balanced.go:55:63: undefined: balancer.PickOptions
# github.com/coreos/etcd/clientv3/balancer/resolver/endpoint
C:\Users\sspaas\go\pkg\mod\github.com\coreos\etcd@v3.3.27+incompatible\clientv3\balancer\resolver\endpoint\endpoint.go:114:87: undefined: resolver.BuildOption
C:\Users\sspaas\go\pkg\mod\github.com\coreos\etcd@v3.3.27+incompatible\clientv3\balancer\resolver\endpoint\endpoint.go:182:40: undefined: resolver.ResolveNowOption

在这里插入图片描述
原因时grpc和etcd版本冲突问题参考

又报错:
在这里插入图片描述
原因主要是etcd中使用的bbolt和grpc版本冲突引起参考

解决冲突后,在服务气短通过检测心跳的方式将rpc的名称为ip的k-v存储到rpc服务器中,然后通过其他客户端通过服务名称获取值后进行rpc远程调用即可。

客户端程序

如果遇到zero集成的etcd和grpc有冲突的话,使用独立的etcd,不要在使用zero集成的etcd。代码如下:

package main

import (
	"context"
	"fmt"
	"time"

	"go.etcd.io/etcd/clientv3"
)

// etcd client put/get demo
// use etcd/clientv3

func main() {
	cli, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"127.0.0.1:2379"},
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		// handle error!
		fmt.Printf("connect to etcd failed, err:%v\n", err)
		return
	}
	fmt.Println("connect to etcd success")
	defer cli.Close()
	//put
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	_, err = cli.Put(ctx, "zhangsan", "yes")
	cancel()
	if err != nil {
		fmt.Printf("put to etcd failed, err:%v\n", err)
		return
	}
	// get
	ctx, cancel = context.WithTimeout(context.Background(), time.Second)
	resp, err := cli.Get(ctx, "demo.rpc")
	cancel()
	if err != nil {
		fmt.Printf("get from etcd failed, err:%v\n", err)
		return
	}
	for _, ev := range resp.Kvs {
		fmt.Printf("%s:%s\n", ev.Key, ev.Value)
	}
}


服务端程序

package main

import (
	"context"
	"fmt"
	"time"

	"go.etcd.io/etcd/clientv3"
)

func main() {
	config := clientv3.Config{
		Endpoints:   []string{"localhost:2379"},
		DialTimeout: 5 * time.Second,
	}

	client, err := clientv3.New(config)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer client.Close()

	lease := clientv3.NewLease(client)                      // 创建一个租约
	leaseResp, err := lease.Grant(context.Background(), 10) // 设置租约超时 10秒
	if err != nil {
		fmt.Println(err)
		return
	}
	leaseRespChan, _ := lease.KeepAlive(context.Background(), leaseResp.ID) // 通过keeplive定期发送心跳

	kv := clientv3.NewKV(client)
	key := "demo.rpc"
	value := "127.0.0.1:9000"
	fmt.Println("key", key)

	// 绑定带有心跳的租约并将自身服务信息put到etcd中心
	_, err = kv.Put(context.Background(), key, value, clientv3.WithLease(leaseResp.ID))
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("register service success")

	for {
		select {
		case i := <-leaseRespChan:
			fmt.Println("heart beat", i.String()) // 心跳信息
		}
	}
}

别忘了启动etcd服务器

etcd --listen-client-urls 'http://0.0.0.0:2379' --advertise-client-urls 'http://0.0.0.0:2379'

在这里插入图片描述

服务端心跳
在这里插入图片描述
获取键值对
在这里插入图片描述

go语言学习网站

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

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

相关文章

android editText获取不到数据

问题分析&#xff1a;在onActivityCreated一开始就创建了findViewById&#xff0c;这时获取的是默认值&#xff0c;需要在点击按钮时重新加载才能获取到输入数据。 需要在点击按钮时重新加载数据&#xff1a;

Android Studio中java编程时禁止生成警告

1、打开Android Studio&#xff0c;进入主界面 2、进入软件后&#xff0c;点击菜单栏的File 3、在File选项中选择Settings 4、进入Settings选择Version Control -> Subversion -> Presentation 5、去掉勾选 Show merge source in history and anotations 6、最后点击确定…

在vite创建的vue3项目中使用Cesium加载czml路径信息和无人机模型

在vite创建的vue3项目中使用Cesium加载czml路径信息和无人机模型 用到的区域文件、地图标记文件、路径信息文件、模型文件 提取码&#xff1a;99jq 使用vite创建vue3项目 npm create vitelatestcd到创建的项目文件夹中 npm install安装Cesium npm i cesium vite-plugin-cesium…

一文详解常见标准化组织

从事软件研发工作多年&#xff0c;在工作中有时会查阅一些通信相关的国际标准。然而&#xff0c;对于制定这些标准的组织&#xff0c;一直缺乏一个系统的了解。本文将对几个常见的标准化组织进行介绍&#xff0c;其中包括ITU、3GPP、GSMA和CCSA&#xff0c;了解它们的背景、成立…

零基础学习C#编程的步骤和建议

如果你是零基础&#xff0c;希望学习C#编程语言&#xff0c;以下是一些建议的学习步骤&#xff1a; 基础概念和语法&#xff1a;开始学习C#之前&#xff0c;了解基本的编程概念和语法是很重要的。可以通过在线教程、编程书籍或视频教程来学习C#的基础知识&#xff0c;包括变量…

JVM中类加载的过程

文章目录 一、类加载是什么二、类加载过程1.加载2.验证3.准备4.解析5.初始化 三、什么时候进行类加载四、双亲委派模型1.三大类加载器2.加载过程 总 一、类加载是什么 把.class文件加载到内存中&#xff0c;得到类对象的过程。 二、类加载过程 1.加载 找到.class文件&#xff…

数据预处理matlab

matlab数据的获取、预处理、统计、可视化、降维 数据的预处理 - MATLAB & Simulink - MathWorks 中国https://ww2.mathworks.cn/help/matlab/preprocessing-data.html 一、数据的获取 1.1 从Excel中获取 使用readtable() 例1&#xff1a; 使用spreadsheetImportOption…

给大家推荐几款好用的格式转换工具

在数字化时代&#xff0c;我们经常需要处理各种不同的文件格式。有时我们可能需要将视频转换为适用于特定设备的格式&#xff0c;有时又需要将音频文件转换为可编辑的格式&#xff0c;或者将文档转换为更通用的类型。这就是格式转换工具的重要性所在。然而&#xff0c;在众多的…

纯css3实现小鸡从鸡蛋破壳而出动画特效

实现一个使用纯css3实现小鸡破壳的效果 示例效果如下所示 示例代码 <template><div><div class"eggWrapper"><div class"chickHead"><div class"eyeDiv"></div><div class"eyeDiv"></di…

一文详解 Okio 输入输出流

在 OkHttp 的源码中&#xff0c;我们经常能看到 Okio 的身影&#xff0c;这篇文章&#xff0c;我们把Okio拿出来进行一个详细的介绍学习。 输入输出的概念简述Okio 简介工程中引入 OkioAPI 简介及使用介绍 一、输入输出 在正式介绍 Okio 之前&#xff0c;让我们先回忆一下输…

STM32自学笔记14-步进电机驱动项目-TB67H450驱动

目前的项目是一种2相4线步进电机的闭环驱动电路&#xff0c;使用的电机驱动芯片是TB67H450&#xff0c;再使用磁编码器MT6816&#xff0c;使用FOC算法&#xff0c;基于STM32F1单片机。 这一节是步进电机的驱动芯片驱动研究 首先研究驱动芯片TB67H450的datasheet 这是一个PWM斩…

11_SPI_Flash 读数据实验

11_SPI_Flash 读数据实验 1. 实验目标2. 操作时序2.1 数据读操作指令2.2 数据读操作时序 3. 流程框图3.1 顶层模块3.2 数据读模块 4. 波形图绘制5. RTL5.1 flash_read_ctrl5.2 spi_flash_read 6. testbench 1. 实验目标 使用页写或连续写操作向 Flash 芯片写入数据&#xff0c…

火山引擎 DataLeap 构建Data Catalog系统的实践(三):关键技术与总结

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 关键技术 构建一个好的Data Catalog系统&#xff0c;需要考虑的核心产品设计和技术设计有很多。篇幅所限&#xff0c;本文只概要介绍技术设计中最核心重要的部分&a…

工作日志2 input 的事件优先级 字符串.trim() this.$set()的应用 获取jq的自定义属性

input 的事件优先级 1.input输入框的事件 字符串.trim() 除去前后空格的方法 undefind不可以使用 this.$set()的应用

苹果Mac动态壁纸软件Dynamic Wallpaper

Dynamic Wallpaper 是一款桌面壁纸管理软件&#xff0c;它提供了动态壁纸的功能。动态壁纸是指可以在一段时间内自动更改外观的壁纸&#xff0c;比如根据时间或其他条件进行变化。这种壁纸可以为用户提供更加生动有趣的桌面体验。 Dynamic Wallpaper 软件具有以下特点和功能&am…

基于Java+SpringBoot+Vue的中小企业财务管理系统设计与实现

博主介绍&#xff1a;✌擅长Java、微信小程序、Python、Android等&#xff0c;专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案…

Word之解决中文和英文混写导致字间距增大的问题(六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【2023裸辞失业后之初学Docker1】

目录 Docker简介docker下载安装常用命令帮助启动类命令镜像命令容器命令 镜像分层概念commit命令本地镜像发布到腾讯云 docker容器数据卷宿主机和容器内添加容器卷案例读写规则容器卷的继承 学习视频来自 https://www.bilibili.com/video/BV1gr4y1U7CY Docker简介 Docker出现…

DNS协议解析原理

0. 前言 为了保证网址的正常访问&#xff0c;域名解析协议&#xff08;DNS&#xff09;其实在背后做出了很多努力&#xff0c;本文将透彻讲解 DNS 协议的原理&#xff0c;了解我们每天都在接触的网址到底是怎么工作的。 1. 什么是 DNS 协议 在学习 DNS 协议之前&#xff0c;我…

你真的不想知道ai绘画工具有哪些吗?

近期我发现了一个超酷的玩意儿&#xff0c;叫做ai绘画工具。没错&#xff0c;它就是那个能让你在不懂任何绘画技巧的情况下&#xff0c;也能创作出令人惊叹的艺术作品的神奇东西&#xff01;简直就像是给你一支魔法画笔&#xff0c;让你成为真正的艺术大师。但是&#xff0c;市…