当谈到将单体应用程序重构为微服务时,大多数工程团队都不知道从哪里开始。此外,最近的一项调查显示,79%的现代化项目失败了,平均耗资150万美元,需要16个月才能完成。在盲目着手现代化项目之前,必须了解技术债务积累、创新和拥有成本、复杂性和风险等因素。事件风暴练习、领域驱动设计(DDD)、StranglerFigPattern等都是需要遵循的有用概念,但作为架构师或开发人员,您如何将单体应用程序重构为微服务?完成这项工作有很多最佳实践,在这篇文章中,我们将探索一些具体的操作,以智能地将整体分解为微服务。这些操作包括识别服务域、将两个服务合并为一个、更准确地重命名服务以及删除作为微服务提取候选对象的服务或类。最好的部分:我们将使用人工智能(AI)和自动化来实现,而不是尝试手动完成。最佳实践1:自动识别服务和领域调查表明,使用白板上的便利贴手动分析单例太长、太昂贵,而且很少成功。团队中哪个架构师或开发人员有时间和能力手动审查数百万行代码和数万个类?大型单体应用程序需要一种自动化的、数据驱动的方法来识别潜在的服务边界。让我们选择一个现成的真实应用程序作为探索这些最佳实践的平台。作为Java开发人员的教程示例,Oracle提供了一个医疗记录(MedRec)应用程序——也称为Avitek医疗记录应用程序,它是一个使用WebLogic和JavaEE的传统单体。使用vFunction,我们将启动一个“学习”阶段,使用基于调用树和系统流的动态分析、静态分析和机器学习来识别理想的服务域。图1:此服务图显示了识别为要提取的各个服务在图1中,我们看到一个服务图,其中服务显示为不同大小和颜色的球体,以及连接它们的线(边)。每个球体代表一个vFunction,自动识别为与特定域关联的服务。这些服务的名称和详细信息显示在屏幕右侧。球体的大小表示服务中包含的类数。颜色表示每个服务中类“排他性”的级别,指的是仅存在于该服务中的类的百分比,而不是跨多个服务共享的类。红色代表低排他性,蓝色代表中等排他性,绿色代表高排他性。更高的类排他性表明服务之间的边界更好、相互依赖性更少以及代码重复更少。总而言之,这些特征表明将高度排他性的服务重构为微服务将不那么复杂。图2和图3:实线和虚线表示服务之间的不同关系这里的实线表示跨服务共享的公共资源(图2)。常见资源包括bean、同步对象、只读DB事务和表、读写DB事务和表、WebSocket、文件和嵌入式文件等。虚线表示服务之间的方法调用(图3)。中间的黑色球体表示仍然处于单例中的类,包含不特定于任何特定域的类和资源,因此未被选为提取的候选者。通过使用自动化和人工智能来分析和揭示以前包含在单一黑匣子中的新服务边界,您现在可以在建议的参考架构中开始运营服务,这为基于数据驱动的分析做出更好的决策扫清了道路。最佳实践#2:整合功能并避免重复当一切都在一个整体中时,可见性是有限的。能够公开建议的服务边界允许您开始制定决策和测试设计概念,例如,识别跨多个服务的重叠功能。什么时候将具有相似功能的不同服务组合到一个微服务中才有意义?最基本的例子是,作为一名架构师,您可能会看到一个机会,可以将我们可以通过类名和类排他性级别识别的两个看似重叠的服务结合起来。图4:已确定要合并的两个相似服务在服务图中(图4),我们看到用白色圆圈勾勒出两个相似的聊天服务:PatientChatWebSocket和PhysicanChatWebSocket。我们可以看到,Physican聊天服务(红色)的动态排他性为0%,而Patient聊天服务(蓝色)的排他性略高(33%)。两种服务都不使用任何共享资源,这表明我们可以将这些资源组合到一个服务中,而无需为我们的操作纠缠任何东西。图5:确认合并服务的决定可以通过按下按钮立即回滚通过合并两个相似的服务,您可以合并重复的功能并增加新合并服务中的类排他性(图5)。因为我们在这个例子中使用了vFunction平台,所以逻辑上绑定这些服务所需的一切都得到了处理——类、入口点和资源都被智能地更新了。图6:新合并的单一服务现在代表两个以前的聊天服务。合并服务就像将一项服务拖放到另一项服务上一样简单,在vFunction平台重新计算此操作的分析后,我们看到球体现在是绿色的,动态排他性为75%(图6)。这表明新合并的服务在类级别的互连较少,让我们有机会以较低的复杂性提取此服务。最佳实践#3:为服务创建准确且有意义的名称我们都知道命名事物很困难。在处理单体服务时,我们真的只能使用类名来了解发生了什么。仅凭此信息,可能很难准确识别哪些类和函数可能属于特定域。在示例中,vFunction自动从图7屏幕右侧的类名派生服务域名。作为架构师,您需要能够根据喜好和需要重命名服务。图7:合并服务的更精确重命名现在让我们回到上一节中合并的两个聊天服务。虽然之前我们有一个用于患者和医生聊天的服务,但现在我们有一个代表两个配置文件的服务,因此PatientChatWebSocket名称不再准确,并且可能会导致使用此服务的其他开发人员在未来出现问题时产生误解。我们本可以选择更好的名称,例如ChatService(图7)。图8:将自动识别的服务重命名为更有意义的名称在图8中,我们可以看到另一个名为JaxRSRecordFacadeBroker(+2)的服务。这里的(+2)部分意味着我们有属于多个类的入口点。您可能会发现此名称具有不必要的描述性,因此您可以将其简单地更改为RecordBroker。通过以更准确和更有意义的方式重命名服务,您可以确保工程团队能够以直接的方式快速识别和处理未来的微服务。最佳实践4:识别不应该是单独微服务的特性哪些特性表明以前包含在单体应用中的特性应该成为微服务?并不是所有的东西都应该是微服务,那么你什么时候想要移除一个作为分离和提取候选者的服务呢?您可能决定某些服务实际上不属于单独的域,例如仅过滤消息的过滤器类。由于这不是任何特定服务所独有的,您可能会决定将其移至公共库或将来的其他服务。当删除功能作为将来提取为微服务的候选功能时,您决定不将此类视为接收流量的单独入口点。让我们看一下AuthenticationAdministrationController服务(图9),它是一个简单的控制器类。图9:删除一个非常简单的非特定服务在图9中,我们可以看到所选类的红色排他性很低,是一个非常小的服务,只包含一个动态类,一个静态类,没有任何资源.您可以决定它本身不应该是一个单独的服务,并通过将其拖放到中间的黑色球体上来删除它(图10)。通过将此类重新定位到单体,我们确定此特定功能不满足作为单个微服务的要求。在本文中,我们展示了架构师和开发人员可以遵循的一些最佳实践,以便将单体应用程序重构为限界上下文和精确域,以便将来进行微服务提取。通过使用vFunction平台,使用人工智能和数据驱动的分析,许多繁重的工作和手动工作已经自动化。这确保架构师和开发团队可以将时间集中在智能建议的参考架构上,而不是花费数千小时在没有适当的“全局”上下文的情况下手动分析小块代码。原文链接::https://thenewstack.io/monoliths-to-microservices-4-modernization-best-practices-2/
