zoukankan      html  css  js  c++  java
  • 0107-将Monolith重构为微服务

    重构到微服务的概述

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

    一个不使用的策略是重写“Big Bang”。那就是当你将所有的开发工作集中在从头开始构建一个新的基于微服务的应用程序时。虽然听起来很有吸引力,但它极具风险,并可能以失败告终。据报道马丁福勒,“宇宙大爆炸改写的唯一保证是宇宙大爆炸!”

    而不是Big Bang重写,你应该逐步重构你的单片应用程序。您逐渐构建一个由微服务组成的新应用程序,并与您的整体应用程序一起运行。随着时间的推移,单片应用程序所实现的功能量会减少,直到它完全消失,或者它变成另一个微服务。这种策略类似于以70英里/小时的速度在高速公路上行驶时为您的汽车提供服务 - 具有挑战性,但比试图进行大爆炸重写风险要小得多。

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

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

    策略1 - 停止挖掘

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

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

    另一个组件是胶合代码,它将服务与整体结合在一起。一项服务很少孤立存在,并且通常需要访问该巨石所拥有的数据。胶合代码驻留在整体或服务中,或两者都负责数据集成。该服务使用胶水代码来读取和写入巨石所拥有的数据。

    服务可以使用三种策略访问整体数据:

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

    胶水代码有时被称为反腐败层这是因为粘合代码阻止了具有自己的原始域模型的服务被来自传统整体域模型的概念所污染。胶水代码在两种不同型号之间转换。术语反腐败层首先出现在埃里克埃文斯的必读书籍Domain Driven Design中,然后在白皮书中进行了完善发展反腐败层面可能是一项不平凡的任务。但是,如果你想从单一的地狱中发展出来,创建一个很重要。

    作为轻量级服务实现新功能有两个好处。它可以防止单块变得更加难以管理。该服务可以独立于整体开发,部署和扩展。您将体验到您创建的每个新服务的微服务体系结构的好处。

    但是,这种方法并没有解决巨石问题。为了解决这些问题,你需要打破庞然大物。让我们看看这样做的策略。

    策略2 - 拆分前端和后端

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

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

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

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

    然而,这个策略只是一个部分的解决方案。一个或两个应用程序很可能是一个无法管理的庞然大物。您需要使用第三种策略来消除剩余的巨石或巨石。

    策略3 - 提取服务

    第三种重构策略是将整体中的现有模块变为独立的微服务。每次你提取一个模块并把它变成一个服务,这个庞然大物就会缩小。一旦你转换了足够的模块,巨石将不再是一个问题。要么它完全消失,要么它变得足够小,它只是另一种服务。

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

    一个庞大而复杂的单片应用程序由数十或数百个模块组成,所有这些模块都是提取的候选对象。确定首先转换哪些模块往往是具有挑战性的。一个好的方法是从几个易于提取的模块开始。这将为您提供一般微服务和特别是提取过程的经验。之后,你应该提取那些会给你带来最大好处的模块。

    将模块转换为服务通常非常耗时。您希望根据您将收到的好处对模块进行排名。提取频繁更改的模块通常是有益的。将模块转换为服务后,您可以独立于单块进行开发和部署,这将加速开发。

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

    在确定要提取哪些模块时,查找现有的粗粒度边界(aka接缝)是非常有用的。它们使模块变成服务更容易,更便宜。这种边界的一个例子是只通过异步消息与应用程序的其余部分进行通信的模块。将该模块转换为微服务可能相对便宜且容易。

    如何提取模块

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

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

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

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

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

    概要

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

    原文地址:https://www.nginx.com/blog/refactoring-a-monolith-into-microservices/

  • 相关阅读:
    Android虚拟机 修改IMEI
    Android 真机调试缺少sqlite3
    DouBan FM API
    MySQL 常用命令[不断更新中]
    通过QRCode生成二维码与解码
    Ant 批量打包Android Umeng多渠道版本
    Centos服务器常用配置集合
    MTU详解
    openvswitch-with-conntrack_nat
    NAT介绍及NAT设备类型
  • 原文地址:https://www.cnblogs.com/bjlhx/p/8796928.html
Copyright © 2011-2022 走看看