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

这篇具有很好参考价值的文章主要介绍了go-zero微服务实战——etcd服务注册与发现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

etcd简介

浅谈etcd服务注册与发现

etcd官网

etcd中文文档

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

go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd

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

go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd
如上图所示并没有出现API的版本,此时是使用默认的v2版本,但是v2版本很多命令使用不了,因此切换为v3版本,命令如下:

# 设置命令为v3
export ETCDCTL_API=3

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

go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd

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

go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd

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

go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd

运行客户端代码
go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd
可以看出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'
go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd

  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()) // 心跳信息
		}
	}
}

go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd

如上图所示,服务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

go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd
原因时grpc和etcd版本冲突问题参考

又报错:
go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,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-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd

服务端心跳
go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd
获取键值对
go-zero微服务实战——etcd服务注册与发现,SHARE,# go-zero,golang,微服务,etcd

go语言学习网站文章来源地址https://www.toymoban.com/news/detail-661525.html

到了这里,关于go-zero微服务实战——etcd服务注册与发现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringCloudAlibaba微服务实战系列(一)Nacos服务注册发现

    实战前先做一个背景了解。 单体架构:近几年技术的飞速发展,各种各样的服务已经进入到网络化。单体架构发布时只需要打成一个war或jar包发布即可;而随着业务量激增或网站流量的增加,必会暴露致命缺陷。 SOA:Service Oriented Architecture 面向服务的体系结构。旨在提升代

    2024年02月15日
    浏览(27)
  • go-zero的服务发现源码阅读

    服务发现原理与grpc源码解析_wangxiaoangg的博客-CSDN博客   go-zero rpc demo官方文档:rpc编写与调用 | go-zero 目录 一 服务注册 1. 创建rpc服务 2. 启动rpc服务 3. registerEtcd做了什么 4. discov.NewPublisher 服务发布者 二 服务发现 1.定义注册resolver 2.解析etcd地址创建链接 3.update方法 在看rp

    2024年02月06日
    浏览(45)
  • go-zero 开发之安装 etcd

    本文只涉及 Linux 上的安装。 二进制安装 下载二进制安装包 下载地址示例: 解压二进制安装包 删除二进制安装包 版本检查 启动 etcd 往 etcd 写读数据 Docker 安装 etcd 主要使用 Google 容器注册表(gcr.io)下的 gcr.io/etcd-development/etcd 仓库来存储其容器镜像。作为次要选项,它还使

    2024年02月04日
    浏览(30)
  • Go gRPC etcd实现服务注册发现与负载均衡

    如果不了解go + grpc 调用方式和实现细节,可以参考上一篇文章 golang grpc配置使用实战教程 技术点 版本 描述 golang 1.19 基础版本 grpc v1.41.0 gRPC golang包 etcd server 3.5.0 注册中心 etcd client v3.5.8 客户端服务发现和负载均衡 服务注册依赖etcd的 key-value操作,key作为gRPC服务唯一标识,

    2024年02月05日
    浏览(40)
  • 使用go-zero快速构建微服务

    本文是对 使用go-zero快速构建微服务 [1] 的亲手实践 编写API Gateway代码 mkdir api goctl api -o api/bookstore.api cd api goctl api go -api bookstore.api -dir . go run bookstore.go -f etc/bookstore-api.yaml 启动API Gateway服务,默认侦听在8888端口 因为默认生成的 api/etc/bookstore-api.yml 为: 按提示下载,再次运行

    2024年02月13日
    浏览(50)
  • go-zero学习 第三章 微服务

    1.1 API服务模块 goctl 使用 api 文件生成 api服务 命令: 1.2 RPC服务模块 goctl 使用 protoc 文件生成 rpc服务 命令: 注意: --go_out 、 --go-grpc_out 、 --zrpc_out 三者配置的路径需要完全一致,否则会报下列错误。 基础代码:已生成基本的API服务、RPC服务。 这里以API服务调用RPC服务的登

    2024年02月16日
    浏览(60)
  • go-zero的rpc服务案例解析

    go-zero的远程调用服务是基于gRpc的gRPC教程与应用。 zero使用使用gRpc需要安装 protoc 插件,因为gRpc基于protoc插件使用protocol buffers文件生成rpc服务器和api的代码的。 gRPC 的代码生成还依赖 protoc-gen-go,protoc-gen-go-grpc 插件来配合生成 Go 语言的 gRPC 代码。 也可以使用go get命令安装

    2024年02月13日
    浏览(64)
  • 【go-zero】go-zero阿里云oss 前端上传文件到go-zero API服务 并在k8s pod中创建文件 并推送到阿里云oss 最佳实践

    问题:在本地通过上传文件,然后将文件推送到aliyun的oss中,是没问题的 但是部署到了k8s中,则出现了问题,一直报错没有创建的权限 思路:开始认为应该将该文件挂载到configmap中,然后通过这种方式修改了deployment和dockerfile。最终发现应该是go的创建文件路径方式搞错了,

    2024年02月13日
    浏览(38)
  • 微服务框架 go-zero logx 日志组件剖析

    上一篇我们说到咱们还剩下 addTenant 功能还未实现,不知道有没有兄弟感兴趣去实验一波的,本篇文章进行简要补充 根据上一篇文章分析,其实我们只需要执行如下几步即可: 编写 tenant.api,提供外部 addTenant 的 http 接口 编写 tenant.api 提供一个 POST http 的接口 / api /tenant/addt

    2024年02月11日
    浏览(37)
  • Go-Zero微服务快速入门和最佳实践(一)

    并发编程和分布式微服务 是我们Gopher升职加薪的关键。 毕竟Go基础很容易搞定,不管你是否有编程经验,都可以比较快速的入门Go语言进行简单项目的开发。 虽说好上手,但是想和别人拉开差距,提高自己的竞争力, 搞懂分布式微服务和并发编程还是灰常重要的,这也是我

    2024年04月28日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包