这七个系列的文章现在完成:

  1. 微服务介绍
  2. 构建微服务:使用API​​网关
  3. 构建微服务:微服务架构中的进程间通信
  4. 微服务架构中的服务发现
  5. 事件驱动的数据管理微服务
  6. 选择微服务部署策略
  7. 重构一个Monolith到微服务(本文)

您还可以下载完整的文章集,以及使用NGINX Plus实现微服务的信息,作为电子书 -微服务:从设计到部署

这是我的系列中关于使用微服务构建应用程序的第七篇和最后一篇文章。在第一篇文章介绍了微服务架构模式,并讨论的好处和使用微服务的缺点。以下文章讨论微服务架构的不同方面:使用API​​网关进程间通信服务发现事件驱动的数据管理部署微服务。在本文中,我们将讨论将单片应用程序迁移到微服务的策略。

我希望这个系列的文章给你一个很好的理解微服务架构,其优点和缺点,以及何时使用它。也许微服务架构是一个很适合你的组织。

但是,有一个很好的机会,你正在一个大型,复杂的单片应用程序。您开发和部署您的应用程序的每日经验是缓慢和痛苦。微服务似乎是一个遥远的涅。。幸运的是,有一些策略,你可以使用从整体地狱逃脱。在本文中,我将描述如何将单片应用程序逐步重构为一组微服务。

重构到微服务概述

转化单片应用到微服务的过程是一种形式应用现代化。这是开发人员已经做了几十年的事情。因此,我们可以在将应用程序重构到微服务时重用一些想法。

不使用的一个策略是“大爆炸”重写。这就是当你把所有的开发工作集中在从头开始构建一个新的基于微服务的应用程序。虽然听起来很吸引人,但它是非常危险的,并且很可能会以失败告终。正如Martin Fowler所说,“大爆炸重写保证的唯一的东西是大爆炸!

而不是大爆炸重写,你应该递增重构你的单片应用程序。您逐步构建一个由微服务组成的新应用程序,并与您的单片应用程序一起运行。随着时间的推移,由单片应用程序实现的功能量收缩,直到它完全消失或者它只是另一个微服务。这种策略类似于在70英里/小时的速度下行驶在高速公路上时为您的车辆提供服务 - 具有挑战性,但远远没有尝试大爆炸重写的风险。

Martin Fowler将此应用程序现代化策略称为“Strangler应用程序”。这个名字来自扼杀者的藤蔓(aka strangler fig)在热带雨林中发现。扼制者藤蔓生长在一棵树上,以便到达森林树冠上的阳光。有时,树死了,留下一棵树形的藤。应用程序现代化遵循相同的模式。我们将构建一个由遗留应用程序周围的微服务组成的新应用程序,这将最终死亡。

让我们看看这样做的不同策略。

策略1 - 停止挖掘

孔的法说,每当你在一个洞,你应该停止挖掘。当你的整体应用程序变得难以管理时,这是很好的建议。换句话说,你应该停止使巨石更大。这意味着当你实现新的功能,你不应该添加更多的代码到巨石。相反,这个策略的一个大想法是将这个新代码放在一个独立的微服务中。下图显示了应用此方法后的系统架构。

除了新服务和传统的整体外,还有两个其他组件。第一个是请求路由器,它处理传入(HTTP)请求。它类似于前面的文章中描述的API网关。路由器向新服务发送对应于新功能的请求。它将遗留请求路由到整体。

另一个组件是粘合代码,它将服务与整体集成。服务很少孤立存在,并且通常需要访问整体所拥有的数据。粘合代码,位于单片机,服务或两者,负责数据集成。该服务使用胶水代码来读取和写入整体所拥有的数据。

服务可以使用三个策略来访问巨庞的数据:

  • 调用整体提供的远程API
  • 直接访问巨庞的数据库
  • 维护自己的数据副本,这是与巨量的数据库同步

胶水代码有时被称为反腐败层。这是因为粘合代码阻止了具有其自己的原始域模型的服务被遗留巨作的领域模型的概念污染。粘合代码在两个不同的模型之间进行转换。术语反腐败层首先出现在必读的域名驱动设计由埃里克·埃文斯,然后在一个白皮书精炼。发展反腐败层可以是一项不小的工作。但是,如果你想成长你的方式从整体地狱是必要的创造一个。

将新功能实现为轻量级服务具有几个好处。它防止巨石变得更加难以管理。该服务可以独立于整体开发,部署和扩展。对于您创建的每个新服务,您都会体验到微服务架构的优势。

然而,这种方法没有解决整体的问题。要解决这些问题,你需要打破巨石。让我们看看这样做的策略。

策略2 - 拆分前端和后端

缩小整体应用程序的策略是将表示层与业务逻辑和数据访问层分离。典型的企业应用程序由至少三种不同类型的组件组成:

  • 表示层 - 处理HTTP请求并实现(REST)API或基于HTML的Web UI的组件。 在具有复杂用户界面的应用程序中,表示层通常是大量代码。
  • 业务逻辑层 - 作为应用程序核心并实现业务规则的组件。
  • 数据访问层 - 访问基础结构组件(如数据库和消息代理)的组件。

通常一方面的表示逻辑与另一方面的业务和数据访问逻辑之间存在清晰的分离。业务层具有包含一个或多个外观的粗粒度API,其封装业务逻辑组件。这个API是一个自然缝,您可以沿着这个缝将整块分割成两个较小的应用程序。一个应用程序包含表示层。另一个应用程序包含业务和数据访问逻辑。分割后,表示逻辑应用程序对业务逻辑应用程序进行远程调用。下图显示了重构之前和之后的架构。

以这种方式分割整体有两个主要好处。它使您能够独立于彼此开发,部署和扩展这两个应用程序。特别地,其允许表示层开发者在用户界面上快速迭代,并且例如容易地执行A | B测试。这种方法的另一个好处是,它暴露了一个远程API,可以由您开发的微服务调用。

然而,这种策略只是部分解决方案。很可能一个或两个应用程序将是一个不可管理的整体。您需要使用第三个策略来消除剩余的整体或整体。

战略3 - 提取服务

第三个重构策略是将单片机中的现有模块转换为独立的微服务。每次你提取一个模块,并把它变成一个服务,这个单块收缩。一旦你已经转换了足够的模块,这个单块将不再是一个问题。它或者它完全消失或者变得足够小,它只是另一个服务。

确定将哪些模块转换为服务的优先级

一个大的,复杂的单片应用程序包括几十或几百个模块,所有这些模块都是提取的候选。确定首先转换哪些模块通常是具有挑战性的。一个好的方法是从一些容易提取的模块开始。这将给你提供微服务的经验,特别是提取过程。之后,你应该提取那些将给你最大的好处的模块。

将模块转换为服务通常是耗时的。你想通过你将收到的好处排序模块。提取频繁变化的模块通常是有益的。将模块转换为服务后,您可以独立于整体开发和部署模块,这将加速开发。

提取具有明显不同于整块的其余部分的资源需求的模块也是有益的。例如,将具有内存数据库的模块转换为服务是有用的,然后可以将服务部署在具有大量内存的主机上。类似地,可以值得提取实现计算昂贵的算法的模块,因为服务然后可以部署在具有大量CPU的主机上。通过将具有特定资源需求的模块转换为服务,您可以使您的应用程序更容易扩展。

当确定要提取哪些模块时,查找现有的粗粒边界(又名接缝)是有用的。它们使得将模块转换为服务变得更容易和更便宜。这种边界的示例是仅通过异步消息与应用程序的其余部分通信的模块。它可以相对便宜并且容易地将该模块转换成微服务。

如何提取模块

提取模块的第一步是在模块和单块之间定义粗粒度接口。它很可能是一个双向API,因为这个单片将需要服务拥有的数据,反之亦然。由于模块和应用程序的其余部分之间的纠缠的依赖性和细粒度的交互模式,实现这样的API通常是具有挑战性的。使用域模型模式实现的业务逻辑对于重构是特别具有挑战性的,因为领域模型类之间存在大量关联。您经常需要进行重要的代码更改以打破这些依赖关系。下图显示了重构。

一旦实现粗粒度接口,然后将模块转换为独立服务。为此,您必须编写代码以使单片和服务通过使用进程间通信(IPC)机制的API进行通信。下图显示重构之前,期间和之后的体系结构。

在本示例中,模块Z是要提取的候选模块。它的组件由模块X使用,它使用模块Y.第一个重构步骤是定义一对粗粒度的API。第一个接口是模块X用于调用模块Z的入站接口。第二个接口是模块Z用于调用模块Y的出站接口。

第二重构​​步骤将模块转换为独立服务。入站和出站接口由使用IPC机制的代码实现。您很可能需要通过将模块Z与微服务机箱框架相结合来构建服务,该服务框架处理诸如服务发现的交叉关注。

一旦你提取了一个模块,你还有另一个服务,可以开发,部署和独立于巨石和任何其他服务进行扩展。你甚至可以从头重写服务;在这种情况下,将服务与整体集成的API代码成为在两个域模型之间转换的反损坏层。每次提取服务时,都会沿着微服务的方向迈出另一步。随着时间的推移,巨石将缩水,你将有越来越多的微服务。

概要

将现有应用程序迁移到微服务的过程是应用程序现代化的一种形式。您不应该从头重写您的应用程序移动到微服务。相反,你应该递增地将你的应用程序重构为一组微服务。有三个策略可以使用:实现新的功能作为微服务;从业务和数据访问组件分离呈现组件;并将整体中的现有模块转换为服务。随着时间的推移,微服务的数量将会增长,您的开发团队的敏捷性和速度将会增加。

这七个系列的文章现在完成:

  1. 微服务介绍
  2. 构建微服务:使用API​​网关
  3. 构建微服务:微服务架构中的进程间通信
  4. 微服务架构中的服务发现
  5. 事件驱动的数据管理微服务
  6. 选择微服务部署策略
  7. 重构一个Monolith到微服务(本文)

您还可以下载完整的文章集,以及使用NGINX Plus实现微服务的信息,作为电子书 -微服务:从设计到部署

results matching ""

    No results matching ""