从单体到微服务:4个现代化最佳实践

通过使用自动化和人工智能来分析和公开以前包含在单体黑匣子中的新服务边界,你现在可以开始在建议的参考架构中操作服务,该架构为基于数据驱动分析做出更好的决策扫清了道路。

本文来自开源云中文社区。

当涉及到将单体应用程序重构为微服务时,大多数工程团队不知道从哪里开始。此外,最近的一项调查显示,79%的现代化项目失败,平均花费150万美元和16个月的时间。

在盲目进行现代化项目之前,必须了解技术债务积累、创新和所有权成本、复杂性和风险等因素。

事件风暴练习、领域驱动设计(DDD)、Strangler Fig Pattern和其他都是要遵循的有用概念,但作为架构师或开发人员,如何将单体应用程序重构为微服务?

完成这项工作的最佳实践有很多种,在这篇文章中,我们将探讨一些具体的行动,以智能地将单体分解为微服务。

这些操作包括识别服务域、将两个服务合并为一个服务、将服务更精确地重命名以及删除作为微服务提取候选的服务或类。最好的部分是:我们将使用人工智能(AI)和自动化来实现目标,而不是试图手动完成这些工作。

最佳实践1:自动识别服务和域

调查表明,使用白板上的便签手动分析一个单体的时间太长,成本太高,很少成功。团队中的哪一位架构师或开发人员有时间和能力手工审阅数百万行代码和数万个类?大型单体应用程序需要一种自动化、数据驱动的方法来识别潜在的服务边界。

让我们选择一个现成的、真实的应用程序作为平台,在其中探索这些最佳实践。作为Java开发人员的教程示例,Oracle提供了一个医疗记录(MedRec)应用程序——也称为Avitek医疗记录应用程序,它是一个使用WebLogic和Java EE的传统单体。

使用vFunction,我们将启动一个“学习”阶段,使用基于调用树和系统流的动态分析、静态分析和机器学习来识别理想的服务域。

2345截图20220818151609.png

图1:此服务图显示了为提取而标识的单个服务

在图1中,我们看到一个服务图,其中服务显示为不同大小和颜色的球体,以及连接它们的线(边)。每个球体表示vFunction自动识别为与特定域相关的服务。这些服务的名称和详细信息显示在屏幕右侧。

球体的大小表示服务中包含的类的数量。颜色表示每个服务中的类“排他性”级别,指的是仅存在于该服务中的类别的百分比,而不是跨多个服务共享的类别。

红色代表低排他性,蓝色代表中排他性和绿色代表高排他性。较高的类排他性表明服务之间的边界更好,相互依赖性更少,代码重复更少。综上所述,这些特征表明,将高度独占的服务重构为微服务将不那么复杂。

2345截图20220818151609.png

图2和图3:实线和虚线表示服务之间的不同关系

这里的实线表示跨服务共享的公共资源(图2)。常见资源包括bean、同步对象、只读DB事务和表、读写DB事务和表、WebSocket、文件和嵌入式文件等。虚线表示服务之间的方法调用(图3)。

中间的黑色球体表示仍处于单体中的类,其中包含不特定于任何特定域的类和资源,因此未被选为提取的候选对象。

通过使用自动化和人工智能来分析和公开以前包含在单体黑匣子中的新服务边界,你现在可以开始在建议的参考架构中操作服务,该架构为基于数据驱动分析做出更好的决策扫清了道路。

最佳实践2:整合功能并避免重复

当一切都在单体中时,能见度有限。如果能够公开建议的服务边界,你可以开始做出决策并测试设计概念,例如,识别多个服务中的重叠功能。

什么时候将具有类似功能的不同服务整合到单个微服务中才有意义?最基本的例子是,作为一名架构师,你可能会看到将两个看起来重叠的服务组合在一起的机会,我们可以根据类名和类排他性级别来识别这些服务。

2345截图20220818151609.png

图4:两个类似的服务已被确定要合并

在服务图(图4)中,我们看到了两个类似的聊天服务,它们用白色圆圈勾勒出来:PatientChatWebSocket和PhysicanChatWebSocket。我们可以看到,Physican聊天服务(红色)具有0%的动态排他性,而Patient聊天服务(蓝色)具有略高的排他性(33%)。

这两个服务都没有使用任何共享资源,这表明我们可以将这些资源合并到一个服务中,而不会因为我们的操作而纠缠任何东西。

2345截图20220818151609.png

图5:确认合并服务的决定可以通过按下按钮立即回滚

通过合并两个类似的服务,你可以合并重复的功能,并在新合并的服务中增加类的排他性(图5)。由于我们在本例中使用vFunction平台,逻辑绑定这些服务所需的一切都得到了处理——类、入口点和资源都得到了智能更新。

2345截图20220818151609.png

图6:新合并的单个服务现在表示两个以前的聊天服务

合并服务就像将一个服务拖放到另一个服务上一样简单,在vFunction平台重新计算对该操作的分析后,我们看到球体现在是绿色的,动态排他性为75%(图6)。这表明新合并的服务在类级别上互连较少,并使我们有机会以较低的复杂性提取此服务。

最佳实践3:为服务创建准确和有意义的名称

我们都知道给事物命名很难。在处理单体服务时,我们实际上只能使用类名来了解发生了什么。仅凭这些信息,很难准确识别哪些类和功能可能属于特定的域。

在示例中,vFunction从图7中屏幕右侧的类名中自动导出服务域名。作为架构师,你需要能够根据偏好和需求重命名服务。

2345截图20220818151609.png

图7:将合并的服务更精确地重命名

现在让我们回到上一节中合并的两个聊天服务。虽然以前我们有一个用于患者和医生聊天的服务,但现在我们有了一个代表这两个配置文件的单一服务,因此PatientChatWebSocket的名称不再准确,可能会导致将来使用此服务的其他开发人员产生误解。我们可以选择一个更好的名称,例如ChatService(图7)。

2345截图20220818151609.png

图8:将自动识别的服务重命名为更有意义的服务

在图8中,我们可以看到另一个名为JaxRSRecordFacadeBroker(+2)的服务。这里的(+2)部分表示我们有属于多个类的入口点。你可能会发现此名称具有不必要的描述性,因此可以简单地将其更改为RecordBroker。

通过以更准确和更有意义的方式重命名服务,可以确保工程团队能够以直接的方式快速识别和处理未来的微服务。

最佳实践4:确定不应作为单独微服务的功能

什么品质表明,以前包含在一个整体中的功能应该成为一个微服务?并不是所有的东西都应该成为一个微服务,所以什么时候你想删除一个作为分离和提取候选的服务?

你可能会决定某些服务实际上不属于单独的域,例如,一个只过滤消息的过滤器类。因为这不是任何特定服务所独有的,所以你可以决定将来将其移动到公共库或其他服务。

当删除作为未来提取为微服务的候选功能时,您决定不将此类视为接收流量的单独入口点。让我们看看AuthenticationAdministrationController服务(图9),它是一个简单的控制器类。

2345截图20220818151609.png

图9:删除一个非常简单的非特定服务

在图9中,我们可以看到所选类的红色排他性很低,而且它是一个非常小的服务,只包含一个动态类、一个静态类,没有资源。你可以决定它本身不应该是一个单独的服务,并通过将其拖放到中间的黑色球体上来删除它(图10)。

2345截图20220818151609.png

通过将这个类重新定位到单体,我们已经确定这个特定的功能不满足成为单个微服务的要求。

在本文中,我们展示了架构师和开发人员可以遵循的一些最佳实践,以便将单体应用程序重构为有界的上下文和精确的域,用于未来的微服务提取。

通过使用vFunction平台,使用人工智能和数据驱动分析,许多繁重的起始和手动工作已经自动化。这确保了架构师和开发团队可以将时间集中在基于智能建议的参考架构上,而不是在没有适当的“全局”上下文的情况下花费数千小时手动分析小块代码。

原文链接:

https://thenewstack.io/monoliths-to-microservices-4-modernization-best-practices-2/

THEEND

最新评论(评论仅代表用户观点)

更多
暂无评论