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

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

各种兼容问题


当 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 时,会遇到如下报错:


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 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:


6fb30135cca5cb25cff38db406f463d7.png


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


找不到 grpc.SupportPackageIsVersion6


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


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[1])。


f158d227309a8cb3647b856aaccb1ac3.png


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



解决方案


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


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


如下图所示:


32f7ed4a8acc7ee36dd91215633dc6b4.png


9ec78119edb324a66b256990efab3310.png


拆分为了 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 的相关支持。


ad740a9a058fbd9ca1bcab9683d12c72.png


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


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

总结


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

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


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

相关文章
|
6月前
|
搜索推荐 Go 开发者
Go模块与依赖管理:构建稳定、可维护的项目生态
【2月更文挑战第9天】Go模块是Go语言从1.11版本开始引入的一个新的依赖管理工具,它改变了以往通过GOPATH管理项目依赖的方式,为Go开发者带来了更加灵活、高效的依赖管理方式。本文将深入探讨Go模块与依赖管理的概念、使用方法和最佳实践,帮助读者更好地理解和应用Go模块,构建稳定、可维护的项目生态。
|
4月前
|
存储 Linux Go
GO 项目依赖管理:go module总结
GO 项目依赖管理:go module总结
73 0
|
5月前
|
存储 算法 Go
go语言并发实战——日志收集系统(七) etcd的介绍与简单使用
go语言并发实战——日志收集系统(七) etcd的介绍与简单使用
|
3月前
|
人工智能 IDE Go
go mod 依赖管理
go mod 依赖管理
39 1
|
3月前
|
安全 Go 开发者
掌握 Go 语言的依赖关系管理
【8月更文挑战第31天】
39 0
|
5月前
|
监控 Go
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
|
5月前
|
存储 缓存 JSON
Go Modules:Go语言依赖管理的新篇章
Go Modules是Go 1.11引入的依赖管理标准,解决`GOPATH`的依赖冲突问题。
103 1
|
5月前
|
监控 Go
go语言并发实战——日志收集系统(十一)基于etcd来监视配置文件的变化
go语言并发实战——日志收集系统(十一)基于etcd来监视配置文件的变化
|
5月前
|
存储 JSON 监控
go语言并发实战——日志收集系统(九) 基于etcd的代码重构思考与初步实现
go语言并发实战——日志收集系统(九) 基于etcd的代码重构思考与初步实现
|
6月前
|
存储 Go
Golang深入浅出之-Go语言依赖管理:GOPATH与Go Modules
【4月更文挑战第27天】Go语言依赖管理从`GOPATH`进化到Go Modules。`GOPATH`时代,项目结构混乱,可通过设置多个工作空间管理。Go Modules自Go 1.11起提供更现代的管理方式,通过`go.mod`文件控制依赖。常见问题包括忘记更新`go.mod`、处理本地依赖和模块私有化,可使用`go mod tidy`、`replace`语句和`go mod vendor`解决。理解并掌握Go Modules对现代Go开发至关重要。
126 2