小工具      在线工具  汉语词典  dos游戏  css  js  c++  java

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

SHARE,# go-zero,golang,微服务,etcd 额外说明

收录于:17天前

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. 密钥存储并启用心跳检测
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服务器自动完成的。开发者只需配置心跳时间并调用心跳方法即可。服务器会根据心跳自动管理数据。

etcd 已经以配置文件的形式集成到 go-zero 中,可以在 goctl 下使用,如下:

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

本节配置etcd服务器的接口和密钥。配置好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版本冲突引起参考

冲突解决后,服务呼吸者通过检测心跳将名为ip的rpc的k-v存储在rpc服务器中,然后通过其他客户端通过服务名获取该值,然后进行rpc远程调用。

客户程序

如果零集成etcd和grpc之间存在冲突,请使用独立的etcd而不是零集成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语言学习网站

. . .

相关推荐

额外说明

[进阶] list 过滤 stream 的lambda进阶操作, 这一篇就够了

目录 1. list转化map基本操作 id最常用方式:  -> 01  key-value值形式: -> 02 id-> 对象本身 -> 03 id-> 对象本身的 lambda写法 ->04  解决冲突的key 2. list计算操作 3. list

额外说明

【算法千题案例】每日LeetCode打卡——98.字符的最短距离

-前言 -原题样例:字符的最短距离 -C#方法:排序遍历 -Java 方法:暴力法 -总结 -前言 - 算法题 - - 每天打卡一道算法题,既是一个学习过程,又是一个分享的过程- - 提示:本专栏解题 编程语言一律使用 C# 和 Java 两种进行解题

额外说明

25.常用的字段类型映射关系,字段类型及Field的常用参数

1.常用的字段类型映射关系: 2常用的字段类型讲解: IntegerField : 整型,映射到数据库中的int类型。 CharField: 字符类型,映射到数据库中的varchar类型,通过max_length指定最大长度。 TextField: 文本

额外说明

《springboot实战》第八章 springboot 整合Druid

系列文章目录 第一章 SpringBoot起步 第二章 springboot 配置文件、多环境配置、运行优先级 第三章 springboot 统一日志 第四章 SpringBoot加载静态文件资源 第五章 springboot 拦截器 第六章 实现自定义

额外说明

RESTful 基础知识

文章目录 1.API 应用程序接口 2.应用接口 3.Web技术的发展阶段 4.前后端分离 5.RESTful风格 6.RESTful设计 6.1 网络上的所有事物都被抽象为资源 6.2 资源状态转换 6.3 使用统一接口 6.4 同一个资源具有多种表现

额外说明

NodeJs和go中使用consul做服务发现

一、环境的安装 1、安装docker curl -fsSL https://get.docker.com | bash -s docker --mirror aliyun curl -sSL https://get.daocloud.io/docker

额外说明

Java使用H2数据库全方式汇总

H2是轻量级数据库, 可以不需要安装就可以运行,对于快速学习和演示比较适用。关于H2的基本内容可以参考: H2 数据库简介 。 本篇快速介绍H2数据库在各种类型的Java应用中的使用, 包括: Java 项目 Java Web 项目 Spring Boo

额外说明

[微积分] 常用定义与公式

函数、极限与连续性 连续性 导数 微分 全微分与偏导数: 级数与中值定理 两元函数 常用积分公式  

额外说明

《实战:如何搭建一个完整的 Vue2.0 项目》- 2、vue.config.js 配置

构建项目时不会自动创建 vue.config.js 文件,需要在根目录下手动创建。插件 @vue/clli-service 会自动加载。直接拷贝如下内容即可。 该文件很丰富,有很多配置项,可自行研究(链接)。这里只列了我的项目中常用的配置。 const

额外说明

honeypot_如何使用Honeypot阻止WordPress中的垃圾邮件评论机器人

蜜罐 垃圾评论是一个巨大的痛苦。为了防止垃圾评论,博主最终采取了严格的措施,例如要求人们在提交评论之前注册或输入验证码。验证码、数学测验和注册等垃圾邮件预防控制措施使普通访问者很难发表评论。通过实施其中一种方法,您正在惩罚错误的人群。许多垃圾评论是由机器

ads via 小工具