2016年底,我和团队开始构建一个全新的平台。想要实现开发人员的终极梦想——没有遗留代码,无需担心向后兼容的问题,最好的一点是,可以自由选择最适合工作的正确技术。三年后,在很多痛苦和折磨之后,我现在可以做一些反省了。在深入探讨之前,我想宣布两件事。

  • 马后炮意义不大
  • 没有万能的方案

我们无法知道如果选择不同的方式结果是否会不同,但是在之前没有重视的领域/架构方面的确有一些非常重要的建议。现在,我们自认为理解得更透彻了。因此对于那些想要做类似项目的人来说,提出一些我很后悔自己当初没有遵守的建议。

忽略的建议#1:康威定律康威定律认为系统架构会不可避免地以某种方式重构所在企业的组织架构。

随着平台的演进,我们编写并运维着30~40个微服务。其中一些用不同的语言重写过。自从开始构建起,熟练的后台开发人员从来没有超过一名。因为我们一直是小而紧凑的团队,每个开发人员都得在所有服务上工作。团队一起制定架构决策,on call意味着处理任何领域的可能问题。从过高的服务/开发人员比例上你可能会猜到,我们的服务最终是看上去“分离“实际上紧耦合的。这对我们伤害很大。因为耦合紧,所以一直通过同一时间“仅仅“部署跨服务的变更来降低工作量,这直接违反了独立部署[1]的原则。

忽略的建议#2 你不是Google

微服务的一大好处是可以独立扩展。在最初的设计里,我们已经将在规模加大时可能成为瓶颈的组件分离了出来。事实证明,我们所预计的规模远远超出了现实里可能遇到的任何规模。实际上,我们不仅仅凭猜测确定域边界,而且每个服务都有一定的overhead。我们为运维功能运行一系列的sidecar容器和Kubernetes的DaemonSet(比如监控和日志)。这导致我们在这些支撑的基础架构上花费的资源比实际应用程序还多,而且多很多。我这里并不是说使用单体应用更好,但是如果可以重新选择从更为简单的架构开始,我会:

  • 打散,因为我们现在对领域更为自信,可以找到正确的抽象方式
  • 收集真正性能瓶颈处的数据,证明真的是一个问题
  • 重叠支撑基础架构来节省经费

忽略的建议#3:你仍然不是Google

微服务的另一个好处是可以为工作选择最佳的工具。我们选择了很多语言,运行着使用Python,NodeJS和Golang编写的服务。总的来说这样很不错,但是要编写共享库的时候就是个噩梦了,因为同样的功能得用三种不同的语言都实现一遍。我的确相信应该实验不同的工具,但是最终的所有东西都需要能够支撑生产环境并且长期维护。如果编写内部共享库,让服务都用这个库,这就不再是实验而已了。最终我们只能选择单一语言。而结果也很好。尽可能多地实验,但是一定要构建出可以重复使用的主要技术栈,一致性也很有价值。如果你使用相同的工具运维所有服务的时候(比如,Web服务器使用数据库连接),这就尤其重要。忽略的建议#4:所有东西都是权衡微服务架构也有很多缺点。我在这里不会详细介绍(有人已经写过文章[2]了),不过我觉得理解你将要做什么很重要。如果我们坐下来比对优缺点,很可能会发现只有在有多个后台团队,使用不同的软件解决不同问题时微服务架构才有价值。

教训

我们花费了时间和精力转回了之前的道路。在2019年1月份,我们往回一步检视架构,确定了10个耦合很紧的服务,将它们整合成1个服务。
我们也已经缓慢地构建了Python服务,以及一个Golang服务。有些情况下这意味着使用NodeJS重写。最终需要维护的是一个共享的JavaScript库。

收获

如果我可以回到过去,会给当时的自己这些警告:

  • 为已知的问题做设计,对未来的猜测要谨慎
  • 从少数大型服务开始,并且仔细地设计边界。首要法则是一个微服务 比两个要好,除非你真的能找到拆分它们的强烈理由。当然,总是有很多有效的理由,但是确保在决策之前真正理解这些理由。
  • 当实验以及构建MVP服务时,要非常清楚地知道不会做什么并且要坚持住。不然很容易就会陷入维护错误方案的陷阱里。

相关链接:

  1. https://youtu.be/PFQnNFe27kU?t=1352
  2. https://martinfowler.com/articles/microservice-trade-offs.html

原文链接:https://itnext.io/microservices-c8b5dbdd58b8

Comments are closed.