Blog

背景

我们的项目是一个基于Kubernetes的云原生项目,会使用到Kubernets的一些组件和依赖。

最开始的项目依赖大概是这样的:

require (
	git.woa.com/khaos/pkg v1.4.3-0.20220819031955-4ad837d439ef
	github.com/ClickHouse/clickhouse-go v1.4.8
	github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0
	github.com/gogf/gf/v2 v2.1.4
	github.com/golang/mock v1.4.3
	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
	github.com/json-iterator/go v1.1.10
	github.com/modern-go/reflect2 v1.0.1
	github.com/olekukonko/tablewriter v0.0.5
	github.com/opencontainers/go-digest v1.0.0
	github.com/robfig/cron/v3 v3.0.1
	github.com/sirupsen/logrus v1.7.0
	github.com/smartystreets/assertions v1.0.1
	github.com/smartystreets/goconvey v1.6.4
	github.com/spf13/cobra v1.1.3
	github.com/tencentyun/cos-go-sdk-v5 v0.7.35
	github.com/tencentyun/tcecloud-sdk-go v3.0.8+incompatible
	go.opentelemetry.io/otel v1.7.0
	go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a
	golang.org/x/tools v0.1.11-0.20220504162446-54c7ba520b92
	google.golang.org/grpc v1.33.1
	google.golang.org/protobuf v1.27.1
	gopkg.in/yaml.v2 v2.4.0
	k8s.io/api v0.19.8
	k8s.io/apimachinery v0.19.8
	k8s.io/client-go v11.0.0+incompatible
)

replace (
	google.golang.org/grpc => google.golang.org/grpc v1.29.1
	k8s.io/api => k8s.io/api v0.19.6
	k8s.io/apimachinery => k8s.io/apimachinery v0.19.6
	k8s.io/client-go => k8s.io/client-go v0.19.6
)

其中的replace语句是由于项目依赖的内部服务所以依赖的kubernetes api版本比较低,短期内无法升级,因此只能添加replace语句来workaround。这种低版本的组件依赖也提高了后面第三方组件的版本冲突风险。

引入ArgoWorkflow服务依赖

随着项目的发展,业务上需要流程编排服务。当然作为大自然的代码搬运师,我们从github上找到了适合的、贴合我们云原生理念的ArgoWorkflow服务。它作为独立的服务运行,我们只需要在当前的项目中依赖其SDK即可,但是在依赖SDK的过程中出现了组件版本冲突。先看看我们有问题的项目依赖:

require (
	git.woa.com/khaos/pkg v1.4.3-0.20220819031955-4ad837d439ef
	github.com/ClickHouse/clickhouse-go v1.4.8
	github.com/HdrHistogram/hdrhistogram-go v1.1.2
	github.com/argoproj/argo-workflows/v3 v3.1.5
	github.com/argoproj/pkg v0.9.1
	github.com/aws/aws-sdk-go v1.33.16
	github.com/go-resty/resty/v2 v2.7.0
	github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0
	github.com/gogf/gf/v2 v2.1.4
	github.com/golang/mock v1.4.3
	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
	github.com/json-iterator/go v1.1.10
	github.com/modern-go/reflect2 v1.0.1
	github.com/olekukonko/tablewriter v0.0.5
	github.com/opencontainers/go-digest v1.0.0
	github.com/robfig/cron/v3 v3.0.1
	github.com/sirupsen/logrus v1.7.0
	github.com/smartystreets/assertions v1.0.1
	github.com/smartystreets/goconvey v1.6.4
	github.com/spf13/cobra v1.1.3
	github.com/tencentyun/cos-go-sdk-v5 v0.7.35
	github.com/tencentyun/tcecloud-sdk-go v3.0.8+incompatible
	go.opentelemetry.io/otel v1.7.0
	go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a
	golang.org/x/tools v0.1.11-0.20220504162446-54c7ba520b92
	google.golang.org/grpc v1.33.1
	google.golang.org/protobuf v1.27.1
	gopkg.in/yaml.v2 v2.4.0
	k8s.io/api v0.19.8
	k8s.io/apimachinery v0.19.8
	k8s.io/client-go v11.0.0+incompatible
	k8s.io/component-base v0.19.6
	sigs.k8s.io/yaml v1.2.0
)

replace (
	google.golang.org/grpc => google.golang.org/grpc v1.29.1
	k8s.io/api => k8s.io/api v0.19.6
	k8s.io/apimachinery => k8s.io/apimachinery v0.19.6
	k8s.io/client-go => k8s.io/client-go v0.19.6
	k8s.io/code-generator => k8s.io/code-generator v0.19.6
	k8s.io/component-base => k8s.io/component-base v0.19.6
)

执行 go mod tidy 没有问题,但是编译的时候会报以下错误:

看起来像是第三方组件版本不兼容问题引起。当项目依赖很多第三方组件的时候,如果不同的第三方组件又彼此依赖到另一个相同的第三方组件A并且版本不同时(如12),Golang的版本管理机制将会使用其中高版本(版本2)的组件A来执行构建。当组件A的不同版本之间存在兼容问题时(版本12不兼容),那么依赖低版本(版本1)的第三方组件在构建时将会出问题。

这个问题在Golang中比较常见,特别是在依赖的第三方组件越多时,这种风险将会变大。如果依赖的第三方组件版本越低,这种风险也会越大。但是对于业务项目而言,一般依赖了一个第三方组件,在项目运行稳定的情况下几乎很难去升级组件的版本。所以这种组件版本依赖冲突问题,往往也只有在项目引入新组件的时候容易出现。

我们对其中kubernetes经过了一系列版本依赖分析,找到了这些依赖中共同依赖的组件Aklog。因此我们通过加了一个replaceworkaround该问题:强制将klog的版本升级到v2.60.0

replace (
	k8s.io/klog/v2 => k8s.io/klog/v2 v2.60.0
)

这个问题看似告一段落。虽然replace的语句丑陋,但能快速解决问题,使得项目进度能够继续开展。虽然我们也有更完美的解决方案,即内部相关项目都升级kubernetes api的版本,但这种方案成本较大,难以快速解决问题。因此我们在项目的开发中往往会采用性价比高的折中方案。我们在解决问题的时候,往往需要从更高层次去分析问题,特别是成本衡量、投入产出比的因素,不能太关注于问题本身。

引入ArgoCD服务依赖

随着项目的发展,我们又需要一个CD服务,所以我们引入了ArgoCD服务,当然这个时候我们又要引入ArgoCDSDK,于是又开始遇到第三方组件各种版本兼容问题。我们的同学经过几天的摸索,搞出来以下组件依赖和replace版本替换:

require (
	git.woa.com/khaos/pkg v1.4.3-0.20220819031955-4ad837d439ef
	git.woa.com/maxqzhu/argocd-sdk v0.0.0-20220919094321-a21a39049255
	github.com/ClickHouse/clickhouse-go v1.4.8
	github.com/HdrHistogram/hdrhistogram-go v1.1.2
	github.com/argoproj/argo-cd/v2 v2.0.4
	github.com/argoproj/argo-workflows/v3 v3.1.5
	github.com/argoproj/pkg v0.9.1
	github.com/aws/aws-sdk-go v1.33.16
	github.com/clbanning/mxj/v2 v2.5.6 // indirect
	github.com/evanphx/json-patch v5.6.0+incompatible // indirect
	github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
	github.com/go-git/go-billy/v5 v5.3.1
	github.com/go-git/go-git/v5 v5.4.2
	github.com/go-resty/resty/v2 v2.7.0
	github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0
	github.com/gogf/gf/v2 v2.1.4
	github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
	github.com/golang/mock v1.4.4
	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
	github.com/json-iterator/go v1.1.10
	github.com/mattn/go-colorable v0.1.12 // indirect
	github.com/modern-go/reflect2 v1.0.1
	github.com/olekukonko/tablewriter v0.0.5
	github.com/opencontainers/go-digest v1.0.0
	github.com/robfig/cron/v3 v3.0.1
	github.com/sirupsen/logrus v1.7.0
	github.com/smartystreets/assertions v1.0.1
	github.com/smartystreets/goconvey v1.6.4
	github.com/spf13/cobra v1.1.3
	github.com/stretchr/testify v1.7.1
	github.com/tencentyun/cos-go-sdk-v5 v0.7.38
	github.com/tencentyun/tcecloud-sdk-go v3.0.8+incompatible
	go.opentelemetry.io/otel v1.7.0
	go.starlark.net v0.0.0-20210602144842-1cdb82c9e17a
	golang.org/x/net v0.0.0-20220621193019-9d032be2e588 // indirect
	golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
	golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 // indirect
	golang.org/x/tools v0.1.11-0.20220504162446-54c7ba520b92
	google.golang.org/grpc v1.33.1
	google.golang.org/protobuf v1.27.1
	gopkg.in/yaml.v2 v2.4.0
	gopkg.in/yaml.v3 v3.0.1 // indirect
	k8s.io/api v0.20.4
	k8s.io/apimachinery v0.21.1
	k8s.io/client-go v11.0.1-0.20190816222228-6d55c1b1f1ca+incompatible
	k8s.io/component-base v0.20.4
	sigs.k8s.io/yaml v1.2.0
)

replace (
	google.golang.org/grpc => google.golang.org/grpc v1.29.1
	k8s.io/klog/v2 => k8s.io/klog/v2 v2.60.0
)

replace (
	github.com/argoproj/gitops-engine => github.com/argoproj/gitops-engine v0.2.2
	k8s.io/api => k8s.io/api v0.19.6
	k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.19.6
	k8s.io/apimachinery => k8s.io/apimachinery v0.19.6
	k8s.io/apiserver => k8s.io/apiserver v0.19.6
	k8s.io/cli-runtime => k8s.io/cli-runtime v0.19.6
	k8s.io/client-go => k8s.io/client-go v0.19.6
	k8s.io/cloud-provider => k8s.io/cloud-provider v0.19.6
	k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.19.6
	k8s.io/code-generator => k8s.io/code-generator v0.19.6
	k8s.io/component-base => k8s.io/component-base v0.19.6
	k8s.io/component-helpers => k8s.io/component-helpers v0.19.6
	k8s.io/controller-manager => k8s.io/controller-manager v0.19.6
	k8s.io/cri-api => k8s.io/cri-api v0.19.6
	k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.19.6
	k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.19.6
	k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.19.6
	k8s.io/kube-proxy => k8s.io/kube-proxy v0.19.6
	k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.19.6
	k8s.io/kubectl => k8s.io/kubectl v0.19.6
	k8s.io/kubelet => k8s.io/kubelet v0.19.6
	k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.19.6
	k8s.io/metrics => k8s.io/metrics v0.19.6
	k8s.io/mount-utils => k8s.io/mount-utils v0.19.6
	k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.19.6
)

可当执行编译的时候,报错依旧,老泪纵横:

当同学几经波折准备放弃,开始采用骚操作来WorkAround的时候(将依赖的SDK剥离出来单独维护)。秉着坑踩得越多,责任也就越大。在一个月黑风高的夜晚,我加入了进来一起研究,毕竟,这个项目还要长久维护的。

这个问题看起来是由两个组件的版本不兼容引起的,处理起来估计会更棘手一些。

……

此处省略一万字。

……

经过一系列复杂的版本分析、依赖分析、兼容处理,对于此次版本冲突问题,加了以下replace语句来解决:

replace (
	github.com/argoproj/argo-cd/v2 => github.com/argoproj/argo-cd/v2 v2.0.1
	github.com/bombsimon/logrusr => github.com/gqcn/logrusr v1.3.0
	github.com/go-openapi/spec => github.com/go-openapi/spec v0.17.0
	sigs.k8s.io/kustomize/v2 => sigs.k8s.io/kustomize/v2 v2.1.0
)

其中大家应该注意到一个组件 github.com/gqcn/logrusr ,这个组件是我从 github.com/bombsimon/logrusr 项目fork的一份,目前是放到了github上。并升级了内部依赖的 github.com/go-logr/logr 组件版本到当前项目整体依赖比较适中的版本v1.2.3,即将整体的冲突的版本通过强制升级的方式来解决。在执行强制升级的时候,组件之间依赖的接口和方法兼容非常重要,不是简单升级版本那么简单。此外,虽然本次组件版本冲突不得不维护一个自定义的组件仓库,但维护一个基本不变的组件比维护一个可能变化的组件成本和风险会更小一些。

总结

Golang开发中,这种版本冲突问题几乎很难避免,项目对三方组件依赖的越多,这种风险就越大。

此次分享的主要目的:

  • 解决问题的思路:分析问题,提出方案,选择方案
  • 解决问题的目的:更高层次思考问题、不局限问题本身
  • Golang开发中,常见的类似的问题如何处理的参考
  • 对于组件开发,特别是GoFrame框架开发而言,站在使用者角度考虑,应当尽量减少第三方组件依赖 https://goframe.org/









大家好,有一段时间没有写博文了,实在因为最近工作过于繁忙,几乎每天都是高负荷运转。


最近,计划中的feature进展有点缓慢,不过每周我都会花3-5天过PR。我最近在处理三项个人认为比较重要feature:

  1. 将结构体属性注释和标签整合,方便接口文档、命令文档编写和维护。也就是说,未来我们的接口文档编写将会更加方便、内容更加丰富。
  2. 通过工具和组件实现多种通信协议的适配。未来,通过现有框架标准的API编写方式,我们将可以通过少量配置和组件的方式,很容易支持HTTP/gRpc/Thift等接口通信协议,然而我们的业务代码不需要任何变化。此外,再结合上面提到的feature,不管是什么接口通信协议,代码也不需要经过改动,接口文档都可以保持一致。
  3. 自动化的客户端生成(HTTP/gRPC)。根据服务端的API接口文档或者API结构定义目录自动生成客户端Go代码。这样客户端与服务端代码完全解耦,API涉及到的所有结构将会递归自动化生成。


最近挺开心的,因为最近大家的PR比较多,goframe就是需要靠社区活跃才能健康发展。未来我也会多推动社区、依靠社区来驱动项目持续健康发展。同时,也希望大家能认识到,开源不易,既然开源了出来,这个开源项目就是属于大家的,属于开源社区的。我也会秉着开放、自由、纯粹的心态,力所能及地和大家一起维护好项目。我们可以做、需要做的事情还有很多很多。目前框架的主体能力已经比较完善和稳定,且在行业已经有了一定的不错的口碑。对于项目的feature和enhancement,我将不会每个都亲自参与,我的精力将集中在以下几个方面:

  1. 重要issue的修复
  2. 重要feature、enhancement的开发
  3. 社区的PR Review和指导
  4. 项目的布道和推广


可以看到,我们社区的开发团队小伙伴也很给力,一起解决项目的issue、提交修复问题的PR、帮助群里提问的小伙伴。我不知道开源精神具体是什么,在工作之外,我们有机会同在一个社区下,一起协作、做一件开心和有意义的事情,也就足够了。对我自己而言,有时工作会感觉到苦闷,但一想到能够有一群共同参与开源创作的小伙伴,有一群欣赏你所参与项目的开发者,也就感觉都不算什么了。




感谢大家的支持!GoFrame荣获了OSC年度评选的最受欢迎项目。

近期收到了奖杯(盒子太厚我直接取出了金币)。

可是这个logo怎么变成了一只熊猫了?








喜报!

GoFrame开源项目获得,2021年度开源中国最受欢迎开源项目奖!

感谢

感谢所有社区团队小伙伴的辛勤付出!

坚持、不停息

让我们继续加油,从跨时代的V2版本开始,继续扬帆起航吧!!




Content Menu

四年,回首,再出发!

大家好啊!

三月很美,自2017年3月开源至今,刚好四年。

最近发了个朋友圈,意想不到,收到大家许多鼓励。

这段时间,对于自己来说算是一个转折点,或者,对她来说亦是如此。

回顾了过往的几年,包括生活的,包括职场的,包括社区的,内心复杂,颇多感慨。

想要说的很多,却又辗转反侧,翻来覆去,难以言怀,算了,就这样吧。

这几年跟大家学到了很多。

感谢你们!

感谢大家!

未来,我们一起,更加努力吧!



感谢 https://gitee.com  ❤️️





新年快乐,牛年大吉!

大家新年好啊!

感谢大家对女碰友框架的认可与陪伴!

我们在过去的日子里经历了许多,

同时,也创造了许多惊艳的成果。

遇到过各式各样的人,

也迈过各种各样的坎。

世界上只有一种英雄主义,

看清生活的真相,

但依然热爱生活。

想与大家说得很多,

但又觉勿需太过表达。

我们从未停歇。

新的一年,咱们就来立个Flag吧:

1、发布一个微服务开发框架项目。

2、组建社区开发团队,实现基本社区驱动。

3、发布英文版本文档,走向国际化。

4、项目贡献者达到100人以上。

欢迎大家共同参与开源贡献,也欢迎大家新的一年共同监督哈!

祝大家新年快乐,牛年大吉!

团队博客开通啦!

大家好啊,我们的团队博客开通啦!🎉

我们会不定期地在这里发布一些与GoFrame相关的发展动态与团队情况,欢迎大家持续关注哦!


感谢大家的认可与支持哟!在2020年度评选中,GoFrame荣获了2020年度开源中国TOP 30开源项目评选!🎉🎉🎉

今天收到了来自于OSC充满爱心鼓励的奖杯,是不是很可爱呀!😊

开源不易,有你们的理解和支持,幸福满满💓!

感谢所有参与项目开发的小伙伴们,爱你们💖!

GF, YES!





相关连接:

https://www.oschina.net/question/2918182_2320114