大家好,我是煎鱼。
我有一个好朋友小咸鱼,他们经过服务化拆分《微服务的灾难:拆的很爽,但服务太小》的磕磕碰碰后,由于一个人负责 N 倍数的服务,多开 IDE,深夜加班,一个不小心,犯迷糊了,就误操作,逻辑写错服务了,就出事故了。
随后,在小咸鱼的 Leader 带领下,经过会议室多轮争吵后。总算是重新整理、设计了一版服务边界,分分合合,原本拆了的合回去,又增添了新服务组合。
于是,小咸鱼又可以愉快的 hello world 起来了。这难道就是事故驱动开发的威力!
但,没开心两天。又遇到了新的问题...
服务依赖
一般来讲,在拆分为微服务后。经历一段时间的业务规模发展后,我们的服务都是具有比较多的依赖。像是:
![](https://i-blog.csdnimg.cn/blog_migrate/a5d9e82e58e222cddcdd09bdb63fecb1.jpeg)
我们发现业务初始依赖的是 ServiceA,结果跑了一段时间后。服务依赖越来越多,还出现了更进一步依赖,Service A 依赖 B、C,他们背后又调用了一大堆的服务。
同时 ServiceA 依赖的服务,还存在跨业务组的情况,也就是一个普通的业务调用,可能关系到多个业务组的协调:
![](https://i-blog.csdnimg.cn/blog_migrate/32ea24ea4966fa44513e3da883e840cb.jpeg)
虽然从图示来看,只有 3 个业务组。但,一个月前可是都是依赖自己。
说明小咸鱼作为业务组 A 的维护方,他所依赖的业务团队正在不断地增大,大家都在用力产生新的服务依赖。
假以时日,这个服务的依赖必然变的非常多(不过,小咸鱼并没有意识到这一点)。
开发环境
终于,在小咸鱼维护了一段时间后。这一个业务产品,成功走过了尝试期。他有了好几位新同事,在迭代的过程中,联调的诉求出现了。
小咸鱼麻利的利用组织里的公共开发环境搭建起了服务:
![](https://i-blog.csdnimg.cn/blog_migrate/9ee2982a5df76dc4191bb0868785abb3.jpeg)
小咸鱼辛辛苦苦的找了其他几个组,让大家都往上面 Push 自己的服务,解决了这一个迭代的联调的问题。
但,好景不长。业务压力总是大的,大家都维护着复数的 f 分支。这时候就遇到了新问题:
![](https://i-blog.csdnimg.cn/blog_migrate/32cc4a02100b8860f3ab7673fa4ee76f.jpeg)
业务组A,期望依赖的是:
ServiceA:v0.1.0。
ServiceB:v0.2.0。
ServiceC:v0.3.0。
业务组B,期望依赖的是:
ServiceA:v1.1.0。
ServiceB:v1.2.0。
ServiceC:v1.3.0。
好家伙,在同一个集成开发环境中,大家期望依赖的服务版本压根不一样。联调起来挺费劲,甚至存在一些风险。
例如:你在开发环境,联调时你以为你依赖的 ServiceB 的 v0.2.0 版本,跑的也好好的。结果其实其他业务在晚上把他更新为 v0.5.0 版本了,接口还是兼容的,但内在逻辑是变了的。当然,你也没有发现这个问题,因为是 “细微” 的修改。
但上到测试环境后,很快就会出现被测试同学打回来的情况。以此往来多了,你就会成为团队里质量不好的那一位 TOP1 了...
这问题怎么解决呢?
解决方案
针对微服务架构下的开发环境,核心还是要看公司内的基础设施建设的怎么样。
公共 dev 分支
若只是基础底蕴不够深厚,钞能力也不够的,一般会采取 dev 分支合并的方式。也就是在 ServiceA 上建立 dev 分支,专门用于集成开发环境。由开发同学配合脚本等,进行维护和应用。
虽然容易出现不同分支,影响到同一块的内容。但由于同一个 Service 一般会由 1~3 个人(小团队)经手维护,都坐在附近,基本可以控制冲突。
甚至有的小伙伴,为了谨慎起见。合并前会反向合并到自己 f 分支,再跑一遍自己的自动化接口测试,以确保正确。
当然,测试环境也是一样的问题。在业务迭代的过程中,常常有多个功能在同时开发,会拉多个分支。
如果开发、测试环境只有一套,就意味着要么团队内部商量好时间。
轮流使用测试环境,要把不同功能的分支代码合到某个分支再统一解冲突,再联调和测试。
这个方案只能治标,但不能完全治本。
多泳道环境
说白了,可能还是需要多套环境来解决。当你期望是某一个泳道用来发布某一个特性分支时。对应的发布系统就会给其相关联的组件打上泳道标识,自然也就能知道依赖的是谁了。
如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/8c647f71350ed17a7c525e491f2f8170.jpeg)
一般客户端会带上泳道标识的 Header,再一路透传下去。所有相关 Proxy 会根据 Header 内的标识进行选择。
考虑到有的服务在功能特性中并没有变更,因此会有 master 和功能泳道的区别,会再根据 Proxy 的规则进行选择。
当然在这块也可以结合服务发现的机制去做,具体看技术选型上的差距了。
总结
微服务化后,N 个服务如何联调,就是开发人员的一个大头疼问题。而人一多,业务压力一大,很可能会出现一个服务同时多个分支并行开发的情况。
也就会导致开发、测试环境同一时间遇到这个烦人问题,我们可以通过公共分支,又或是多泳道的方式解决。
但两者都存在不同程度的缺点:
公共环境,需要公共分支,需要人为的一定介入。
多泳道环境,需要的基础设施建设较多,同时 MySQL、Redis 等公共介质也是一个问题,成本也是运维的一个考虑因素。
没有任何一个方案是绝对的银弹。
你们又是怎么思考,怎么解决这个问题的呢,欢迎大家在评论区留言!
关注煎鱼,吸取他的知识 ????
你好,我是煎鱼。高一折腾过前端,参加过国赛拿了奖,大学搞过 PHP。现在整 Go,在公司负责微服务架构等相关工作推进和研发。
从大学开始靠自己赚生活费和学费,到出版 Go 畅销书《Go 语言编程之旅》,再到获得 GOP(Go 领域最有观点专家)荣誉,点击蓝字查看我的出书之路。
日常分享高质量文章,输出 Go 面试、工作经验、架构设计,加微信拉读者交流群,记得点赞!