Go etcd 的依赖问题终于解决了。。。

大家好,我是煎鱼。

前几年非常高频的接触到这一堆微服务相关组件:grpc + grpc-gateway + etcd + protobuf + protoc-gen-go,一开始都是相安无事,逐步跟进新版本。

这不,幺蛾子就来了。写这些组件的开发大佬(或公司)都不在一起,各自为政,各有各的想法、喜欢、规范...因此会出互相不兼容,甚至出现了卡脖子的情况。

各种兼容问题

当 etcd 是 v3.3/v3.4,grpc > v1.27 时,经常会遇到各种看着脑壳痛的兼容性问题。

至少但不限于如下几个场景。只是例举几个比较常见的三个兼容错误。

找不到 grpc/naming

找不到 grpc-go 库中的google.golang.org/grpc/naming 包。原因是什么?原因之一是 go.etcd.io/etcd/client 引用到 grpc-go 库中的实验包。

go mod tidy 时,会遇到如下报错:

vbnet 复制代码
go: finding module for package google.golang.org/grpc/naming
go: finding module for package google.golang.org/grpc/examples/helloworld/helloworld
go: found google.golang.org/grpc/examples/helloworld/helloworld in google.golang.org/grpc/examples v0.0.0-20231026203026-8cb98464e599
go: finding module for package google.golang.org/grpc/naming
go: git.xxx.cn/xxx/xxx-common/jy imports
	go.etcd.io/etcd/client tested by
	go.etcd.io/etcd/client.test imports
	github.com/coreos/etcd/integration imports
	github.com/coreos/etcd/proxy/grpcproxy imports
	google.golang.org/grpc/naming: module google.golang.org/grpc@latest found (v1.59.0), but does not contain package google.golang.org/grpc/naming

看到最后的 but does not contain package google.golang.org/grpc/naming。以为是 grpc-go 乱删库,做了不兼容变更。

想着找官方解决一下问题。印象很深刻,人家 grpc-go 表示:我这已经声明是实验性,随时可能删除的了,你不应该依赖他。(不会支持的意思)

找不到 etcd/clientv3/balancer/picker

还是由于 grpc-go 库的实验包在新版本去掉了。会导致 etcd v3.3 出现:undefined: balancer.PickOptionsundefined: resolver.BuildOption 的相关错误信息:

go 复制代码
$ go get go.etcd.io/etcd/clientv3
# github.com/coreos/etcd/clientv3/balancer/resolver/endpoint
../../go/pkg/mod/github.com/coreos/etcd@v3.3.18+incompatible/clientv3/balancer/resolver/endpoint/endpoint.go:114:78: undefined: resolver.BuildOption
../../go/pkg/mod/github.com/coreos/etcd@v3.3.18+incompatible/clientv3/balancer/resolver/endpoint/endpoint.go:182:31: undefined: resolver.ResolveNowOption
# github.com/coreos/etcd/clientv3/balancer/picker
../../go/pkg/mod/github.com/coreos/etcd@v3.3.18+incompatible/clientv3/balancer/picker/err.go:37:44: undefined: balancer.PickOptions
../../go/pkg/mod/github.com/coreos/etcd@v3.3.18+incompatible/clientv3/balancer/picker/roundrobin_balanced.go:55:54: undefined: balancer.PickOptions

不得不说,这个 BUG 我还给 etcd 提了 issues 和 pr:

最终合并了。(但是 etcd v3.5 当年发布的太慢了,没等到...)

找不到 grpc.SupportPackageIsVersion6

protoc-gen-go 与 grpc 版本不兼容。会出现如下报错:

go 复制代码
Getting error undefined: grpc.SupportPackageIsVersion6 and undefined: grpc.ClientConnInterface

本身这个问题,只需要升级 grpc >= 1.27 就可以了。但如果你使用了 etcd sdk,又会前面的 etcd 版本依赖问题,程序会陷入麻烦的升又升不得,降也降不了。

最后还是将 protoc(protoc-gen-go) 降级为 v1.3.2,grpc 保持在 v1.26,这样 etcd v3.3 的依赖才能正常使用。

背后缘由

细心的同学会发现,归根到底还是和 etcd v3.3 扯上关系,grpc 就没法升级到 v1.27 以上。其他所有关联的 protoc、grpc-gateway 的版本都没法继续推进。

当你想用 go module 来做各种兼容管理时,会发现 etcd v3.3 根本没有 go module...

etcd v3.4 虽然有 go.mod,但也无法拉取和使用(原因详见:etcd-io/etcd/issues/11154)。

etcd 官方的响应也是不太积极的。猜测是积重难返,比较难解决。

解决方案

社区等了许多年,现在终于有了解决办法。etcd v3.5 已经正式支持了 go module!

etcd 将之前的模块按功能做了领域划分,把之前各种的低版本依赖、循环依赖等问题都处理了。

如下图所示:

拆分为了 api、client、raft、server、etcdctl、bbolt 等独立的 Go 模块。不会像老版本一样交叉影响。

如果你是新项目,建议无脑使用 etcd v3.5 以上版本。千万别用 v3.3/v3.4 及更低的!

比较无奈的一点

可能有的同学以为皆大欢喜了?其实并不。

他的模块化改造成功仅限于 etcd v3.5 的版本。而历史项目,如果你是使用 etcd v2 store,那么很抱歉。

etcd 老版本(v3.3/v3.4 等)是没有变动的,在 v3.5 的新版本(包含最新的文档)中都在开始在逐步去除 etcd v2 的相关支持。

如果仍然在使用 etcd v2 的同学,建议进行数据迁移用 v3。这样可以避免很多技术上的问题。

迁移不方便的话,除了各种 replace 和锁版本外。如果你使用的 etcd 功能非常基础,也可以自己实现一个简易版的 SDK。

总结

etcd 的这个历史问题已经存在了好几年,一直处理的慢慢吞吞。甚至影响到了 Go 生态圈的一些技术选型问题。

前几天有同学反馈 tidb 里引用了 cloud.google.com/go/pubsub 库,而该库又依赖了 grpc 的较高的版本。从而导致原有卡在 grpc v1.26 的应用又出现了问题。才回过头来看看。

在新版本中,etcd 的依赖问题终于解决了。真的是,这值得被我们记住!虽然他老版本依然没处理...

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

Go 图书系列

推荐阅读

相关推荐
梦想很大很大3 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰8 小时前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘12 小时前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤13 小时前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt111 天前
AI DDD重构实践
go
Grassto3 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto4 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室5 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题5 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo
啊汉7 天前
古文观芷App搜索方案深度解析:打造极致性能的古文搜索引擎
go·软件随想