单体Web应用程序向模型驱动云原生迁移的需求

摘要

随着云原生应用的出现,如何将现有的、通常是单体式的应用迁移到这一新范式成为了一个问题。主要的迁移挑战在于将应用分解为细粒度组件以及引入云计算范式。对于复杂的现有应用而言,迁移尤为困难。一种结构化且有工具支持的方法将有助于迁移过程,因此本文提出了一种基于模型驱动工程的方法。作为基础,本文一方面从文献中,另一方面从一项迁移案例研究中,推导并提出了对此类方法的需求。这些需求不仅针对必要的模型,还考虑了整体方法。本文阐明了实现模型驱动的云原生迁移方法所需的基本条件,并讨论了尚存的挑战。

关键词 云原生 · 模型驱动 · 迁移 · 微服务 · 函数即服务 · 分解

1 引言

云原生是当今构建基于Web的应用的主流范式[1]。许多新应用从一开始就直接构建为云原生应用(CNA),但也需要将现有应用迁移到CNA模式,以充分利用云原生应用的优势。然而,此类迁移过程较为困难,且需要具备专业技能的软件工程师。需要迁移的现有应用通常具有单体架构特征,经过较长时间演化,已达到较高的复杂度水平。

云原生应用的一个关键特征是其细粒度架构,这意味着应用由可以独立托管和演进的各个组件构成。因此,将现有的基于Web的应用迁移到云原生应用的关键挑战在于,如何将复杂的单体应用拆分为更小的、符合云原生范式的组件。在文献中,迁移到云原生应用这一主题已被认为具有重要意义([1–3])。一些已完成迁移的个别报告作为案例研究已有提供([4–6])。

但目前仍然缺乏结构化且广泛适用的方法来促进迁移过程。然而,这类方法对于支持参与迁移项目的软件工程师、减少迁移工作量以及提高对迁移成功性和利益的信任至关重要。

为了实现一种结构化且具备工具支持的向云原生应用(CNA)迁移的方法(下文称为云原生迁移),已有研究提出采用模型驱动工程作为一项有前景的技术,以应对迁移中的困难并提供通用适用性[2,7]。因此,本文旨在通过分析包含迁移方法的现有文献、成功迁移的报告,并结合来自一个作为案例研究的迁移项目中的自身经验,推导出此类模型驱动方法所需的必要需求。所探讨的指导性研究问题是:

– 模型驱动的云原生迁移方法在哪个抽象层次上需要哪些信息?
– 为了充分受益于云原生范式,模型驱动方法中需要包含哪些方面?

为了回答这些研究问题,本文结构如下:第2节介绍了本文的基础,并提供了推导需求所需的定义。第3节概述了本文所采用的双重方法论,第4节给出了模型驱动迁移方法的需求。接着,第5节对结果进行了讨论。第6节介绍了相关工作,最后第7节得出结论。

2 迈向云原生迁移

2.1 云原生

尽管“云原生”这一术语已被广泛使用并具有普遍共识,但由于其涵盖的主题十分广泛,因此需要一个清晰的定义,以便在此基础上开展进一步的工作。在本文中,我们采用 Kratzke 和 Quint [8] 的定义:“云原生应用(CNA)是一种由(微)服务[..]构成的分布式、弹性且水平可扩展的系统。该应用及其每个自包含的部署单元均按照以云为中心的设计模式进行设计,并运行于自助式弹性平台上。” 根据他们的定义,多种软件工程实践的结合促成了云原生应用(CNA)的出现,这些实践也构成了云原生应用的特征。其中最为显著的是云计算整体以及微服务架构风格。此外,基础设施的软件化以及弹性平台的使用也是云原生应用的重要特征。微服务架构风格[9]体现了从单体应用经由面向服务架构向细粒度软件架构发展的趋势。

在这些架构中,应用通过独立组件的组合构建而成。云计算所提供的能力强化了这一趋势,因为它通过将运维及其他关注点进行抽象,降低了复杂性,从而支持细粒度架构的高效开发与运营。

一个典型的云原生应用(CNA)的最新示例是函数即服务范式(FaaS)[10],在此范式中,开发人员可以专注于构成独立部署单元的各个函数。这些函数在弹性 FaaS 平台上运行,该平台对运维问题进行了抽象。此外,云原生应用(CNAs)使用云平台提供的服务,而不是自行实现功能,以进一步降低复杂性。这对应于面向以云为中心的设计模式和示例的服务包括身份验证、缓存或日志记录。云原生应用的特征是推导出结构化迁移方法需求的基础。本文中最重要的特征是细粒度架构和云计算范式。

2.2 云迁移

随着持续的创新和新技术的出现,现有应用的迁移始终是一个重要话题,以利用这些创新并保持竞争力。自首个云平台出现以来,云迁移就已成为一个研究课题。Jamshidi 等人回顾了云迁移的研究,并已描述了不同类型的迁移场景[11]。一种可能的方式是将部署在本地环境中的现有应用迁移到 IaaS 服务的虚拟机中(Migrate the whole application stack[11])。虽然这种方式可以减轻应用开发者管理基础设施的负担,但无法获得云计算提供的其他优势。该应用只能作为一个整体进行扩缩容,启动虚拟机所需时间相对较长,应用的不同部分无法独立演进,且应用某一部分的故障可能导致整个应用失效。相比之下,Jamshidi 等人所描述的 Partial migrate 和 Cloudify 类型更具优势,即对系统进行改造以充分利用云平台提供的能力,并例如使用云平台的服务来替代现有功能。向云原生应用的迁移即对应于这些类型。这类迁移需要投入更多努力,且随着现有应用复杂性的增加,所需的工作量也会上升。

通常,将现有应用迁移到云原生应用的过程十分困难,因此需要结构化方法来支持迁移过程。弗朗西斯科等人研究了软件行业在向微服务架构迁移时所采用的方法及面临的挑战[2]。由于微服务架构风格是云原生应用的关键特征,他们的见解也可应用于云原生应用的迁移。弗朗西斯科等人采用了卡兹曼等人最初提出的马蹄形模型。该模型如图1所示,用于描述适用于云原生应用的迁移过程。

示意图0

关键阶段是架构转换阶段,在云原生应用的情况下,系统被拆分为更小的组件,并引入云计算范式。然而,逆向工程和正向工程阶段同样重要,因为它们为实现转换提供了基础,并支持新架构的实际落地。根据弗朗西斯科等人调查的迁移项目,“半形式化模型和领域特定模型并未被广泛使用”[2]。此外,迁移过程本身并非一个明确的项目,而是作为“日常工作的一部分”逐步完成的[2]。这表明目前缺乏结构化和形式化的向云原生应用迁移的方法。另一个需要考虑的方面是,弗朗西斯科等人调查的项目几乎总是在迁移过程中添加新功能[2]。虽然通常认为迁移应保持功能不变,但在实践中这似乎并不现实。

Taibi等人在一项调查中也探讨了实际中使用的迁移过程和方法[3]。然而,Taibi等人所描述的推导出的迁移过程仍处于较高的抽象层次,对于如何对现有系统进行架构转换以形成云原生应用提供了很少的支持。如何将现有系统拆分为更小的组件这一问题,已被报告为主要挑战[3]。

2.3 模型驱动方法

模型驱动工程(MDE)作为一个概念有着悠久的历史。Kent 描述了其基本原理,主张在软件开发中将模型作为一等构件。[13]平台特定模型(PSM)用于表示特定平台的具体实现。平台无关模型(PIM)用于描述与技术细节无关的系统,以专注于最重要的方面。可以将 PSM 转换为 PIM,以便在更高抽象层次上表示现有系统,从而简化系统的进一步演化。同时,也可以将 PIM 转换为 PSM,以便从该模型生成特定平台的具体实现。PSM、PIM 与系统实际实现之间的关系如图2所示。

示意图1

主要优势在于,系统可以在更高抽象层次上进行开发和维护,并且独立于技术细节。然而,为了充分利用模型驱动工程(MDE),所使用的模型必须针对特定用例准确无误,并且应提供支持模型生成、模型转换和代码生成的工具。以弥补在维护模型的同时编写代码所带来的额外工作量。这些模型需要捕获有关系统的详细信息,包括其功能和行为,以支持代码的生成。模型驱动工程(MDE)似乎是一种合适的方法,能够提供形式化和结构化支持,从而推动现有系统向云原生应用(CNA)的迁移。弗朗西斯科等人指出,他们希望将模型驱动工程方法用于微服务迁移作为未来的研究方向[2]。事实上,MDE的基本机制——从现有系统生成平台相关模型(PSM),将其转换为平台无关模型(PIM),通过变换PIM来优化架构,最后再将PIM重新转换为PSM——与弗朗西斯科等人提出的马蹄形模型高度吻合。然而,将MDE作为云原生迁移方法的基础在于拥有合适的模型,这些模型能够准确支持将现有系统拆分为更细粒度的架构,并引入云计算范式。因此,本文的目标是推导出在云原生迁移过程中所使用的模型所需满足的需求。

3 方法论

为了推导模型驱动的云原生迁移方法的需求,我们采用双重方法论。一方面,我们分析现有文献,考虑云原生迁移的项目或方法。文献分析的具体步骤在第3.1节中描述。另一方面,我们进行了一次云原生迁移,并将其作为案例研究,以验证文献中的需求并进一步推导出新的需求。案例研究的一般信息见第3.2节。

3.1 文献检索

为了找到可供分析的文献,我们根据Brereton等人[14]的建议进行了文献检索。在检索过程中,我们使用了以下关键词:迁移、分解、微服务、云原生、模型驱动、基于模型。我们通过谷歌学术、IEEE Xplore和语义学者使用这些关键词来确定与该主题相关的一组初始文献。从该组文献中,我们筛选出符合以下条件的文献:
– 明确描述了一种模型驱动的云迁移方法,
– 描述了一个向微服务架构或云原生架构的迁移项目,
– 或描述了一种用于云原生迁移的架构转换方法。

最后,我们仅选择了那些详细描述迁移项目或方法的文献,以便能够从中推导出模型驱动的云原生迁移的需求。这种详细程度对于现有应用和转换后的应用都是必要的。用于分析的最终文献如表1所示。

作者 年份 标题+参考文献
弗雷和哈塞尔布林格 2011 cloudmig方法:面向云优化的软件系统基于模型的迁移应用[15]
梅尼赫塔斯等人 2014 使用ARTIST迁移方法论进行软件现代化和云化和框架[16]
莱夫科维茨等人 2016 面向从单体企业系统中提取微服务的技术[17]
Gysel 等人 2016 服务切割器:一种系统化的服务分解方法[18]
Iosifescu‐Enescu 等人 2017 面向云化的自动可扩展网络地理门户的基于云的架构GeoVITe 瑞士学术地理门户[6]
Mazlami 等人 2017 从单体软件架构中提取微服务[19]
Spillner and Dorodko 2017 Java代码分析及转换为AWS Lambda函数[20]
Bucchiarone et al. 2018 从单体到微服务:来自银行业务领域的实践经验报告[5]
Nakazawa et al. 2018 用于通过先单体后微服务方法设计微服务的可视化工具[21]

3.2 案例研究

作为一项案例研究,我们将一个单体应用迁移为基于 FaaS范式的无服务器应用1。我们选择FaaS范式,因为它基于细粒度组件(即函数),并可被视为云计算领域的最新趋势[10]。需要说明的是,该项目的目标并非在性能、成本或可维护性方面改进现有应用,而是探索将现有单体应用迁移到云原生应用的迁移过程。

对于单体应用,我们选择了Spring Petclinic示例应用的REST版本2。尽管该应用相对简单,但它具备基于 Web的应用程序的典型特征,因此适合作为一个贴近现实但又易于理解的示例。该REST版本仅涵盖后端功能,在第一轮迭代中,我们保留了原有的前端。

我们使用了OpenFaaS3作为平台,因为它具有开源特性,并且支持无需依赖云服务商的本地开发。我们也可以选择例如AWS Lambda4,但这将导致相似的结果,因为底层的 FaaS 范式是相同的。然而,OpenFaaS 与 AWS Lambda 之间存在技术差异,因此潜在的转换将不可避免地需要付出努力。该示例应用还包含一个 SQL 数据库,我们在第一轮迭代中直接沿用了该数据库。该项目的目标是使用 OpenFaaS 函数重新实现应用逻辑,并在转换前后对应用建模,以评估采用模型驱动方法实现此目标所需满足的需求。

这些需求随后可与通过文献分析得出的需求进行比较。

4 结果

接下来将介绍双重视角方法论得出的需求。这些需求按照第2.3节中提出的MDE方法进行组织。图3给出了一个概览,该图结合了文献分析和案例研究的结果。

4.1 从文献中得出的需求

4.1.1 现有系统的平台相关模型需求

迁移过程中的第一个逻辑步骤是分析和建模现有应用。现有应用应以平台相关模型(PSM)的形式进行表示,如图3左下角所示。PSM 可由多个部分组成。其核心是作为源代码的应用逻辑。由于在转换过程中需要将现有的单体应用拆分,因此有必要在足够高的抽象层次上对应用进行表示。对于大多数编程语言而言,存在多个可选的抽象层次。以 Java 为例,包是最高层次的抽象,而单个语句则是最低层次的抽象。将系统拆分为微服务的各种方法通常建议采用类级别([19,21])。然而,斯皮尔纳和多罗德科的方法[20]要求在方法级别进行分析,因为他们的方法中会生成符合 FaaS 范式的云函数。弗雷和哈塞尔布林格[15]以及梅尼赫塔斯等人的方法[16]则使用知识发现元模型(KDM)[22],该模型具备在单个语句级别分析应用的潜力。因此,类级别的分析应被视为最低要求,而更细粒度的抽象层次能够实现对组件更精确的拆分。

除了应用的组件外,它们之间的关系对于确定哪些元素属于同一组以及在何处将应用拆分为更细粒度的组件也非常重要。这些关系可以通过静态代码分析生成的依赖关系图来展示,这是一种简单的方法,但仅由莱夫科维茨等人[17]完成。尽管依赖关系图可以显示元素之间的关系,但很难衡量这些关系的强度。因此,Nakazawa 等人[21]提出对系统进行运行时分析,以生成调用上下文树,从而用于说明组件之间关系的强度。

Mazlami 等人[19]使用元数据来确定类之间关系的强度。具体而言,他们利用应用程序开发所使用的版本控制系统中的元数据,例如哪些类被一起修改或由相同的开发人员处理。Gysel 等人[18]也使用关于应用程序的元数据,他们考虑系统所有可用的文档,例如非正式的架构模型或 ERM 图。然而,他们的方法与其他提出的方法不同,因为无需以类或方法的形式表示应用。他们从元数据中推导出一个基于领域驱动设计(DDD)概念的平台无关模型(PIM)。Gysel 等人将应用建模为一组数据、操作和工件元素,这些元素被概括为纳米实体(nanoentities)。然后,这些纳米实体基于所谓的耦合准则进行连接,从而推导出形成服务的纳米实体组。此类元数据通常可以丰富关于现有应用的信息,但也需要更多的 effort 来获取。

对于平台相关模型(PSM)而言,最后一个因素是应用所使用的存储组件或数据库。令人惊讶的是,只有莱夫科维茨等人[17]在其拆分应用的方法中纳入了数据库,更具体地说是数据库模式。然而,数据库是应用的一个重要组成部分,而且由于微服务架构推荐采用分布式数据治理方式,因此在拆分应用时也应考虑对数据库进行拆分。

总结现有应用的平台相关模型(PSM)需求,我们可以说,该应用应在足够的抽象级别上进行表示,以派生出细粒度的组件。类级别是最低要求,但更细粒度的表示更为理想。在考虑元素之间的关系时,应能够标记这些关系的强度。数据库也应包含在PSM中。元数据有助于丰富PSM,但也需要额外的努力来获取。

4.1.2 平台独立模型的需求

然后应将现有应用的PSM映射到PIM。PIM应捕获各个组件内部元素及其关系的加权图概念,如图3左上角所示。有必要将PSM中的信息抽象并映射为有用的 PIM。因此,本文提出了一种PIM的基本建模方法作为示例性解决方案。该方法结合了以下方面的见解:通过捕捉共性并包含被认为有用的特定信息,对相关文献进行分析。组件是建模方法的基本元素,可以是计算组件或存储组件。这种区分非常重要,因为存储组件本质上是有状态的,无法直接利用云环境的弹性。这一点与莱夫科维茨等人[17]的观点一致,他们区分了业务功能和数据库表;Gysel 等人[18]区分了操作与数据;Bucchiarone 等人[5]在新架构的表示中将服务与数据库分别可视化。为了表示应用在类和方法级别上的结构,如第 4.1.1 节所述(基于4.1.1–21]),计算组件可灵活地表示类或方法。例如,若要表达哪些方法属于同一个类,可以使用组件组,而组件组本身也可被视为组件。因此,单体应用可被表示为一个由子组件构成的单一组件。然后根据组件之间的集成与通信关系进行连接。该建模方法应区分同步通信与异步通信,以尽可能推动向异步通信转变。在云原生应用中,通过消息传递实现的异步通信更受青睐,[5]因为它能确保组件间的松耦合,从而提升可扩展性和故障恢复能力。最后,组件可通过附加特性进行描述。

有状态性已在计算组件与存储组件的区分中讨论过。虽然存储组件始终是有状态的,但计算组件通常倾向于无状态,但也可能是有状态的。有必要明确哪些组件是无状态的,因而适用于弹性伸缩,例如在函数即服务(FaaS)中[20],以及哪些组件是有状态的,以便识别改进的可能性。此外,一致性关系对于决定哪些组件应组合在一起、哪些可以分离至关重要。Gysel 等人[18]也将一致性作为拆分应用的依据,因为处理具有更强一致性要求数据的组件应被归为一组,而较弱的一致性要求则更有利于组件的分解。此外,正如 Gysel 等人所采用的,基于领域驱动设计(DDD)的特性可支持基于领域知识的分解。还应考虑安全方面,例如与组件通信是否需要身份验证,或哪些组件必须位于同一虚拟网络中[6]。最后,平台无关模型(PIM)应支持应用聚类或映射算法。这些算法利用组件类型、组件之间的连接关系以及组件特性等信息,对应用进行拆分,并在适用时引入云计算范式。特别是在分解方面,[17–19],或[21]的方法应当因此可以推广,并基于所讨论的平台无关模型建模方法。

对于云原生应用(CNA)的平台无关模型(PIM),采用了相同的建模方法,但需要进行扩展。组件作为子组件集合的概念变得更加重要,因为该应用由细粒度的组件构成。在此组件层次结构中代表最高层级的组件也定义了部署单元。与单体架构不同,将会有多个部署而非单一部署[5]。此外,新增了一种服务组件类型。这是必要的,因为云应用越来越多地依赖于现成的服务而非自行实现的功能。服务是具有明确定义接口的现成组件,例如认证服务、消息队列、媒体处理服务或机器学习服务。通过使用这些服务,可以降低提供此类功能的复杂性。Iosifescu‐Enescu 等人[6]讨论了其转换后应用所需的关键服务,包括可靠消息排队、缓存以及安全相关服务,如虚拟云网络和托管防火墙。在云原生迁移过程中,组件可以被服务所替代。因此,还增加了另一个重要特征:描述一个组件是自管理的还是托管的,例如作为来自云服务商的服务被消费。Iosifescu‐Enescu 等人[6]的迁移项目通过将功能从自管理组件转向云服务商的服务来说明这一点。例如,他们提到了从独立的 PostgreSQL服务器迁移到PostgreSQL数据库即服务(DBaaS)。Bucchiarone 等人[5]所描述的迁移项目则向迁移后的应用引入了基于开源项目的缓存和日志记录服务。例如,使用ElasticSearch5和Kibana6进行日志记录,这可以在所提议的PIM中表示为一个自管理的服务组件。最后,组件之间同步通信与异步通信的区别变得更加重要,在迁移过程中应考虑向异步通信转变,以促进组件间的松耦合[5]。

4.1.3 云原生系统的平台相关模型需求

如图3概览的最后部分所示,提出了云原生应用的平台相关模型的需求。在平台相关模型中,必须具体决定系统应部署在哪里,例如在哪个云服务商或私有云中。在不断发展的云服务环境中,应用程序的部署有多种选择,尽管存在不同的云服务商提供许多相似的服务,如 Iosifescu‐Enescu 等人[6]所列出的,但其差异仍需加以考虑。通常需要决定将多大程度的运营管理问题交由服务商处理。现有的服务模式包括 IaaS、PaaS 和 SaaS[23],以及新兴的 FaaS 模式。此外,还有可作为服务使用的容器编排技术。特别是 Kubernetes,正日益被选为运行 CNAs[24] 的主要技术之一。PIM 中的信息较为抽象,例如仅考虑某个组件的可扩展性要求。因此,PSM 应包含来自云服务商的具体技术选项,正如 Menychtas 等人[16]所提到的,以便实现向 PSM 中具体元素的恰当转换。此外,自动化实践(如持续集成和部署)也应在 PSM 中得到体现,因为如 Bucchiarone 等人[5]所讨论的,只有通过此类实践,才能有效管理包含大量独立组件的细粒度架构。最后需要注意的是,PSM 本身仍是一种模型,源代码以及基础设施描述(例如用于 Kubernetes 的 Pod 清单)应从 PSM 中生成。

4.2 来自案例研究的需求

尽管第4.1节和图3中提出的需求源自文献,但案例研究的目标是验证这些需求,并可能基于迁移过程的实际经验补充其他需求。需要注意的是,在该案例研究中,我们手动完成了应用的转换,未采用特定的分解方法。因此,无需为现有应用创建全面的平台相关模型。尽管如此,我们仍为现有应用创建了基本的 UML图,以探索其在迁移过程中的有用性,并更好地理解现有应用。图4展示了现有应用的一个简化模型,重点说明了与宠物实体相关的功能,该实体作为应用中的一个示例实体。

宠物REST控制器
+获取宠物(int petId)
+获取所有宠物()
+获取宠物类型()
+添加宠物(Pet pet)
+更新宠物(int petId, Pet pet)
+删除宠物(int petId)
+获取宠物(int petId)
+获取所有宠物()
+获取宠物类型()
+添加宠物(Pet pet)
+更新宠物(int petId, Pet pet)
+删除宠物(int petId)
+获取宠物(int petId)
+获取所有宠物()
+获取宠物类型()
+添加宠物(Pet pet)
+更新宠物(int petId, Pet pet)
+删除宠物(int petId)
宠物类型REST控制器
主人REST控制器
根REST控制器
模型 模型 模型
模型 模型 模型
Vet Vet
专业 专业
Pet 主人 User Pet 主人 User
Pet 主人 User Pet 主人 User
Pet 主人 User Pet 主人 User
Pet 主人 User Pet 主人 User
角色 角色 角色
角色 角色 角色
REST接口 服务
诊所服务实现
+ findPetById()
+ findAllPets()
+获取宠物类型()
+ savePet()
+ deletePet()
+其他控制器的方法
仓库
宠物仓库 <<接口>>
+ findPetTypes() + findById() + save()
+ findAll()
+ delete()
访问REST控制器 访问仓库
兽医控制器 兽医仓库
用户控制器 用户仓库
专业仓库
专业控制器

示意图2

可以看出,该应用包含一系列实体,这些实体显示在图4左下角的模型包中。基本上,每个实体都有一个提供CRUD操作的REST控制器和一个连接到数据库的仓库。控制器使用一个服务类,该类将所有实体的功能集中在一个类中,并在控制器和仓库之间进行协调。由此可以明显看出,为了实现细粒度的拆分,有必要在方法级别上表示现有应用。因此,尽管UML图的基本粒度是在类级别,我们还是连接了类的方法。

然而,对于实体类来说,在其方法级别上表示它们是没有意义的,因为它们是作为完整对象使用的。因此,系统在类级别以及方法级别的混合表示是平台相关模型的要求。

UML图还为我们提供了类和方法的基本依赖关系图。该依赖关系图突显了应用内部的紧密耦合。然而,对于有意义的分解而言,仅知道一个组件依赖于另一个组件是不够的。还需要有关关系强度的信息。根据我们的手动方法,可以通过理解组件的名称和功能来提取其语义信息。但对于更自动化的模型驱动方法,则需要提取更多信息,例如在现有应用的PSM需求中描述的元数据。这一问题也存在于使用Spring框架的过程中。尽管Spring通过使用注解简化了应用开发——这些注解由Spring解释以提供功能,但组件之间的关系可能隐藏在这些注解背后,因此需要额外的工作来提取框架特定信息。

另一个明显的问题是,需要将数据库纳入现有应用的平台相关模型(PSM)和平台无关模型(PIM)中。仅仅关注应用逻辑是不够的,拆分应用时需要考虑各个部分,因为组件可能通过数据库紧密耦合。在案例研究中,只有在函数中同时复制其他被引用实体的模型和仓库类时,才能实现每个实体对应一个OpenFaaS函数的方式拆分应用。为了将应用拆分为每个函数仅处理一个实体的形式,还必须修改数据库。这显然会影响一致性考虑,因此验证了在PIM中描述一致性要求的需求。例如,一只宠物属于一个主人,因此依赖于该主人的存在。如果处理宠物和主人的逻辑被分离,当删除一个主人时,问题就出现了:如何确保相关的宠物也被删除,是否允许出现不一致视图(即没有主人的宠物),还是需要强一致性。必须能够反映哪些组件需要被分组并部署在同一个聚合组件内以确保一致性,或者需要采取哪些额外措施来确保跨多个组件的最终一致性。

最后,用户认证在转换后的应用中是一个挑战。在单体应用中,通过Spring使用注解来处理用户认证以及配置调用特定操作所需的用户角色,并且这些配置是全局可用的。而在转换后的应用中,我们使用了一个额外的认证函数,因为OpenFaaS对此提供的支持较少。在云原生应用中,身份验证理想情况下应由明确的身份验证服务以及位于客户端和实际应用服务之间的网关组件来处理。在平台无关模型中,这可以通过进一步的组件特性来表示,这些特性描述了组件的安全性和身份验证需求。

5 讨论

基于文献和一项案例研究,我们得出了模型驱动的云原生迁移方法的需求,总结如图3所示。目前该方法仍处于概念阶段,所提出的需求在其实际实现中需要进一步评估。对于实际实现,还存在其他方面和挑战,将在下文进行讨论。

5.1 迁移前可行性研究的重要性

Jamshidi 等人开发了一个全面的云迁移框架[11],其主要阶段包括迁移规划、迁移执行和迁移评估。本文讨论的模型驱动方法属于迁移执行阶段,在该阶段实际执行系统的迁移。然而,迁移规划阶段对于一个成功的迁移项目至关重要,因为在该阶段会进行评估和可行性研究,以确定是否需要迁移以及迁移的目标是什么。所提出的模型驱动的云原生迁移方法可能并不适用于所有类型的应用。因此,在应用该方法之前,应充分分析和评估迁移的可行性。分析阶段的结果和决策对于架构转换阶段以及将精细化的平台无关模型转换为特定的平台相关模型也具有重要价值,有助于合理决策应用应如何拆分和部署。

5.2 技术异构性

考虑到现有应用的另一个挑战是它们在技术上的高度异构性。其中编程语言是关键因素,但即使在同一编程语言内部也存在差异。正如我们在案例研究中所经历的,该示例应用虽然是用Java编写的,但与其他 Java实现并不相同,因为它基于Spring框架,而该框架引入了其自身的特定机制。因此,为了使该方法具有普遍适用性并能通过工具提供支持,需要针对不同的编程语言和框架开发不同的平台特定模型。然而,该方法的优势在于仅在平台特定模型中处理技术异构性。如果平台独立模型与实际实现无关,即使技术不断发展,它们也能保持稳定。

如果通过为相关技术提供多种PSM来应对技术异构性,那么所提出的方法是否适用于所有应用的问题仍然存在。单体应用往往具有高度的集成性。我们已经提出,有必要在方法层面分析现有系统。但可能存在一些系统,其单个方法本身就很复杂,并且捆绑了多种功能,理想情况下应将其拆分为不同的组件。在这种情况下,如果不想将应用从头开始重写为云原生应用,则在应用所提出的方法之前,可能需要先对现有系统进行重构。

5.3 数据库的重要性

从我们的角度来看,目前尚未得到充分重视的一个方面是数据库的包含。这也是弗朗西斯科等人调查的结果:“令人惊讶的是,超过一半的参与者报告称在迁移过程中未对现有数据进行迁移”[2]。为了充分受益于云原生应用的优势,也需要像拆分应用逻辑组件一样对数据库进行相应的拆分。我们在案例研究中也遇到了这一问题。由于在第一次迭代中我们仅将应用逻辑拆分为函数,而保持数据库不变,因此不得不复制代码以维持与数据库的通信方式。这导致函数之间的独立性不如预期。此外,由于所有函数都使用同一个数据库,我们还遇到了过多打开数据库连接的问题。

因此,系统的耦合不仅存在于应用逻辑中,也存在于数据库中;要实现全面的迁移,数据库同样需要被处理。当数据被分离时,必须考虑整个应用所需的事务一致性级别。因此,一致性方面的考量也应纳入所提出方法的平台无关模型中。

5.4 用户界面的重要性

另一个迄今为止尚未解决的方面是用户界面(UI)。应用的耦合不仅体现在应用逻辑中,也体现在数据库中,这一观点同样可以延伸到用户界面。对于基于Web和移动应用而言,通常采用将服务器端与客户端分离并通过 REST进行通信的架构。基于这种分离,可以利用服务器端的独立性,将其迁移到云原生应用,而保持客户端不变。

然而,正如我们在案例研究中所经历的那样,如果客户端期望通过单个请求获取集成数据,则可能会导致问题。当应用在服务器端通过将实体相互解耦合而被拆分时,服务器端将无法再提供不同实体的聚合。因此,客户端需要针对不同实体发出多个请求,而不是一个请求。此外,客户端本身也需要进行迁移。在本文分析的文献中,用户界面很少被提及,因此在所提出的模型驱动方法中并未体现。然而,用户界面不应被忽视,最终可能有必要通过显式组件在建模中将其包含进来。

5.5 半自动化转换

所提出方法的关键阶段是架构转换阶段,在此阶段中对平台无关模型(PIM)进行转换。该阶段应将迁移项目所预期的利益在架构中予以确立。然而,可能的解决方案范围广泛,仅基于技术因素难以做出决策。必须引入来自应用特定领域的业务知识,而这些知识只能由人工专家提供。因此,我们认为该阶段只能实现半自动化,理想的方案是人工专家在工具支持下完成架构转换。该工具应为预期的云原生应用(CNA)提供一个包含系统约束的框架,同时具备足够的灵活性,以设计出适配的解决方案。一种可能的扩展是引入云原生应用(CNAs)的通用蓝图或模式,以指导架构转换阶段。

对于从云原生系统的PSM生成代码的最后一步,一种合理的方法是仅生成预期系统的基架。实际的实现仍由软件工程师完成,以确保正确的功能,并为最后的完善工作提供灵活性。

6 相关工作

本文的主题涉及多个研究主题的交叉,例如云原生应用、微服务、云迁移和模型驱动工程。一项具有相似目标的值得注意的工作是ARTIST项目[16]。它提供了一套完整且由工具支持的将传统系统迁移到云的方法论。Jamshidi 等人[11]所描述的所有阶段均被支持,即迁移规划、迁移执行和迁移评估。基本上,ARTIST项目的方法论和工具涵盖了如图2所示的相同流程,但其重点是当时云计算的发展状态。此外,该项目缺乏最近的更新工具支持7以及方法论本身,应用转换步骤并未像本文所提出的那样聚焦于云原生应用。尤其是将应用分解为细粒度组件并不是一个主要关注点。因此,本文提出的方法与ARTIST项目有许多共同之处,但在一些基本特征上有所不同。尽管如此,ARTIST项目期间开发的一些工具支持可能可被复用并适用于本方法。

拉德马赫等人[25]提出了一种基于领域驱动设计(DDD)的微服务模型驱动工程方法。他们使用 DDD来捕获应用的平台无关功能,并开发了UML元模型8,可用于对应用进行建模并生成相应的代码。然而,他们的重点在于新应用开发,而非迁移。因此,将他们的方法与本文的方法在已迁移系统的PIM上进行结合是可能的,但他们不支持架构转换阶段。

弗里茨希等人[26]综述了明确关注架构转换阶段的相关工作。弗里茨希等人回顾了将现有应用分解为微服务的方法。这种分解是架构转换阶段的关键部分。因此,所综述的方法具有高度相关性,其中一些方法也被纳入本文的文献分析中([17–19])。然而,与这些已综述的方法不同的是,本文提出的方法明确聚焦于云原生应用,从而在转换阶段引入了云计算范式。

最后,还有一些方法旨在优化已基于微服务的现有应用的架构。与生成应用的PSM阶段类似,格兰切利等人[27]以及迈耶和魏因赖希[28]提出了提取微服务架构的方法。格兰切利等人使用来自源代码和应用日志的静态信息,而迈耶和魏因赖希认为只有在运行时进行分析才能为彻底的架构分析提供足够的信息。采用模型驱动方法时,如果模型能够与实现保持同步,则这可能并非必要。然而,这些方法有助于验证转换后的应用是否实现了迁移所追求的目标。

7 结论

基于文献分析和案例研究,我们推导出了一个建议的模型驱动云原生迁移方法。这些需求根据迁移的不同阶段以及各阶段所需的模型进行分组。针对第1节中提出的研究问题,这些需求提供了具体的答案。所需的信息和抽象级别通过组件类型及其关联关系来捕获,而受益于云原生范式的各个方面则体现在组件类型及其特性中。

本文的贡献在于提出了相关需求以及所提议方法的概述。这些需求可用于推进云原生迁移的模型驱动研究。特别是,可根据这些需求开发该方法中平台无关模型和平台特定模型的元模型。基于这些元模型,需要工具支持来从现有应用中提取具体模型,并从模型生成代码。

此外,可以使用模型来表达典型的迁移模式和规则,以指导迁移过程。通过提供典型模式,可以支持所讨论的半自动架构转换。这一点尤为重要,因为云原生应用的可能解决方案空间较大。因此,这为该主题的后续研究工作奠定了基础。但第5节中讨论的挑战需要被重视并加以应对。这些挑战在具体的迁移项目之间的重要性有所不同,但它们源于云原生应用的普遍特性,因此对云原生应用的一般性研究具有重要意义。总体而言,云原生是基于Web的应用程序的首选范式,为其开发提供结构化支持有助于开发人员高效且有效地实现这些应用。

更多推荐