最近,我们开发团队的开发计划出现了小停顿。技术部门认为,现在是将应用从单体架构迁移到微服务的最佳时机。图片来自Pexels经过一个月的准备和调查,我们取消了迁移并仍在使用Monolith。对我们来说,微服务不仅没有帮助,反而影响开发计划。大约一年前,我们了解了微服务,但惊讶地发现它对我们不起作用。这篇文章把我们的经验写出来,可能对大家有参考意义。发现问题和早期妥协我们严重依赖第三方。我们的应用程序集成了外部现有产品和业务规则,以向用户呈现友好的UI。客户端是一个UWPApp,后台有相应的服务来和第三方域进行数据交换。对第三方的依赖严重影响了我们对微服务的选择。例如,应用程序经常需要在不同域之间传输功能,使第三方域看起来像一个完全不同的域,如果我们之间只有一个服务,这还不算太糟糕。然而,当分解成多个微服务时,整个域交换看起来很奇怪。我们的微服务是不是和第三方分解的不一样?我们是否重复了所有服务的前端和后端需求?还是我们自己分解了微服务,还需要一个微服务来获取第三方的信息?所有这些问题似乎都偏离了微服务指南。我们与第三方密切合作,并经常合作发布。微服务的好处是每个团队可以独立发布服务不受影响,而跨公司合作就失去了这个好处。微服务的另一个优势是每个团队只需要完整设计自己的业务问题。而对于我们来说,作为一个完全独立于第三方的公司团队,这种重构似乎不太可行。我们无法有效地分离微服务。我们真的不知道从哪个单体应用开始。因此,我们在域模型之间进行连接以决定要创建哪些微服务。但是,一旦这样做,发现很多共享的业务逻辑影响了微服务领域的划分。如果把微服务拆分成更小的,只能带来更多的耦合关系,到处都需要消息总线,消息可能会爆炸。原因是我们的整体应用程序服务于一个业务逻辑。为了方便用户,我们已经创建了很多跨域和跨组的工作流程,并且在过去的四年中,UI本质上一直在将事情整合在一起。我们还误解了微服务是如何隔离的,并低估了在服务之间选择正确边界的重要性。唯一能做的就是为了实现一个标准的功能,所有相关的微服务需要同时升级,这就要求每个微服务不能由一个团队拥有。共享微服务我们有大约12名开发人员,分布在两个职能团队和一个支持团队中。工作波动很大,没有专门的团队负责。所有团队同时接触同一批代码是很正常的,一个微服务不能分配给一个团队。在考虑架构时,记住康威定律很重要,这意味着软件架构将通过模仿组织和团队结构来发展。微服务架构对于负责不同业务逻辑的不同团队更有效。但是共享代码功能的工作模式最好采用单体架构。该平台还没有准备好,问题意味着在IIS中同时运行微服务和单体应用至少六个月。我们不会访问微服务相关的工具,比如容器、Kubernetes、服务总线、API网管等,这意味着与其他微服务的通信是非常困难的。因此,我们决定每个微服务复制与存储层转换相关的读取服务的共享逻辑。因为服务不能正常拆分,意味着要承担大量的复制工作量。比如一些复杂的基础业务逻辑,至少要复制粘贴维护4个规划的微服务。没有清晰的未来图景。开发团队在六个月内只有一个大概的想法,业务变更频繁(业务变更需求也是家常便饭),这让微服务的不确定性更大,因为即使在短期内,也无法预测未来。出现什么链接。微服务之间的复杂度会不会增加?耗时数月才分离的服务会回到过去吗?虽然我们今年早些时候做了一些PoC,但由于业务需求的变化不得不放弃。该架构是紧密耦合的。我们只有很窄的时间窗口,刚好可以把单体应用分解成列出的微服务,没有多余的时间去处理可能发生的变化,也没有B计划,我们自己卡住了。因为我们在策划阶段就发现了很多问题和挑战,更不用说实施阶段了,开发团队压力很大。风险和时间压力加剧了缺乏经验,事实上,架构师和实施专家都没有任何特殊经验,也没有可用的标准工具,我们不得不自己实施。在和其他微服务高手交流之后,他们也发出了很多警告,并且给出了很多以前没有的架构建议,指出了我们在领域模型之间划线的顺序。到目前为止,由于时间紧迫和工作量大,我们的计划已经包含了许多不同于标准微服务的折衷方案。缺少高手,这更像是一条不归路,开发团队也越来越着急。再次,折磨我们的目的来解决痛点一旦困难摆在面前,我们就失去了目的,我们停下来意识到我们还没有弄清楚为什么要这样做。我们没有列出痛点,也不清楚这样做是否能解决它们。更何况,微服务可能会给我们带来新的问题。我们开始反思,我们能从中得到什么好处?它能解决什么问题?我们召开了更多的会议来讨论它,但从来没有一个明确的答案。最后发现我们在讨论微服务的过程中忽略了一个很重要的痛点,也没有足够的时间来解决这个问题,就是不能考虑微服务或者其他的东西。潜在的好处是什么这时候,我们开始反思一般意义上的微服务的好处?自治微服务允许团队控制整个堆栈以提供功能。这种分离将减少不同团队之间的协作次数,而不会影响彼此的工作。让团队更专注在单体应用中,团队可以专注于所有任务。使用微服务,您就是业务流程方面的专家。他们会了解自己领域的业务规则和需求,知道软件栈是如何构建的,并且在发生变化时非常有信心。易于扩展使用微服务,您可以根据性能需求扩展服务。在单体应用中,虽然服务也可以水平扩展,但是单体应用的模块是不能独立扩展的。微服务粒度可以增加或减少服务能力。也许参与其他工作,或者在发现性能问题时稍作休息。易于回滚每个特性只需修改单个微服务,即可回滚,不影响其他团队工作。此外,微服务还可以降低单个错误对整个系统的影响。易于迭代使用增强系统,每次发布都是耗时且有风险的,需要大量工作来处理每个发布。微服务可以减少沟通时间和成本,团队可以自主决定合适的时间。采用最好的技术团队依靠微服务来选择最好的技术解决方案。单体很难升级。易于升级大型应用程序升级不是一件容易的事。尤其是在跨多个团队协作时。相互隔离的微服务一次只能升级一个服务,更容易控制风险。风险保护微服务可以将经常变化的服务与很少变化的服务分开,降低意外发生的风险。降低粒度小型化服务更易于理解并保持设计一致。相比之下,单体应用会因为不同团队的分歧而带来不一致性。优点总结微服务有很多优点。但是我们从中得到了什么?最终,这些优势只能为了一个无法更改或妥协的架构而放弃。我们失去了微服务带来的隔离。与第三方的协作减少了服务无关性带来的好处。微服务并不是所有的优势,还有一长串需要考虑的问题。例如,日志记录、监控、异常处理、容错、回滚、通信、消息格式、容器、服务发现、备份、遥测、警报、跟踪、工具、共享、文档、扩展、时区、阶段、API版本、网络延迟、健康检查、负载均衡、CDC检测等。没有微服务平台,我们就不得不自己面对上面列出的所有问题。我们因为痛点不得不转向微服务,但不仅不能从中受益,还面临着转向微服务带来的一堆问题。我们为什么要打扰?微服务只是名义上的。下图是我们目前的单体应用与微服务的对比。从架构的角度来看,新架构非常类似于单体,各个组件仍然紧密耦合。也许我们只是使用微服务这个标签。单体就一定不好吗?好像“单体”就是落后,“微服务”就是先进。但是从开发团队的角度来看,我们的单体应用运行的很好,基本上没有任何问题。我们有一个很好的CI/CD配置,易于配置和回滚。分支和测试策略可确保提前解决问题。Dejavu这时候,似乎有种似曾相识的感觉。我之前在这个行业的经历中也有过类似的经历,但从来没有被称为微服务。虽然不完全符合微服务的规则,但确实解决了问题,带来了类似的好处。一个由5人组成的小团队领导着一个由200名开发人员组成的团队。这是一个巨大的C#应用程序,大约5%的工作在整体上共享,其余的在两个节点之间共享。我们也不喜欢单体,工作、编译、测试都很慢,而且架构变化很快,经常看到不同的同事出现。有时整个项目的延迟是因为一个从未听说过的同事退出,技术更新需要几个月,因为它们需要与整个公司同步,拉取申请需要整个系统批准数周。同时,有两个小服务我们可以很好地控制、部署和架构。一旦出现性能问题,实例数就会受到质疑,直到解决底层问题,其他团队很少会受到困扰。我们的团队主导着前端和后端开发语言的选择。简而言之,我们非常专注于一个非常狭隘的业务逻辑,每个人都成为了专家。我们越了解技术之外的微服务,就越发现它不适合我们。我们是否为了技术而过于技术化?还有很多问题没有考虑到:是否有专门负责业务逻辑的团队?领域和微服务能分清楚吗?所有团队之间的工作是否平衡?团队负载均衡吗?姿势难度是否分解为其他工作?迁移到微服务是一个大爆炸。大家停止函数,开始思考如何分解单体引用,即使前提条件不满足。事实证明,这不是一个好方法,而且可能是一种退步。先创建所有微服务,再搭建架构,忽略团队架构。最好一开始就考虑团队和业务逻辑的结合,等架构成熟了,等微服务自然出现。而且,新的业务需求可以直接放在新的服务中。强制使用微服务还意味着选择每个微服务的大小。一些文章建议,每个微服务的设计都应该在至少一个团队的支持下进行。其他人建议越小越好,如果需要更改,可以在很短的时间内完成。领导决定按工作区域划分,必要时再细分。这个决定导致了上面提到的问题。后来在查看磁盘的时候,发现如果等微服务自然出现,其实它的大小是最合适的。取消随着预定时间的临近,我们的团队不断发现越来越多的问题。上线四天了,还是看不到预期的效果。于是召开了一次会议,最终取消了微服务计划。更换移动微服务的热情已经消散,这意味着我们还没有做必要的研究。放弃微服务后,我们也有精力去研究其他的解决方案。最终,我们决定将单体应用划分到不同的项目中,以更好地划分架构和耦合关系。另外,这种架构使得领域模型更加清晰,以后更容易考虑微服务。结论领导层对微服务的仓促决定没有考虑到挑战和现状。经过评估,发现微服务并不适合我们,需要做出更多的妥协。这些权衡抵消了微服务的好处。微服务不考虑团队结构和工作量等非技术因素。经过几个月的研究,我们放弃了微服务的尝试,决定对现有的单体应用做一些更合适的微调。
