译者|朱刚策划|YunZhao在微服务架构的设计中,如何拆分单体是架构师非常重要也很头疼的问题。在本文中,将介绍有关如何准备和执行整体应用程序拆分的一些想法和分步说明。概述单体分裂必须追求的一些目标:不仅仅是分裂,而是通过分裂获得一些好处。如果考虑拆分的成本和影响,也许其他一些方法(例如应用程序扩展或数据库硬件更新)可能更可取。另一个要实现的好处示例可能只是应用程序现代化。然而,这里有一个或多或少官方的分裂单体的方式,它试图考虑分裂的原因和目标。当然这不是教条,你可以找到几种拆分的方法。此迁移路线图旨在将整体应用程序迁移到微服务,以在没有(或最少)应用程序停机时间的情况下获得微服务的好处。清晰的基线由于应用程序支持,单体应用程序可能看起来很杂乱,但这是可以预料的。充其量,期望一个具有大量调整的大型耦合分层应用程序。无论如何,第一步是您需要收集有关当前应用程序的所有信息:需求、用例、ASR、组件、部署图等。了解应用程序(作为一个整体)在大多数情况下,应用程序缺少文档可能描述了基线,那么你至少需要收集以下信息:应用的功能模块,它们与外部环境的关系;API和Service接口说明;带有模块描述的组件图就足够了。这是因为在大多数情况下,拆分将按功能或换句话说应用功能执行;显示物理硬件以及系统和软件配置的部署图。这是因为某些NRF可能会受到部署的影响(例如,具有故障隔离的可扩展性)。理解数据为什么数据图和底层数据映射很重要?在大多数情况下,微服务将与底层数据和数据库一起被抽象出来。杂乱的数据会影响此类NRF的性能。在任何情况下,它都有助于发现潜在的问题,例如数据缺失或过多、数据混乱以及某些微服务的数据提取边界。了解上下文在某些情况下,需要提取的功能可能已经作为单独的外部服务存在。不需要抽取一些业务能力,只是复用一些已有的对外服务。像TTM这样的微服务优势可以用更少的努力来实现。了解用户这一点虽然与上下文重叠,但显示了用户/外部系统如何使用应用程序,因此可以了解使用了哪些功能以及如何使用,也许应用程序的某些部分已过时且未使用。关于应用程序的其余信息将用于做出决策并显示是否需要拆分、如何拆分以及提取什么。为什么拆分单体?可能很难回答为什么我们需要将单体应用程序拆分成微服务,答案可以更面向业务或更面向技术。在大多数情况下,企业看不到将整体架构重构或拆分为微服务有任何好处。业务驱动因素乍一看,可以找到以下先决条件,但列表可以扩展。无论如何,业务的驱动力都是增收减亏,所以新的项目只会从这两个问题中衍生出来。缩短上市时间,降低TCO:只扩展必要的部分,减少损失:弹性、高可用和容错解决方案,测试覆盖提供更好的用户体验另外,一些奇怪的动态可能会悄无声息地出现,但不会表现出来:非常主流,它也打破了整体。技术驱动技术驱动只是扩展了业务驱动因素的列表,它可能看起来像这样:摆脱过时的技术并平稳地迁移到现代/支持的技术降低复杂性增加可支持性增加测试覆盖率可重用性透明和可预测的为变体团队重用微服务的好处以下提供了微服务的优势以及它们如何满足业务和技术要求。当然,表格可以通过几个额外的微服务优势进行扩展,但它们大多是派生的并且与表格内容重叠。在记住优点的同时,请不要忘记缺点。拆分步骤1.准备以下是拆分单体应用程序的大致正式步骤。这些步骤可能会根据业务需求、整体状态、CI/CD过程等进行调整。在建立基线早期获得的模块/服务列表应该围绕业务能力进行组织,并且可能更深一层。例如,欺诈检测系统和促销服务可能需要地址。可以在拆分过程的中间实现预期的目标。从业务的角度来看,这可能是一件好事,但从技术的角度来看,继续使用具有多个提取服务的单体应用程序是不好的。2.对于一个需要先拆分的应用来说,想要有一个好的形状几乎是不可能的。因此,可能会在整体中执行几轮服务重构,一些服务可能正在重构,而另一些服务正在被提取。3.典型的分层应用这是服务抽象的起点,此时应用的主要层,如控制器、应用服务、DAO等,是可观察和可理解的。4.Service/FunctionalBoundary和APIDDD可能有助于定义服务边界,但我们需要从现有应用程序中提取业务功能,而不是建模业务模型。只需开始将业务功能映射到现有的应用程序服务和领域模型,以确定服务边界。在分层应用程序中,控制器可以描述要提取的API。API可能会被调整/扩展,但这里的重点是整个应用程序必须以最小的更改与服务一起工作。这些更改与我们需要使用提取功能(代理和外观)的原因和方式有关。5.创建服务门面定义服务边界时,我们需要改变与功能交互的方式。我们不需要处理一组表示业务功能的应用程序服务,而是需要在单体应用程序中创建一个外观并通过外观进行工作。换句话说,我们需要在提取服务之前得到一个松散耦合的单体。6.重构数据使用数据库提取一项服务可能会影响单体应用程序的许多不同服务。所以服务数据只能通过API访问,不能通过数据库访问。因此,由于直接访问数据,即使是服务获取也可能需要大量工作。7.停止将新功能写入单一应用程序。拆分为微服务并向解决方案添加新功能。两个活动并行执行是很常见的情况,因此从一开始就创建新功能,因为单独的微服务是有意义的。8.拆分在大多数情况下,所有的准备步骤都应该在实际拆分之前完成。应用程序应该表现为具有细粒度服务、良好描述的API和边界以及每个服务的独立数据(避免跨数据库共享数据)的松耦合单体。9、先抽取服务比较正确的做法不是先抽取服务,而是先抽取业务特征。尝试按业务能力/领域对现有应用程序进行重组/重构/分组,每个应用程序可能包含多个应用程序服务。潜在的优先级排序标准:最常更改的服务:最小化对部署的影响。可能被第三方服务替代的服务:只是为了让代码库更轻量。需要扩展的服务:优化性能。与整个单体耦合:使代码库更轻便,更易于理解。服务的复杂性:收集经验、建立CI/CD流程、沟通方式等。检查清单可能会有所不同,可能会添加标准,例如将底层数据库模型从关系数据库模型更改为NoSQL、技术更改(编程语言)、团队利用率等等。因此,至少可以选择一个服务进行提取。10.选择微服务之间的通信方式这不是一个很复杂的步骤。但我们不仅需要选择协议和序列化类型,还需要考虑云提供商的限制(即广播支持)。在大多数情况下,REST或gRPC是请求-响应同步通信的首选方式。这是由于相对简单、团队经验、不同工具的支持等原因。很难想象使用干净的TCP的新的或提取的微服务。由于异步、单向(当然可以使用“回复”机制,但会导致服务耦合)等原因,基于消息的通信方式不能被视为请求-响应的替代方案。异步适用于事件溯源(即发即弃)以及消费者建立自己的世界观。一个例子是关于成功支付的通知将反映在订单履行系统中以组装交付和财务系统,可以使用SQS、Kafka或其他消息服务。11.实施服务使用选定的通信方法、拥有的数据库等实施微服务。为测试目的创建服务模拟以测试单体和其他相关微服务是有意义的。12.创建一个服务代理创建一个具有额外职责的服务代理。在整体中使用服务或使用抽象服务意味着可以使用代理与已删除/提取的微服务进行通信。该代理将允许在单体和抽象服务中的现有服务实现之间轻松切换。可以使用金丝雀发布方法。13.切换到微服务经过测试,在生产中测试的金丝雀版本仅对微服务的使用和从遗留代码中清理单体应用程序有意义。检查初始目标是否已达到并决定停止或继续拆分过程。如果继续,则需要选择下一个特征并进行提取。译者介绍朱刚,社区编辑,2019年CSDN博客高手20强,2020年腾讯云+社区优秀作者。10年一线开发经验,曾参与猎头服务网站架构设计、企业智能客服、大型电子政务系统开发。主导某大型国有企业内部防泄密及电子文档安全监控系统建设,目前在某知名BIM公司从事招投标软件开发工作。原标题:拆分巨石:什么,什么时候,如何,伊戈尔·阿扎尼(IgorAzarny)
