微服务重构概述

 

 

  

 

将Monolith重构为MicroServices

克里斯·理查森(ChrisRichardson)。

  1. 微服务导论
  2. 构建微服务:使用API网关
  3. 构建微服务:微服务体系结构中的进程间通信
  4. 微服务体系结构中的服务发现
  5. 事件驱动的微服务数据管理
  6. 选择Microservices部署策略
  7. 将Monolith重构为MicroServices

微服务重构概述

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

一个不使用的策略是“大爆炸”重写。也就是说,您将所有的开发工作都集中在从头开始构建一个新的基于微服务的应用程序上。虽然这听起来很有吸引力,但风险很大,很可能以失败告终。马丁·福勒据说“生活大爆炸唯一的保证就是大爆炸!”

与“大爆炸”重写不同,您应该逐步重构您的单块应用程序。您将逐步构建一个由微服务组成的新应用程序,并与您的单块应用程序一起运行它。随着时间的推移,单块应用程序实现的功能数量会减少,直到它完全消失,或者变成另一个微服务。这一策略类似于在高速公路上以每小时70英里的速度行驶时为你的汽车提供服务-这具有挑战性,但风险远低于试图重写“生活大爆炸”(Big Bang)。

Martin Fowler将此应用程序现代化策略称为Strangler应用。这个名字来源于勒死葡萄树。陌生人无花果在热带雨林中发现的。为了到达林冠上方的阳光,一株缠绕在树周围的藤蔓生长。有时,树死了,留下一棵树状的藤蔓.应用程序现代化遵循相同的模式。我们将围绕遗留应用程序构建一个由微服务组成的新应用程序,该应用程序最终将死去。

让我们来看看不同的策略。

策略1-停止挖掘

这,这个,那,那个孔洞定律说只要你在洞里就别再挖了。当您的单块应用程序变得无法管理时,这是一个很好的建议。换句话说,你不应该再让巨石变大了。这意味着在实现新功能时,不应该向Monolith添加更多代码。相反,这种策略的主要目的是将新代码放在一个独立的微服务中。下图显示了应用这种方法后的系统架构。

除了新的服务和遗留的Monolith之外,还有另外两个组件。第一个是请求路由器,它处理传入(HTTP)请求。它类似于前一篇文章。路由器向新服务发送对应于新功能的请求。它将遗留请求路由到Monolith。

另一个组件是胶水代码,它将服务与Monolith集成在一起。服务很少单独存在,通常需要访问Monolith拥有的数据。驻留在Monolith、服务或两者中的胶水代码负责数据集成。服务使用胶水代码来读取和写入Monolith拥有的数据。

服务可以使用三种策略来访问Monolith的数据:

  • 调用Monolith提供的远程API
  • 直接访问Monolith数据库
  • 维护与Monolith数据库同步的数据副本

胶水代码有时被称为反腐败层。这是因为胶水代码阻止具有自己原始域模型的服务受到遗留Monolith域模型的概念的污染。胶水代码在两种不同型号之间转换。“反腐败层”一词最早出现在必读的书中。领域驱动设计艾瑞克·埃文斯,然后在白皮书。发展反腐败层可能是一项重要的工作。但是,如果你想要从铁板一块的地狱中成长出来,就必须创造一个。

将新功能实现为轻量级服务有几个好处。它防止了巨石变得更加难以控制。可以独立于Monolith开发、部署和缩放服务。您将体验微服务体系结构对您创建的每个新服务的好处。

然而,这种方法并不能解决Monolith的问题。要解决这些问题,你需要拆散巨石。让我们来看看这样做的策略。

策略2-拆分前端和后端

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

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

通常,表示逻辑与业务逻辑和数据访问逻辑之间有一个清晰的分离。业务层有一个粗粒度的API,它由一个或多个外观组成,封装业务逻辑组件。这个API是一个自然的接缝,您可以沿着它将Monolith分成两个更小的应用程序。一个应用程序包含表示层。另一个应用程序包含业务和数据访问逻辑。拆分后,表示逻辑应用程序对业务逻辑应用程序进行远程调用。下图显示重构前后的体系结构。

以这种方式分割一个单体有两个主要好处。它使您能够独立地开发、部署和扩展这两个应用程序。特别是,它允许表示层开发人员在用户界面上快速迭代,并且可以轻松地执行A/B测试。这种方法的另一个好处是它公开了您开发的微服务可以调用的远程API。

然而,这一战略只是部分解决办法。很可能其中一个或两个应用程序都是不可管理的单点。您需要使用第三种策略来消除剩余的Monolith或Monolith。

策略3-提取服务

第三种重构策略是将Monolith中的现有模块转换为独立的微服务。每次您提取一个模块并将其转换为服务时,Monolith就会缩小。一旦你已经转换足够的模块,单体将不再是一个问题。要么它完全消失,要么它变得足够小,以至于它只是另一个服务。

确定要转换为服务的模块的优先级

一个大型的、复杂的单块应用程序由几十个或数百个模块组成,所有这些模块都是提取的候选模块。首先找出要转换的模块是很有挑战性的。一个好的方法是从一些易于提取的模块开始。这将为您提供一般的微服务经验,特别是提取过程的经验。在此之后,您应该提取那些将给您带来最大好处的模块。

将模块转换为服务通常很费时。你想按照你将得到的利益对模块进行排名。提取频繁变化的模块通常是有益的。一旦将模块转换为服务,就可以独立于Monolith开发和部署它,这将加速开发。

它也是有益的提取模块,有明显不同的资源需求与其余的单核。例如,将具有内存数据库的模块转换为服务非常有用,然后可以将服务部署到具有大量内存的主机上。同样,提取实现计算开销大的算法的模块也是值得的,因为服务随后可以部署在拥有大量CPU的主机上。通过将具有特定资源需求的模块转换为服务,可以使应用程序更易于扩展。

在确定要提取哪些模块时,寻找现有的粗粒度边界(即接缝)是很有用的。它们使得将模块转换为服务变得更容易、更便宜。这样的边界的一个例子是一个模块,它只通过异步消息与应用程序的其余部分通信。它可以相对便宜和容易地把这个模块变成一个微型服务。

如何提取模块

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

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

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

第二个重构步骤将模块转换为一个独立的服务。入站和出站接口由使用IPC机制的代码实现。您很可能需要通过将模块Z与微服务底盘框架它处理跨领域的问题,如服务发现。

一旦您提取了一个模块,您就有了另一个可以独立于Monolith和任何其他服务开发、部署和缩放的服务。您甚至可以从头重写服务;在这种情况下,将服务与Monolith集成的API代码将成为一个反腐败层,在两个域模型之间进行转换。每次提取服务时,都会朝着微服务的方向迈出另一步。随着时间的推移,Monolith会缩小,您将拥有越来越多的微服务。

摘要

将现有应用程序迁移到微服务的过程是应用程序现代化的一种形式。您不应该从零开始重写应用程序,转而使用微服务。相反,您应该将应用程序逐步重构为一组微服务。您可以使用三种策略:将新功能实现为微服务;将表示组件与业务和数据访问组件分离;以及将Monolith中的现有模块转换为服务。随着时间的推移,微服务的数量将会增加,您的开发团队的敏捷性和速度也会提高。

你可能感兴趣的:(java,微服务)