【etcd】解决 go-zero 注册 etcd 出现 “Auto sync endpoints failed.” 的问题

这篇具有很好参考价值的文章主要介绍了【etcd】解决 go-zero 注册 etcd 出现 “Auto sync endpoints failed.” 的问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

go: v1.20.3

go-zero: v1.5.4

etcd: v3.5.9


问题描述

在 go-zero 中用 etcd 去实现服务注册发现,rpc 服务可以注册到 etcd,同时其他服务可以发现注册的微服务,也可以访问。但是,注册的 rpc 服务的日志,就是一直报以下错误。日志一直在刷 Auto sync endpoints failed 的问题,服务也可以访问,就很诡异。

{"level":"warn","ts":"2023-07-30T15:57:02.004+0800","logger":"etcd-client","caller":"v3@v3.5.4/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc0007281c0/192.168.2.2:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"transport: Error while dialing dial tcp 0.0.0.0:2379: connect: connection refused\""}
{"level":"info","ts":"2023-07-30T15:57:02.004+0800","logger":"etcd-client","caller":"v3@v3.5.4/client.go:210","msg":"Auto sync endpoints failed.","error":"context deadline exceeded"}

如果是老手,看到这里 ,应该知道问题会出在哪里。我是菜鸟,就只好一步步分析。

如果想直接看解决方法的,到最后,下面是我的分析过程。


排查

当出现问题的时候,想的就是包的问题,不是我的问题。就去 trace go-zero 的源码,也就是 etcd 注册的那个地方。

把 go-zero,封装 etcd 的源码看了好几遍,也没发现有问题,都是正常的注册与发现。(注意:这时候我 go-zero 版本还是 v1.3.2)

没什么问题,以为是 go-zero 版本太旧了,升级一下。因为看 issue 说 etcd 版本也有可能太旧。

验证一

把 go-zero 版本升级到 v1.5.4(中间是先到v1.4.4),把 etcd 升级到 v3.5.9(中间是先到v3.5.7),发现并没有成功,还是会出现 Auto sync endpoints failed


想想 go-zero 应该也不至于会出这个问题,会不会是我 etcd 启动的问题?我是用 docker 启动的 etcd,因为是在测试,就用单点。这边对配置的 IP 其实没有概念,也不知道都是干嘛的。

docker run -d --name ai-etcd --network=host --restart always \
 -v $PWD/etcd.conf.yml:/opt/bitnami/etcd/conf/etcd.conf.yml \
 -e ETCD_ADVERTISE_CLIENT_URLS=http://0.0.0.0:2379 \
 -e ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 \
 -e ETCD_LISTEN_PEER_URLS=http://0.0.0.0:2380 \
 -e ETCD_INITIAL_ADVERTISE_PEER_URLS=http://0.0.0.0:2380 \
 -e ALLOW_NONE_AUTHENTICATION=yes \
 bitnami/etcd:3.5.9

这个 docker 的启动方式,也是往上找的,没问题呀。启动也 ok,go-zero 也注册得上去。

再看看 etcd 到底哪里出的问题,又去看了下源码。

// client.go L196
func (c *Client) autoSync() {
	if c.cfg.AutoSyncInterval == time.Duration(0) {
		return
	}

	for {
		select {
		case <-c.ctx.Done():
			return
		case <-time.After(c.cfg.AutoSyncInterval):
			ctx, cancel := context.WithTimeout(c.ctx, 5*time.Second)
			err := c.Sync(ctx)
			cancel()
			if err != nil && err != c.ctx.Err() {
				c.lg.Info("Auto sync endpoints failed.", zap.Error(err))
			}
		}
	}
}

// Sync synchronizes client's endpoints with the known endpoints from the etcd membership.
func (c *Client) Sync(ctx context.Context) error {
	mresp, err := c.MemberList(ctx)
	if err != nil {
		return err
	}
	var eps []string
	for _, m := range mresp.Members {
		...
	}
	c.SetEndpoints(eps...)
	return nil
}

上面这个方法报错,因为 Auto sync endpoints failed 是一直出现的,说明 go-zero 里面有个地方,应该也配置了 AutoSyncInterval ,所以这边会跑这个。下面是,go-zero 调用的地方,其实也就是初始化一个etcd client的传参。

// registry.go L337
// DialClient dials an etcd cluster with given endpoints.
func DialClient(endpoints []string) (EtcdClient, error) {
	cfg := clientv3.Config{
		Endpoints:            endpoints,
		AutoSyncInterval:     autoSyncInterval,
		DialTimeout:          DialTimeout,
		DialKeepAliveTime:    dialKeepAliveTime,
		DialKeepAliveTimeout: DialTimeout,
		RejectOldCluster:     true,
		PermitWithoutStream:  true,
	}
	...
}

此时此刻很无奈,感觉不知道往哪里思考。服务也没报错,也能调用,就又很不想去分析。这种问题就很折磨,关键日志很多,很丑。还是多找找吧,去看 go-zero 的 issue,看到也有人提这个问题,不过都没有什么解决方案。去看 etcd 的 issue,也没有看到什么。最后也不知道怎么地,想为什么要一直带着 go-zero 去想这个问题,我自己写一个 etcd client 试一下不就行了。找了个范例,测一下,不就知道是 go-zero 的问题,还是 etcd 起的有问题。

范例我就不详细列了,可以去看我的另一篇 【etcd】docker 启动单点 etcd_非晓为骁的博客-CSDN博客 的文章。

cli, err = clientv3.New(clientv3.Config{
	Endpoints:        []string{"192.168.2.2:2379"},
	DialTimeout:      time.Second * 5,
	AutoSyncInterval: time.Second * 5,
})

同样也设置了 AutoSyncInterval,结果难受香菇,竟然也会报这个错误

这里有一个很重要的点,不要出了问题就局限在你用的框架里面,更要会抽丝剥茧,简单地看问题。


这时候说明 etcd 部的就是有问题的,只好再看下 docker run 的指令和错误。我把错误,减少到下面这一行,仔细看下,可以看到是服务 dial 0.0.0.0:2379 失败。rpc 服务和 etcd 是在 2 台服务器,访问本地 2379 就是访问容器内 2379,那肯定访问不到呀。关键是 0.0.0.0:2379 拿来的呢?

"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"transport: Error while dialing dial tcp 0.0.0.0:2379: connect: connection refused\""

rpc 的配置,配的是 etcd 的 host,肯定不是 0.0.0.0:2379。那说明是 etcd 服务自身返回回来的。这时候,只好去分析 docker run 里面的 url。4 个,有 2 个是 2380,说明不是我要关注的,剩下 2 个应该就是问题本身。另外 2 个 2380,看起来是 cluster 相关的,所以也可以直接忽略。

  • -e ETCD_ADVERTISE_CLIENT_URLS=http://0.0.0.0:2379 \
  • -e ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 \

看了下注释:

  • ETCD_LISTEN_CLIENT_URLS :List of comma separated URLs to listen on for client traffic.
  • ETCD_ADVERTISE_CLIENT_URLS:List of this member’s peer URLs to advertise to the rest of the cluster. The URLs needed to be a comma-separated list.

我理解的是 ETCD_LISTEN_CLIENT_URLS 是监听的 IP:PORT,谁可以访问这个服务,类似我们其他服务用的 bind,所以这个用 0.0.0.0 应该没问题。ETCD_ADVERTISE_CLIENT_URLS 这看起来是要通知别人要访问这个 IP:PORT 才可以访问到我,看起来好像是这个的问题。改成我的服务器 IP 试试。

验证二
docker run -d --name ai-etcd --network=host --restart always \
 -v $PWD/etcd.conf.yml:/opt/bitnami/etcd/conf/etcd.conf.yml \
 -e ETCD_ADVERTISE_CLIENT_URLS=http://192.168.2.2:2379 \
 -e ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 \
 -e ALLOW_NONE_AUTHENTICATION=yes \
 bitnami/etcd:3.5.9

emmm,这样子在用我 etcd 的范例测试一下,果真没有报错了。为自己的愚蠢感到深深的无语,还一直以为是 go-zero 的问题,其实跟 go-zero 一点关系都没有。


总结

这个问题,出现了很久从 v1.3.2 开始就有。但一直分析不出来就搁置,而且不影响使用。最后还是洁癖,看不惯,分析这个问题。一开始就先入为主地看是 go-zero 的问题,去看 issue,去百度,google,但都带上了 go-zero。其实就不是它的问题,自己的分析能力还是不够。etcd 这边 docker 启动的方式,大部分都是一样的,启动起来好像也没啥问题,也不会往那边去想。

这个问题深层次原因,应该还是对 etcd 不了解,里面的一些 url 不了解。而且,需要多去尝试,用最小单元去做测试,这样才可以事半功倍。

解决方案

etcd docker run 的 ETCD_ADVERTISE_CLIENT_URLS 要改成服务器 IP,然后 rpc 服务重新注册。


这个是我自己分析的过程及理解,可能这里面还有更深层次的问题,有懂的大佬可以分享一下。文章来源地址https://www.toymoban.com/news/detail-622727.html

到了这里,关于【etcd】解决 go-zero 注册 etcd 出现 “Auto sync endpoints failed.” 的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【Go-Zero】goctl生成model层后报错Unresolved reference ‘ErrNotFound‘解决方案

    大家好 我是寸铁👊 总结了一篇goctl生成model层后报错Unresolved reference \\\'ErrNotFound’报错解决方案的文章✨ 喜欢的小伙伴可以点点关注 💝 大家好,我是寸铁!今天在使用 goctl 一键转换生成 model 层代码时,出现了个小 bug 。下面我们一起来看一下这个 bug 是什么? 具体报错信息

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

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

    2024年02月13日
    浏览(46)
  • go-zero学习 第一章 基础

    因官网重新改版,本文是基于官网最新版本的文档并整合旧文档重新进行全面总结、归纳。 本文主要对官网 快速开始 进行提炼总结,未涉及部分将在后续章节陆续补充完善。 go-zero 的 goctl 工具下载 验证 goctl 的安装结果: goctl 一键安装 protoc 、 protoc-gen-go 、 protoc-gen-go-grp

    2024年02月09日
    浏览(48)
  • go-zero系列:接入Prometheus

    参考文档:https://zhuanlan.zhihu.com/p/463418864 https://prometheus.io/download/ 进入下载文件夹,比如prometheus-2.44.0.windows-amd64。 然后双击Prometheus.exe启动软件。 启动后,可以访问 http://127.0.0.1:9090/。就能查看Prometheus后台。 然后重启go-zero项目,能看到输出日志:Starting prometheus agent at 0.0.

    2024年02月16日
    浏览(40)
  • go-zero微服务实战——服务构建

    接上一节go-zero微服务实战——基本环境搭建。搭建好了微服务的基本环境,开始构建整个微服务体系了,将其他服务也搭建起来。 order的目录结构,如下 根目录 api服务 rpc服务 自定义逻辑层logic 自定义参数层models 自定义工具层util api服务和rpc服务都是基于goctl一键生成的,当

    2024年02月14日
    浏览(46)
  • 使用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日
    浏览(64)
  • 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日
    浏览(60)
  • go-zero 是如何做路由管理的?

    原文链接: go-zero 是如何做路由管理的? go-zero 是一个微服务框架,包含了 web 和 rpc 两大部分。 而对于 web 框架来说,路由管理是必不可少的一部分,那么本文就来探讨一下 go-zero 的路由管理是怎么做的,具体采用了哪种技术方案。 路由管理方案有很多种,具体应该如何选

    2024年02月13日
    浏览(33)
  • 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日
    浏览(74)
  • go-zero微服务实战——基本环境搭建

    项目架构来源于go-zero实战:让微服务Go起来。此对该项目有所删减,相对简单适合初学者。 省去了项目中每个服务占用独立docker的过程,省略了docker-compose的构建过程。每个服务是一个独立的程序不依赖与容器。 安装goctl 安装protoc 安装go-zero 生成api标准api服务 生成rpc服务 生

    2024年02月07日
    浏览(44)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包