当前位置: 首页 > 科技观察

从单体架构迁移到微服务架构:三种策略叙述

时间:2023-03-13 02:07:58 科技观察

迁移到微服务概述将单体应用程序迁移到微服务架构意味着一系列现代化过程,有点像这几代开发人员一直在做的事情,实时地,我们迁移时可以复用一些想法。一种策略是:不要大规模(大爆炸)重写代码(重写只能在您承诺重建一个新的基于微服务的应用程序时使用)。重写代码听起来不错,但实际上充满了最终可能失败的风险,正如MartinFowler所说:“BigBang重写唯一保证的就是大爆炸!”相反,逐渐迁移到单体应用策略是逐渐生成新的微服务应用程序并将它们与旧的单体应用程序集成。随着时间的推移,单体应用在整个架构中的比例逐渐降低,直至消失或成为微服务架构的一部分。这种策略有点像在高速公路上对限速70英里/小时的汽车进行维修。虽然它具有挑战性,但它比重写风险要小得多。MartinFowler将这种现代化战略称为Strangler应用程序,以生长在热带雨林中的绞杀藤(也称为绞杀无花果)命名。为了爬到森林的顶端,绞杀藤不得不长在大叔的周围。片刻之后,这棵树死了,留下了树状的藤蔓。这个应用也采用同样的模式,围绕传统应用发展出一种新型的微服务应用,传统应用将逐渐退出舞台。让我们看看其他可能的策略。策略1-停止挖掘洞定律说,当你在洞里时,你应该停止挖掘。对于难以管理的整体式应用程序,这是最佳建议。换句话说,你应该停止让单体继续增长,即你不应该在开发新功能时向旧单体添加新代码,最好的方法应该是将新功能开发为独立的微服务。如下图:完美叙述"src="http://p9.pstatp.com/large/pgc-image/06d58a621e994a15a94749ea4c66e058"_fcksavedurl="http://p9.pstatp.com/large/pgc-image/06d58a621e994a15a94749ea4c66e058"_fcksavedurl="http://p9.pstatp.com/large/pgc-image/06d58a621e994a15a94749ea4c66e058"width="640"height="541">除了新服务和传统应用,还有两个模块,一个是requestrouter,负责处理入口(http)请求,有点像前面提到的API网关,router向新开发的服务发送新特性请求,将传统请求回传给单体应用。另一个是胶水代码(胶水代码),集成微服务和单体应用。微服务很少独立存在,经常访问单体应用的数据。胶水代码,可能在单体应用中,也可能是服务的,或者两者兼而有之,负责数据集成。微服务读写数据F通过胶水代码从单个应用程序中获取。微服务访问单体应用的数据有以下三种方式:通风单体应用提供的远程API直接访问单体应用数据库,并维护一份来自单体应用的副本。在应用中同步的数据胶水代码也称为反腐层,因为胶水代码保护微服务的新领域模型免受传统单体应用领域模型的污染。胶水代码在这两个模型之间提供翻译功能。反腐层一词最早出现在EricEvans的必读领域驱动设计中,随后被提炼成白皮书。开发容灾层可能不是很重要,但却是避免单体式泥潭的必要环节。将新功能实现为轻量级微服务有很多优势,例如防止单体应用程序变得更加难以管理。微服务本身可以独立开发、部署和扩展。采用微服务架构会给开发者带来不同的个人感受。然而,这种方法并没有解决单体本身的任何问题。为了解决单体应用本身的问题,必须在单体应用的深处进行变革。让我们来看看这样做的策略。策略2-前端和后端分离降低单体应用程序复杂性的策略是将表示层与业务逻辑和数据访问层分离。典型的企业应用程序至少包含三个不同的元素:表示层-处理HTTP请求,响应RESTAPI请求或提供基于HTML的图形界面。对于复杂的用户界面应用程序,表示层通常是代码中最重要的部分。业务逻辑层——完成业务逻辑的应用程序的核心。数据访问层——访问数据库和消息代理等基本元素。表示层和业务数据访问层之间有明确的分离。业务层有一个由多个方面组成的粗粒度API,其中包含业务逻辑元素。API是一个天然的边界,可以将一个业务分成两个更小的应用,一个是表现层,一个是业务和数据访问逻辑。拆分后,性能逻辑应用远程调用业务逻辑应用。下图显示迁移前后架构不同:完美描述"src="http://p1.pstatp.com/large/pgc-image/ce2dd2e1adaa4966b3ed87f1b07a15dd"_fcksavedurl="http://p1.pstatp.com/large/pgc-image/ce2dd2e1adaa4966b3ed87f1b07a15dd"_fcksavedurl="http://p1.pstatp.com/large/pgc-image/ce2dd2e1adaa4966b3ed87f1b07a15dd"width="640"height="388">monomer拆分有两个优点一种是让应用的两部分的开发、部署和扩展相互独立,特别是让表现层的开发者可以在用户界面上快速选择,进行A/B测试;另一种是让一些远程的APIs可以被微服务调用,但是这个策略只是部分解决方案,很可能应用程序的任何一个部分或两个部分都无法管理,所以需要第三种策略来消除剩余的单体架构。策略3——提取服务第三个米格配给策略是从单体应用中抽取一些模块成为独立的微服务。每当提取一个模块并将其转换为微服务时,整体应用程序就会变得更简单;一旦转换了足够多的模块,单体应用程序本身就不是问题,要么消失,要么足够简单成为一项服务。排序哪些模块应该变成微服务一个巨大的复杂单体应用程序由数十或数百个模块组成,每个模块都是一个提取的对象。决定第一个抽取的模块通常是一个挑战,一般最好从最容易抽取的模块开始,这样可以让开发者积累足够的经验,对后续的模块化工作有很大的好处。将模块转为微服务一般比较耗时,一般可以按照受益程度排序。通常,最受益的是频繁更改的模块。一个模块一旦转化为微服务,就可以作为一个独立的模块进行开发和部署,从而加快开发进程。优先提取资源消耗大户也是排序标准之一。例如,将内存数据库抽象为可以部署在大内存主机上的微服务会很有用。同样,将对计算资源敏感的算法应用抽象化也有好处,这样的服务可以部署在CPU多的主机上。通过将资源消耗模块转换为微服务,可以轻松扩展应用程序。查看现有的粗粒度边界来决定应提取哪些模块也是有益的,从而使移植更容易和更简单。例如,一个只与其他应用程序异步和同步消息的模块是一个明确的边界,可以非常简单轻松地转换为微服务。如何提取模块提取模块的第一步是定义模块和整体应用程序之间的粗粒度接口。由于单体应用程序需要微服务的数据,反之亦然,它更像是一个双向API。开发这样的API具有挑战性,因为必须在负责任的依赖性和细粒度接口模式之间取得平衡,特别是对于使用领域模型模式的业务逻辑层,因此通常需要更改代码来解决依赖性问题,如中所示如图:一旦粗粒度接口完成,这个模块就转化为一个独立的微服务。为此,必须编写代码,以便单体应用程序和微服务使用进程间通信(IPC)机制通过API交换信息。迁移前后对比如图:完美叙述"src="http://p3.pstatp.com/large/pgc-image/154c174a35e0472a86e558deee9d9eee"_fcksavedurl="http://p3.pstatp.com/large/pgc-image/154c174a35e0472a86e558deee9d9eee"_fcksavedurl="http://p3.pstatp.com/large/pgc-image/154c174a35e0472a86e558deee9d9eee"width="640"height="859">在此示例中,Z模块使用Ymodule是候选提取模块,其元素正在被X模块使用,迁移的第一步是定义一组粗粒度的API,第一个接口应该是X模块用来激活Z模块的内部接口;第二个interface是Z模块使用的,使用的外部接口是用来激活Y模块的,移植的第二步是将模块转换成一个独立的服务,内部接口和外部接口都使用基于IPC机制的代码,而Z模块一般集成到一个微服务基础架构中ework出来割接过程中的问题,比如服务发现。提取模块后,可以开发、部署和扩展另一个服务。此服务独立于单体应用程序和其他服务。该服务可以通过从头编写代码来实现;在这种情况下,集成服务和单体应用程序的API代码成为在两个领域模型之间进行转换的灾难恢复层。每提取一次服务,就向微服务迈进了一步。随着时间的推移,单体应用会越来越容易,用户可以添加更多独立的微服务。将现有应用程序迁移到具有微服务架构的现代应用程序不应通过从头开始重写代码来实现。相反,它应该逐渐迁移。可以考虑三种策略:将新功能实现为微服务;将表示层与业务数据访问层分开;将现有模块提取到微服务中。随着时间的推移,微服务的数量会越来越多,开发团队的弹性和效率也会显着提高。