微服务被认为是一种理想的架构模型,因此StevenLemon公司的领导层决定从单体架构迁移到微服务架构,这让整个开发团队在接下来的日子里苦不堪言。摆在我们面前无法解决的七大实际问题,还没有享受到微服务架构带来的好处,发现这不仅仅是一个技术问题。最终,整个团队决定放弃。领导决策:迁移微服务最近,我所在的开发团队在紧张的交付周期后进行了短暂的休息。领导觉得这个时间可以用来把单体架构迁移到微服务。经过一个月的研究和准备,我们最终放弃了迁移方案,继续沿用原来的单体架构。在我们看来,微服务不仅不会帮助我们,反而会严重影响开发过程。微服务被认为是一种理想的架构模式,但它们不适合我们。我们公司的情况是这样的:有200多个开发人员,但我们的团队只有5个人,我们后端开发中大约有5%涉及企业级的单体系统,即一个巨大的C#应用程序。剩下的时间我们开发了自己的两个Node服务。这两种服务都足够小,我们的团队可以完全控制开发、架构和部署过程。当我们遇到性能问题时,我们将生产中的实例数量增加一倍,直到根本问题得到解决。我们几乎不与其他团队合作,因为服务是用TypeScript开发的,所以我们的团队(主要是前端开发人员)能够在前端和后端使用相同的编程语言。最重要的是,我们可以在客户端和后端验证和报告服务中包含复杂的规则计算引擎。总而言之,我们整个团队都专注于特定业务。首先免责声明:我们不喜欢开发单体系统,因为添加新功能、编译和运行测试很慢,而且架构经常变化,构建过程中总是有不可预测的事情。所以,当领导提出要迁移到微服务架构的时候,我们也同意了。为什么选择放弃?然而,在整个研究过程中,我们发现了以下七个难题,最终让我们选择了放弃。严重依赖第三方我们的整体应用程序是一个构建在外部产品之上的自定义UI层,集成了自定义业务规则,并提供了一个交互界面。客户端是一个UWP应用程序,以及一些在我们的域和第三方域之间进行转换的后端服务。因为严重依赖第三方,我们在划分微服务的时候遇到了一些问题。例如,为了让第三方域工作,应用程序必须在域之间做一些转换工作,这样第三方域看起来就像是我们域的一部分。如果前端和第三方之间只有一个服务,那么这个转换还是可行的。当我们试图将域划分为多个独立的微服务时,域之间的翻译工作造成了很大的麻烦。比如微服务的划分是否应该和第三方保持一致,在两边的服务之间重复前端需求?还是按照自己的原则划分微服务,通过一个微服务获取第三方多个域的数据?这两种方法都违反了微服务原则并导致了额外的耦合。此外,我们经常需要与外部各方合作,因为某些功能需要双方进行更改。实际上,外部方成为我们之外的另一个开发团队。如此紧密地合作意味着我们的发布过程必须与他们的同步。微服务的好处之一就是每个团队都可以独立发布自己的服务,不需要和其他团队协调,但是跨团队甚至跨公司的协同发布过程让我们无法享受到这些好处。微服务的核心思想之一就是打破“不同层由不同团队开发”的模式。在微服务架构中,每个团队都需要处理与其业务相关的整个技术栈。因为外部方是一个完全独立的公司,所以我们进行这种重构是不现实的。无法有效拆分微服务我们无法在单体系统中找到可以清晰拆分为微服务的部分。因此,我们随机挑选了几个领域模型,得到了需要创建的微服务列表,但当我们开始调查时,我们发现这些微服务之间存在大量共享的业务逻辑和隐式耦合。我们进一步尝试将这些微服务细分为更小的服务,但这带来了更多的耦合,无处不在的消息总线,以及潜在的通信爆炸——一个服务需要与十个或更多的多微服务通信。这些微服务之所以耦合度高,难以拆分,主要是因为我们原来的单体架构只为一个业务提供服务。UI应用程序的主要设计目标是聚合来自第三方基础应用程序的数据。为了方便用户,我们创建了跨域工作流以将分散的功能集中在一起。整个过程中,我们没有正确理解如何拆分微服务,低估了正确选择微服务边界的重要性。如果按照我们的方式拆分,实现一个标准的功能需要同时修改多个微服务。每个功能都需要不同的微服务团队参与开发,这使得单个微服务不可能只负责一个团队。不同的团队共享微服务我们有大约12名开发人员从事这项工作,分布在两个职能团队和一个支持团队中。但是我们负责的工作是波动的。一个团队不会只负责开发应用程序的某个部分。两个团队同时修改同一份代码的情况并不少见,因此微服务的所有权不能分配给一个团队。康威定律指出,软件架构将以与组织和团队结构类似的方式发展。如果你有很多独立的团队,可以负责不同的业务关注点,那么考虑采用微服务架构。但是,如果只有几个团队开发相同的功能,那么就不要这样做。平台还没有准备好,因为有各种各样的问题,至少6个月,我们不得不同时部署旧的单体应用和新开发的微服务,无法使用微服务相关的工具,比如容器、Kubernetes、服务总线、API网关等。没有这些工具,微服务之间的通信就会变得更加困难。因此,我们在每个微服务中包含共享逻辑。有很多重复的工作,因为它没有被正确地分割。例如,我们必须跨四个微服务复制、粘贴和维护一个特别复杂但重要的业务逻辑。前路渺茫。开发团队对于接下来6个月要做什么只有一个大概的想法,除此之外别无其他。业务变化频繁,需求突然变化的情况并不少见。这种不确定性使得微服务的开发变得更加困难,因为无法预测会出现什么新情况。比如,微服务之间的关系和耦合会不会越来越大?几个月后,我们是否需要花时间将它们重新连接在一起?今年早些时候,我们尝试进行微服务概念验证,但随后由于业务需求发生变化而被拒绝。时间太紧了。工期很紧,leader留下的时间足够把单体拆分成有计划的微服务。没有多余的时间去反省自己的所作所为,或者在必要的时候调整方向。我们在规划阶段就发现了很多问题和挑战,实施阶段就更不用说了,开发团队都处于焦灼状态。缺乏经验除了面临风险和时间压力外,负责设计和实施微服务的人员之前也没有相关经验。由于没有足够的标准工具可用,情况更加恶化,我们不得不自己实施基础设施平台。在与一些有微服务经验但没有参与我们项目的人交谈后,引起了更大的恐慌。我们没有他们建议的基础设施,他们指出了我们在领域模型之间绘制边界的可能后果。到目前为止,我们的计划已经包含了许多妥协,这些妥协与标准的微服务模型有些不同。时间紧迫,没有高人指点,失误屡见不鲜,我们以非常高的代价得到了教训。反思:微服务能解决痛点吗?随着这些事情变得越来越困难,清晰的前进道路开始变得模糊。我们意识到我们不知道我们为什么要做这些事情,我们没有列出痛点是什么,我们不知道做这些事情是否能解决问题。更糟糕的是,微服务会产生新的问题。我们开始分析这些问题:什么应该从重构中受益?应该解决什么问题?我们试图通过没完没了的会议来解决这些问题。每次休息时,开发人员之间的每一次对话都在讨论和质疑微服务,但仍未得到解答。事实证明,我们确实有其他比微服务更紧迫的痛点需要解决,这些痛点在我们考虑迁移到微服务时被忽略了,但我们没有足够的时间来解决它们,所以我们最终,无论是好处微服务或其他痛点都得到了解决。微服务有什么好处?在意识到采用微服务的目的不明确后,我们开始研究微服务能带来什么好处。自治采用微服务架构时,开发团队可以控制交付功能所需的整个技术堆栈。好处是可以减少与其他团队的协调,又不会互相影响。开发团队可以专注于某些领域。采用单体架构时,开发任务的分配是不固定的,任何人都可以分配到任何任务。但如果每个团队都能有自己的服务,就可以积累特定业务领域的专业知识,了解特定领域的业务规则和要求。他们对自己的技术堆栈有很好的了解,并且在进行更改时更有信心。可扩展性采用微服务时,开发人员可以根据每个服务的性能需求进行扩展。当使用单体架构时,虽然可以通过添加更多服务器来水平扩展,但是单体的每个组件都无法独立扩展。此外,细粒度的微服务可以更轻松地根据需要进行垂直扩展。例如,有时您可能希望处理更多的负载,并且在处理性能问题时需要一些额外的机会。更容易回滚如果回滚某个功能,只需要修改单个微服务就可以直接回滚,不影响其他团队的工作。此外,微服务架构有助于降低单个微服务故障导致整个系统崩溃的风险。更高的发布频率对于大型系统,每次发布都非常耗时且伴随着风险。回归测试需要涵盖很多东西,限制了发布节奏。开发人员可能需要通过很多人,并在参与发布的所有团队之间进行协调。微服务减少了变更范围,减少了团队之间的协调工作。开发团队可以根据自己的时间表发布版本,而不是被单一的节奏所束缚。个体团队使用最合适的技术微服务可以为要解决的问题选择最合适的技术,可以使用更新的技术,而单体系统则难以升级,只能停留在陈旧的技术平台上。更轻松的升级升级大型应用程序的框架从来都不是一件有趣的事,而且往往伴随着风险。当需要跨多个团队协调相互关联的更改时,一切都会变得更加困难。采用微服务架构时,只升级必要的服务,一次只能一个团队升级一个服务。缩小更改范围应用程序的不同部分以不同的速度更改,大多数组件可能几个月甚至几年都不需要更改。将不经常更改的代码与经常更改的代码分开可以降低意外回归的风险。来的风险。易于重构较小的服务更容易理解。一个服务只由一个团队开发,服务的设计风格可以保持一致。较小的微服务更容易重构。相比之下,单体架构可能会不一致,因为随着时间的推移,不同的团队会向单体系统添加不同的设计理念。这些好处对我们有什么影响?采用微服务有很多潜在的好处,但我们可以收获吗?最终,单体的不可更改部分和我们必须做出的妥协使得无法获得这些好处。开发团队需要在不同的微服务之间进行协调,一些功能分散在多个共享的微服务中,这意味着我们没有获得微服务的隔离优势:减少协调和专业化。微服务之间的差异成为劣势而不是优势。开发每个新功能都需要了解新的微服务以及其他团队需要做出的改变。我们对第三方的依赖严重阻碍了开发过程,并使我们无法获得微服务可扩展性的优势。权衡利弊采用微服务架构并非没有成本。需要解决的问题很多,大部分已经在单体系统中解决,例如:日志、监控、异常处理、容错、服务间的回退通信、消息格式、容器化、服务发现、备份、遥测、警报、跟踪、构建管道、发布管道、工具、共享基础设施代码、文档、扩展、时区支持、API版本控制、网络延迟、健康检查、负载平衡、CDC测试、容错、在本地开发中调试和开发多个微服务环境等等。更糟糕的是,因为没有现成的微服务平台,以上的事情我们都得自己做。我们在迁移到微服务时确实遇到了痛点和困难,我们确信我们无法从微服务架构中获得任何好处,而且要支持微服务还有一长串额外的工作要做。标称微服务下图显示了我们当前的单体架构、计划架构和微服务架构。在结构上,新架构与当前的单体架构非常相似,一切仍然紧耦合。单体架构不好吗?自从微服务架构流行起来,“单体”就成了一个贬义词,好像“单体”是坏事,“微服务”是好事。但回过头来看,我们的开发团队在开发单体系统时没有遇到任何问题。开发和扩展非常简单,已经有很好的CI/CD流水线,部署和回滚都非常容易。我们的分支机构管理和测试策略确保很少有问题会投入生产。微服务与技术无关。我们越研究微服务,越觉得它跟技术无关,更多的是跟团队结构和工作模式有关。或许我们把微服务当作一个纯粹的技术问题是错误的?此外,还有许多无法回答的大局问题。让不同的团队负责不同的业务是否可行?我们能否明确区分领域和微服务之间的功能?所有团队的工作量是否足够,是否存在部分团队松懈的情况??个别团队是否会被堆积如山的高优先级工作压得喘不过气来?阻止我们拆分单一系统的问题是否也会使领导层难以分配工作?领导层对这种转变感兴趣吗?服务迁移是一件大事,几个月来所有开发人员都停止了新功能的开发,并开始在没有满足许多先决条件的情况下拆除单体。我们是为了做而做的,并没有考虑是否真的有必要。这远不是从A到B的问题,而是倒退一步。我们先创建微服务,然后构建基础设施,而忽略了重组团队结构。如果我们首先围绕业务问题重组团队,然后准备基础设施,这就为微服务的自然出现奠定了基础。一旦出现任何新的业务问题,就可以将它们直接放入新服务中。在拆分微服务时,我们必须预先确定每个微服务的大小。关于微服务规模调整的主题有很多相互矛盾的建议。有人建议微服务应该大到足以由一个团队开发;其他人建议微服务应该足够小,以至于服务结构可以在您的脑海中可视化,甚至小到可以在两周内重写;其他人建议它应该与业务规模相似。领导决定根据我们的领域模型拆分微服务,如果还有问题,继续拆分成更小的服务。这就导致了上面提到的一些问题。事后看来,如果我们先把先决条件放在适当的位置,让微服务自然出现,我们最终可能会得到一个符合实际的微服务规模。取消计划随着微服务发布日的临近,我们团队发现的问题越来越多。我们做出了更多的妥协,微服务的优势进一步消失。实施微服务的第一个冲刺已经过去四天了,但我们仍然看到收获不大,问题也越来越多。我们开了个会,每个开发人员的脸上都写着答案,无论领导层想要什么,是否继续沿着这条路走下去。最终,我们放弃了转向微服务的计划。做什么而不是微服务?因为所有的精力都放在了如何迁移到微服务上,所以我没有花时间研究其他替代方案。但在放弃微服务之后,我们开始寻找其他替代方案。最后,我们没有将整体拆分为微服务,而是将其拆分为多个项目。这种拆分为我们提供了一些额外的结构,我们可以更容易地看到耦合和重复的地方,没有额外的负担,也不必面对微服务架构中存在的问题。此外,这种结构使我们的领域模型更加清晰,更容易评估哪些部分可以拆分为微服务。如果某些部分被证明是合适的微服务候选者,则该部分可以从整体中分离出来并成为微服务。结论领导层在没有考虑现状和需要面对的挑战的情况下决定转向微服务。经过评估,我们发现微服务并不适合,需要做出很多妥协。这些妥协阻止了微服务的好处被收获,因此转向微服务对我们来说是一种损失。在决定转向微服务时,我们没有评估团队结构等非技术方面。经过数月的研究和努力,我们最终放弃了这个想法,并用剩下的时间对“单体”进行了一些小的重构。
