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

如何用图分析可视化微服务架构

时间:2023-03-15 14:40:46 科技观察

【.com快译】你在自己的项目中使用过微服务吗?您在使用过程中是否遇到过一些意想不到的问题?本文将通过分析基于SpringCloud的微服务系统、jQAssistant、Neo4j,与大家探讨如何使用图技术检测反模式,可视化整个系统,分析跨服务影响。背景几年前,一个客户要求我用微服务重写他们的IT系统。但是在开发的最后,遇到了代码缺陷,无法返回等问题。虽然现场团队进行了反复的review和重构会议,但由于系统规模(生产环境超过13个微服务),调整难度大,收效甚微,所以最终产品的质量是与他们的预期相去甚远。可见,人们往往低估了从传统方法向微服务架构转换的难度,尤其是当生产环境中有数千行代码时,人们往往无法对目标系统有清晰的认识,无法确定范围要执行的任务。优先排序,直到出现问题时为时已晚。使用图分析来识别问题并修复微服务架构经过研究,我发现了一个非常有用的工具——jQAssistant。它帮助我将代码、软件架构和所有附带的规则转换为Neo4j中的图形。我发现转换图形将有助于:检测反模式、执行影响分析、改进数据治理以及促进团队之间的沟通。下面我们将通过分析一个具体的应用实例来详细讨论图形化转换的过程。一个应用示例这里我们将使用经典的PiggyMetrics项目。由SpringBoot和SpringCloud开发,基于MongoDB数据库的个人会计微服务应用。该应用程序的图形转换相对简单。如上图所示,我们只需要准备构建应用程序所需的JAR文件,然后通过命令行将JAR文件提供给jQAssistant即可。几秒钟后,你会得到相应的简单图形。如上面的代码片段所述,PiggyMetrics应用程序中的类UserController是一个标准的SpringRestController。它定义了两个名为getUser和createUser的方法。两者都带有绿色的@RequestMapping注释。在这些注释中,我们可以找到映射到各种NPC的HTTP动词。最后还有一个叫userService的调用。下图是控制器对应的图形。从图中可以看出,代码的不同部分由各种节点和关系表示。示例:在左侧,红色节点表示JAR文件,它通过CONTAINS关系链接到蓝色UserController类。并且UserController类本身将链接到getUser和createUser方法以进一步调用其他方法。当然,我们在前面代码中看到的注解、请求映射、参数都会在图中显示为绿色。由此,我们将能够轻松检查代码、类或模块之间的循环依赖、是否遵守命名约定以及架构规则(例如特定代码是否被测试覆盖)。松耦合的微服务很多人认为松耦合的微服务通过HTTP、异步协议、消息协议进行通信,而这种通信并没有体现在字节码中。我们需要在此基础上用图形来表示代码。也就是说,除了语言和框架,我们还会用软件架构这个更高层次的概念来表示应用程序中的API和不同的工程实践。让我们回到上面的UserController示例。多亏了Spring框架,我们可以遍历图来识别具有正确注释的方法,这些方法又映射到一些HTTP动词。上图显示了一个Cypher查询。通过使用@RequestMapping注释的浏览方法将HTTP信息输入到图中。端点作为一个新概念引入图中。图中左侧的蓝色代码行可以以指令的形式为发现的内容添加端点标签,为那些暴露为REST端点的已知方法节点添加HTTP映射信息。这里我们定义了一些淡蓝色的REST端点。它们可以匹配上面提到的getUser和createUser方法,以及它们的不同路径。参照端点的定义方式,我们还可以定义HTTP客户端的相关概念。例如:由于PiggyMetrics应用程序使用Feign库在两个服务之间进行HTTP调用,我们可以使用它来遍历图形并通过查找FeignClient注释及其相关信息来创建新概念。就像公开一些REST端点的控制器一样,我们制作HTTP客户端,如上图所示。它使用HTTP动词调用URL。也就是说,我们可以将带有URL信息的FeignClient标签作为一个新的概念添加到图中。一旦确定了HTTP客户端和REST端点,我们就可以根据这些新概念轻松地将它们连接到各种匹配的HTTP方法和它们使用的URL。例如,在下面的代码图中,我们通过一个名为INVOKES_REMOTE的关系在图中展示了这个过程。因为服务是松耦合的,所以我们可以识别服务之间的依赖关系,并使这些松耦合在图中显而易见。从下图中的可视化内容,我们可以清楚的看到这四个服务以及它们之间的相互调用。由此,我们可以找到可能的反模式,例如导致服务之间“先有鸡还是先有蛋”的循环问题。当然,我们也可以进行影响分析,找出端点修改难度等问题。微服务还是分布式整体?通过图表分析,我们还可以看到微服务是否遵循最佳实践,从而提高服务实现的成熟度。如下例所示:数据治理在之前的PiggyMetrics应用中,我们不仅可以通过MongoDB和SpringData轻松定义持久化实体的概念,还可以查看跨服务MongoDB集合的使用情况。下图显示我们查询到的账号集合被两个不同的服务调用。基于这两个服务之间的隔离性,我们判断应该将它们合并。当然,我们还可以发现更多同一个数据库在多个地方同时管理的情况。由此,我们还可以定义哪些端点直接或间接受到哪个数据存储库中更改的影响。如上数据表所示,最下面的“UserRepository”是远程服务间接使用的。如果我们想改变它,我们需要检查远程服务可能会受到怎样的影响。而这些是你无法仅仅通过查看存储库中的相关代码或单个服务来学习的东西。通过上面提到的jQAssistant,我们可以为JDBC扫描数据库中的元数据,将数据库的结构映射到图上。基于此,我们接下来可以对MongoDB进行更高级的影响分析,或者进行数据列级别的分析进行验证。也就是说,如果我们要改变一个数据库的数据格式或者一个列的长度,我们需要识别所有与该列相关的对象。文档是最新的吗?微服务领域的另一个最佳实践是预先采用契约优先的方法,即首先定义API规范,然后执行它。例如,我们可以先选择当前业界标准化的OpenAPI规范,然后使用YAML文件编写API合约。然而,您可能会遇到的问题是:您如何知道您实施的规范或文档是否是最新的?如上图所示,我们可以通过扫描YAML文件,在文件内容中找到OpenAPI的相关说明。也就是说,通过遍历所有YAML文件,我们寻找一个名为OpenAPI的密钥来检查每个服务是否至少包含一个规范文件。此外,它还是一种检索丢失文档的快速方法。此外,就文件本身而言,我们甚至可以进一步下钻,看看文件到底是什么。例如,我们可以从中同时提取参数名称和类型,并使用Spring控制器进行相同的操作,对比两者的实际检测差距。如下图所示,通过查询,我们很快发现某项服务缺少相应的文档。即:在三个端点中,只有两个具有实际文档。此外,我们能够深入“挖掘”API参数及其参数类型。健壮性健壮性是一个很重要的方面,它可以应对生产环境中的故障??,从而避免整个系统崩溃。通常我们可以采用熔断器、响应回退等主流机制,避免让故障影响到上层服务。要检查所有端点或HTTP客户端是否已实现正确的回退,我们可以使用上面的简单查询来查看它们是否具有通过遍历FeignClient注释声明为回退的属性。如上图所示,在PiggyMetric示例中,我们发现服务中缺少两个回退。信息共享为了共享,我们经常需要创建一个可视化文件。拥有开放图数据库的好处是可以有选择地将图导出为GraphML文件,然后使用yEd等工具将GraphML文件导出为可视化数据。而且,在yEd中,你可以自定义样式和布局,以满足大量元素的实际需求。如下图所示,您可以导出多种不同形状的模式数据。作为服务之间依赖关系的一个简单示例,我们可以更改它以提供我们需要的东西,或者导出为有用的停靠可视化。可以看出,这种视觉转换对于开发团队和架构师之间的沟通、产品负责人和项目经理之间的对话、让他们更好地理解需要完成的工作是非常有用的。为了让您对系统的图形表示有一个整体印象,下图显示了一个真实的应用示例。值得一提的是,如果没有工具的帮助,我们很难手动完成此类图形的构建。更重要的是,我们的系统通常是动态开发的。更实际的场景上面的例子可能过于简单化了。在实际应用中,图分析还可以应用到更多的实际场景中。例如,我们可以通过依赖分析更深入地挖掘安全问题,然后通过寻找端点上的注解来加强安全性。另外,我们可以通过导入runtime的数据,了解到一个API每天被调用的次数,然后为API的重要性分配一个权重。当然,我们也可以从版本控制系统中导入数据,根据源代码的依赖关系来确定变更的优先级。很显然,那些很少修改的服务就意味着它们基本可以正常工作,所以我们不必太在意。一般来说,您可以根据您当前的需求和架构,使用基本的源代码来构建反映更高层次概念的图形。由此,您可以获得目标系统的实时更新,检查它与原计划的匹配程度,并及时改进实际的架构规则。原标题:FixingYourMicroservicesArchitectureUsingGraphAnalysis,作者:NicolasMervaillie