如何使用 GraalVM 减少与 Kafka 集成测试中的内存消耗

    在本文中,我想分享我使用 GraalVM 为 EmbeddedKafka 创建本机映像的经验。在集成测试中使用此映像不仅可以加快测试场景的执行速度,还可以减少内存消耗。有趣的是,与在 Testcontainers 中使用 confluentinc/cp-kafka 相比,在速度和内存使用方面存在明显差异

35faddb64ff2bec310ce0eb32704b2c7.jpeg

EmbeddedKafka、Testcontainers 和 GraalVM

项目中使用的关键组件的简要概述:

EmbeddedKafka 

        EmbeddedKafka 是一种允许将 Kafka 服务器直接嵌入到 JVM 应用程序或测试环境中的工具。这对于使用 Apache Kafka 进行数据流处理或作为消息传递系统的应用程序的集成测试非常有用。EmbeddedKafka 主要用于与 Kafka 交互的隔离测试,由于其快速启动和关闭,因此简化了测试的设置和管理。这确保了测试在不同环境中的可重复性,并提供了对 Kafka 配置的控制。但是,由于 Kafka 的资源密集型特性和对数据存储的需求,在 JVM 应用程序中运行嵌入式 Kafka 会增加内存使用量。这是在开发便利性和额外内存负载之间的权衡,使得外部 Kafka 服务器(相对于 JVM 应用程序)更适合生产环境或内存资源有限的情况。

Testcontainers 

        Testcontainers 是一个框架,用于支持使用 Docker 容器的自动集成测试。它允许在测试执行期间创建、管理和删除容器。使用 Docker 容器可确保测试环境在不同机器和平台上的一致性,从而简化本地开发和测试。在 Testcontainers 中使用 Kafka 有几个优点,尤其是在更真实、更灵活的环境中进行测试时。Testcontainers 基于官方 Confluent OSS 平台镜像运行 Kafka 实例。

GraalVM

        GraalVM是一个用于运行程序的平台,支持各种编程语言和技术。除其他外,它还允许将 Java 应用程序编译为静态链接的可执行文件(本机二进制文件)。这些本机可执行文件运行速度更快,需要更少的内存,并且不需要安装 JVM。

测试场景

        为了说明编写测试的方法,我准备了与一个简单的测试场景相对应的代码示例:

  • 向主题 topic1 发送消息 value1

  • 阅读主题 topic1 中的消息。

  • 验证该值是否等于 value1

示例可以在项目存储库中找到:

  • 使用 EmbeddedKafka 的测试位于 example-spring-embedded-kafka 模块中。

  • 使用 Testcontainers 的测试位于 example-testcontainers 模块中。

存储库结构有助于比较模块,以评估使用每种方法时代码结构和组合的差异。

将 EmbeddedKafka 包装在容器中

        第一个任务是在单独的容器中实现 EmbeddedKafka 的启动。为此,我采取了以下简单步骤:

  • 使用 Spring Initializr 创建了标准的 Spring Boot 应用程序。

  • 在应用程序中,我设置了具有必要参数的类实例的启动。org.springframework.kafka.test.EmbeddedKafkaZKBroker

  • 描述了 Dockerfile 并构建了映像

以上所有操作都反映在项目仓库中 emk-application 模块的代码中。

在容器中启动 EmbeddedKafka

        Testcontainers 文档提供了使用以下类启动 Kafka 容器的指南:KafkaContainer

KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.1"))

        但是,这个类不适合我的需求,因为它旨在与 confluentinc/cp-kafka 兼容映像一起使用。尽管如此,检查它是有益的,因为它揭示了围绕参数处理的有趣逻辑:KAFKA_ADVERTISED_LISTENERS

  1. 在容器开始时,执行 / 指令的替换。ENTRYPOINTCOMMAND

  2. 启动后,参数将与启动 Kafka 的说明一起传递到容器。KAFKA_ADVERTISED_LISTENERS

此过程在附图中进行了详细说明。

ed6d136737e5f90e6a4667d211e06ad6.png

    为什么有必要这样做?在运行过程中,客户端可以连接到任何 Kafka 节点以获取执行读/写操作的地址,即使 Kafka 由单个节点表示。外部用户需要外部地址,内部用户也需要内部地址。通过指定 ,我们向代理提供有关其外部地址的信息,然后代理将其传达给客户端。客户端相对于代理而言是外部的,因为代理在容器中运行。KAFKA_ADVERTISED_LISTENERS

我在一个新类中实现了上面描述的逻辑:EmbeddedKafkaContainer.java。

为 EmbeddedKafka 创建本机映像

        为 GraalVM 启动新的 Spring Boot 项目的最简单方法是访问站点 start.spring.io,添加“GraalVM Native Support”依赖项,然后生成项目。该项目附带一个 HELP.md 文件,它提供了有用的入门提示。

元数据收集

        用于构建本机映像的工具依赖于在应用程序代码执行期间可用的静态分析。但是,这种分析并不总是能够完全预测 Java 本机接口 (JNI)、Java 反射、动态代理对象等的所有用例。因此,需要以元数据的形式向原生映像构建工具显式指定动态函数的这些用例。提供此类元数据的一种方法是通过放置在项目目录 META-INF/native-image/<group.id>/<artifact.id> 中的 JSON 文件。

        GraalVM 提供了一个跟踪代理,用于方便地收集元数据和准备配置文件。此代理跟踪应用程序在标准 Java VM 上执行期间动态函数使用的所有实例。

我的方法如下:

  • 我在 JVM 下启动了一个带有嵌入式 Kafka 的 Spring 应用程序实例,并带有跟踪代理。

  • 我从我的一个项目中运行了大量测试,使用已启动的应用程序作为主要的 Kafka 代理。

在此过程中生成的文件被放置在项目目录 META-INF/native-image 中。

启动和使用

为了演示结果,我准备了以下工件:

  • 类为:pw.avvero:emk-testcontainers:1.0.1 的库EmbeddedKafkaContainer

  • Docker 镜像:(JVM) 和 (native, platform=linux/arm64)avvero/emkavvero/emk-native

  • 可以在 example-embedded-kafka-container 模块中找到与测试场景相对应的示例用法。

KafkaContainerConfiguration 的配置如下:

@TestConfiguration(proxyBeanMethods = false)
public class KafkaContainerConfiguration {@Bean@RestartScope@ServiceConnectionEmbeddedKafkaContainer kafkaContainer() {return new EmbeddedKafkaContainer("avvero/emk-native:1.0.0");}
}

        为了评估内存利用率,我从我的一个项目中运行了大约 7 分钟的测试。根据 docker stats 的观察,我注意到内存消耗的以下趋势:

confluentinc/cp-kafka:7.3.31.331GiB
AVVERO/EMK677.3米B
avvero/emk-native126.4米B

使用GCeasy通过GC日志进行内存分析(Young + Old + Meta空间),结果如下:

confluentinc/cp-kafka:7.3.31.06 GB/866.92 MB(已分配/峰值)
AVVERO/EMK567.62 MB/241.74 MB(已分配/峰值)
avvero/emk-native20.00米 -> 15.50米?

        分析本机映像的 GC 日志是一项更复杂的任务,因为数据的格式和组成与“标准”GC 日志不同。不幸的是,我找不到适合此目的的分析工具,可以提供现成的分析。因此,下面是日志的片段,它有助于估计我例中内存利用率的一般顺序。

[497.519s] GC(11371) Collect on allocation
[497.520s] GC(11371)   Eden: 4.50M->0.00M
[497.520s] GC(11371)   Survivor: 0.00M->0.00M
[497.520s] GC(11371)   Old: 15.50M->15.50M
[497.520s] GC(11371)   Free: 3.50M->8.00M
[497.520s] GC(11371) Incremental GC (Collect on allocation) 20.00M->15.50M 0.896ms

GC 日志文件附加到性能测试模块。

关于启动时间,我使用 JMH 进行了一系列性能测试,以评估不同 Kafka 容器配置的启动时间和操作准备情况:

  • testContainersKafkaStartAndReady- 使用 confluentinc/cp-kafka 测试容器:7.3.3

  • emkJvmKafkaStartAndReady - avvero/emk (JVM)

  • emkNativeKafkaStartAndReady - avvero/emk-native(原生,platform=linux/arm64)

        测试的重点是验证启动和准备情况。仅仅启动一个 Kafka 容器并不总是意味着它已准备好运行。就绪情况检查模拟了一个真实场景,在这个场景中,Kafka 不仅已启动,而且还已完全准备好运行。这样可以更全面地了解 Kafka 在各种容器化环境中完全运行所需的时间。

性能测试结果如下:

Benchmark                                                 Mode  Cnt  Score   Error  Units
TestContainersBenchmark.testContainersKafkaStartAndReady    ss   10  3,091 ± 0,354   s/op
TestContainersBenchmark.emkJvmKafkaStartAndReady            ss   10  2,659 ± 0,708   s/op
TestContainersBenchmark.emkNativeKafkaStartAndReady         ss   10  0,521 ± 0,055   s/op

        avvero/emk-native:1.0.0 容器表现出更高的性能,平均启动和就绪检查时间仅为 0.521 秒,偏差为 ±0,055

        在集成测试中使用 EmbeddedKafka 和 GraalVM 的本机映像可以加快测试启动时间并减少内存消耗,与传统方法(例如在 Testcontainers 中使用 confluentinc/cp-kafka)相比,它是一种有效的解决方案。

        GraalVM 的使用为旨在提高集成测试性能和效率的开发人员开辟了新的机会。这种方法可以针对其他类似的任务和技术进行调整和扩展,这突显了其在软件开发领域的多功能性和潜力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/379039.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VRRP虚拟路由冗余技术

VRRP虚拟路由冗余技术&#xff1a;是一种路由容错协议&#xff0c;用于在网络中提供路由器的冗余备份。它通过将多个路由器虚拟成一个虚拟路由器并且多个路由器之间共享一个虚拟IP地址来实现冗余和高可用性。当承担转发业务的主路由器出现故障时&#xff0c;其他备份路由器可以…

uniapp 微信默认地图选点功能实现

效果图 配置项 微信公众平台-小程序配置 uniapp配置 上代码 <template><view class"content"><button click"toMap">请选择位置</button></view> </template><script setup lang"ts">function toMa…

C# 各版本语法新功能汇总

C# 8.0 以后 官网 C# 7.3 》》in C# 7.2 》》 命名参数、具名参数 》》》 条件 ref 表达式 C# 7.1 》》 default 运算符 default 在C#7.1中得到了改进&#xff0c;不再需要default&#xff08;T&#xff09;了 //变量赋值C#7.0 var s "字符串"; s default(s…

使用llama.cpp量化模型

文章目录 概要整体实验流程技术细节小结 概要 大模型量化是指在保持模型性能尽可能不变的情况下&#xff0c;通过减少模型参数的位数来降低模型的计算和存储成本。本次实验环境为魔搭社区提供的免费GPU环境&#xff08;24G&#xff09;&#xff0c;使用Llama.cpp进行4bit量化可…

前端书籍翻页效果

目录 前端书籍翻页效果前言代码示例创建模板页面css样式编写js代码 结论 前端书籍翻页效果 前端实现翻书效果&#xff0c;附带vue源码 源码下载地址 前言 实际业务开发中&#xff0c;有时候会遇到需要在前端页面内实现翻书效果的需求&#xff0c;本篇文章就为大家介绍如何使…

N Puzzle (数字推盘游戏)

N Puzzle [数字推盘游戏] 1. 15 Puzzle2. N PuzzleReferences puzzle /ˈpʌzl/&#xff1a;n. 谜&#xff0c;智力游戏&#xff0c;疑问&#xff0c;不解之谜&#xff0c;令人费解的事 vt. 迷惑&#xff0c;使困惑1. 15 Puzzle https://en.wikipedia.org/wiki/15_puzzle The…

C#开发:Git的安装和使用

一、安装git 二、如何克隆代码&#xff1f; 1.找到某个本地目录&#xff0c;右键-gitbash 2. 输入以下命令&#xff08;红色是地址&#xff0c;在gitlab获取或联系管理员获取&#xff0c;下图为复制地址的方式&#xff09;&#xff1a; git clone http://xxxxxxxxx.git 输入帐…

MySQL双主双从实现方式

双主双从&#xff08;MM-SS&#xff09; 前言 避免单一主服务器宕机&#xff0c;集群写入能力缺失 从 1 复制 主1 &#xff0c;从 2 复制 主 2 主 1 复制 主 2&#xff0c;主 2 复制主 1 也就是 主 1 和主 2 互为主从。主1主2互为主从&#xff0c; 是为了以下情景&#xff0c…

C#字符串基本操作

1、代码 //1、创建字符串&#xff08;获取长度&#xff09;string str "Hello, World!";Console.WriteLine($"string:{str},length:{str.Length}");//2、字符串连接string str1 "Hello, ";string str2 "World!";Console.WriteLine…

datahub安装部署

作者&#xff1a;恩慈 背景&#xff1a;由于某客户需要建立sparksql的血缘关系&#xff0c;于是提出了datahub&#xff0c;由于网上关于datahub资料较少&#xff0c;因此这里做以记录。 datahub作为一个元数据管理平台&#xff0c;可以对数据资产进行有效的组织&#xff0c;还…

HarmonyOS 开发者联盟高级认证最新题库

本篇文章包含 Next 版本更新后高级认证题库中95%的题目。 答案正确率 50-60%&#xff0c;答案仅做参考。 请在考试前重点看一遍题目&#xff0c;勿要盲目抄答案。 欢迎在评论留言正确答案和未整理的题目。 1、下面关于方舟字节码格式PREF_IMM16_v8_v8描述正确的是 16位前缀操作…

中间件的理解

内容来源于学习网站整理。【一看就会】什么是前端开发的中间件&#xff1f;_哔哩哔哩_bilibili 每日八股文~白话说mq&#xff0c;消息中间件_哔哩哔哩_bilibili 例如&#xff1a; 1&#xff09;两个人打电话&#xff0c;中间的通信网络就是中间件。 2&#xff09;菜鸟驿站&…

Java.Net.UnknownHostException:揭开网络迷雾,解锁异常处理秘籍

在Java编程的浩瀚宇宙中&#xff0c;java.net.UnknownHostException犹如一朵不时飘过的乌云&#xff0c;让开发者在追求网络畅通无阻的道路上遭遇小挫。但别担心&#xff0c;今天我们就来一场说走就走的探险&#xff0c;揭秘这个异常的真面目&#xff0c;并手把手教你几招应对之…

巧用通义灵码助力护网面试

前言 前几年护网还算是一个比较敏感的话题&#xff0c;但是随着近段时间的常态化开始&#xff0c;护网行动也是逐渐走进了大众的视野&#xff0c;成为了社会各界共同关注的安全盛事。本篇也是受通义灵码备战求职季活动的启发&#xff0c;结合近期要开始的护网行动&#xff0c…

每日一题,力扣leetcode Hot100之128. 最长连续序列

题目理解&#xff1a; 从示例1可以看出简单的连续数字就算&#xff0c;从示例2可以看出当有重复数字时&#xff0c;是不算长度的 解法一&#xff1a; 第一个想到的解法&#xff0c;就是对nums排序&#xff0c;然后双层循环遍历进行判断&#xff0c;当前一个和后一个相减等于…

Yolov8网络结构学习

详解YOLOv8网络结构/环境搭建/数据集获取/训练/推理/验证/导出/部署 深入解析YOLOv8&#xff1a;网络结构与推理过程 YOLO? You Know! --YOLOV8详解 一&#xff1a;yolov8总体结构 1.Backbone:它采用了一系列卷积和 反卷积层只来提取特征&#xff0c;同时也使用了残差连接和…

广联达Linkworks ArchiveWebService XML实体注入漏洞复现

0x01 产品简介 广联达 LinkWorks(也称为 GlinkLink 或 GTP-LinkWorks)是广联达公司(Glodon)开发的一种BIM(建筑信息模型)协同平台。广联达是中国领先的数字建造技术提供商之一,专注于为建筑、工程和建筑设计行业提供数字化解决方案。 0x02 漏洞概述 广联达 LinkWorks…

小程序图片下载保存方法,图片源文件保存!

引言 现在很多时候我们在观看到小程序中的图片的时候&#xff0c;想保存图片的原文件格式的话&#xff0c;很多小程序是禁止保存的&#xff0c;即使是让保存的话&#xff0c;很多小程序也会限制不让保存原文件&#xff0c;只让保存一些分辨率很低的&#xff0c;非常模糊的图片…

【.NET全栈】ASP.NET开发web应用——ASP.NET中的样式、主题和母版页

文章目录 前言一、在ASP.NET中应用CSS样式1、创建CSS样式&#xff08;1&#xff09;内联样式&#xff08;2&#xff09;内部样式表&#xff08;3&#xff09;外部样式表 2、应用CSS样式&#xff08;1&#xff09;菜鸟教程-简单例子&#xff08;2&#xff09;菜鸟教程-用户界面&…

详解:adobe国际认证有多少种

Adobe国际认证&#xff0c;作为全球公认的数字媒体和创意设计技能认证&#xff0c;涵盖了多个专业领域和软件应用。这一认证体系为专业人士提供了展示自己技能水平的平台&#xff0c;并帮助他们在职场中脱颖而出。那么&#xff0c;Adobe国际认证到底有多少种呢&#xff1f; Ado…