解决 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
的问题,服务也可以访问,就很诡异。
如果是老手,看到这里 ,应该知道问题会出在哪里。我是菜鸟,就只好一步步分析。
如果想直接看解决方法的,到最后,下面是我的分析过程。
排查
当出现问题的时候,想的就是包的问题,不是我的问题。就去 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 的启动方式,也是往上找的,没问题呀。启动也 ok,go-zero 也注册得上去。
再看看 etcd 到底哪里出的问题,又去看了下源码。
上面这个方法报错,因为 Auto sync endpoints failed
是一直出现的,说明 go-zero 里面有个地方,应该也配置了 AutoSyncInterval
,所以这边会跑这个。下面是,go-zero 调用的地方,其实也就是初始化一个 etcd client 的传参。
此时此刻很无奈,感觉不知道往哪里思考。服务也没报错,也能调用,就又很不想去分析。这种问题就很折磨,关键日志很多,很丑。还是多找找吧,去看 go-zero 的 issue,看到也有人提这个问题,不过都没有什么解决方案。去看 etcd 的 issue,也没有看到什么。最后也不知道怎么地,想为什么要一直带着 go-zero 去想这个问题,我自己写一个 etcd client 试一下不就行了。找了个范例,测一下,不就知道是 go-zero 的问题,还是 etcd 起的有问题。
范例我就不详细列了,可以去看我的另一篇 【etcd】docker 启动单点 etcd_非晓为骁的博客-CSDN博客 的文章。
同样也设置了 AutoSyncInterval
,结果难受香菇,竟然也会报这个错误。
这里有一个很重要的点,不要出了问题就局限在你用的框架里面,更要会抽丝剥茧,简单地看问题。
这时候说明 etcd 部的就是有问题的,只好再看下 docker run 的指令和错误。我把错误,减少到下面这一行,仔细看下,可以看到是服务 dial 0.0.0.0:2379 失败。rpc 服务和 etcd 是在 2 台服务器,访问本地 2379 就是访问容器内 2379,那肯定访问不到呀。关键是 0.0.0.0:2379 拿来的呢?
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 试试。
验证二
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 服务重新注册。
这个是我自己分析的过程及理解,可能这里面还有更深层次的问题,有懂的大佬可以分享一下。
评论