您可能已经注意到,我们已经开始了Debezium 2.0的工作。开云体育官方注册网址之一计划中的变更对于2.0版本来说是切换到Java 11作为基准.虽然一些Java构建提供者仍然支持Java 8,但其他Java 8发行版已经达到了它们的生命周期/支持的终点。正如New Relic的调查所示,用户无论如何都在转向Java 11Java生态系统报告的状态指示。但这不仅仅是支持的问题:Java 11带来了各种性能改进,有用的工具,如JDK Flight Recorder,它在Java 11中是开源的,等等。因此,我们觉得是时候开始考虑使用最新的JDK作为Debezium的基准了,而新的主要版本自然是进行转换的里程碑。开云体育官方注册网址

从Debezium 2.0的第一个版本开始,开云体育官方注册网址2.0.0.Alpha1, 开云体育官方注册网址Debezium位将被编译为Java 11字节代码。因此,在下一个主要更新中,运行Debezium将需要Java 11。开云体育官方注册网址此外,如果您在项目中使用任何Debezium位作为库(使开云体育官方注册网址用Debezium嵌入式引擎),你必须改用java11。

但是等等,标题中的Java 11/17是什么意思?它只是为了吓唬你,还是我们真的要马上切换到Java 17 ?

<戏剧性暂停>

不,我们不想吓到你。实际上,我们正在计划切换到Java 17,但只针对测试套件。请注意,Java 11和17都是长期支持(LTS)版本。我们现在还不想为实际的Debezium构件移动Java 17,因为这对大量Debezium开云体育官方注册网址用户来说可能是一个问题;例如,前面提到的New Relic报告显示,大多数用户仍在使用Java 11,当然我们并不想将他们排除在外。然而,使用Java 17进行测试并不会以任何方式影响用户,并且允许我们在测试中使用一些最新的Java特性,例如:*文本块,例如简化了多行JSON或SQL字符串的使用,*记录,这可以提高我们测试中大量使用的流操作的可读性,*转换表达式,以及更多。

很甜蜜,对吧?

实现

用Maven为代码和测试设置不同的字节代码级别非常容易,你只需要设置以下属性:

< maven.compiler.release >11< / maven.compiler.release >< maven.compiler.testRelease >17< / maven.compiler.testRelease >

请注意,我们正在使用释放选择而不是遗产目标选项,这可以防止意外使用目标Java版本中不存在的Java api。参见Gunnar的博客文章ByteBuffer和可怕的NoSuchMethodError欲知详情。

在切换到Java 11之后,Maven Checkstyle插件ImpSort插件(一个负责正确导入排序的插件)开始失败。然而,将它们的版本升级到最新版本已经解决了所有问题。

这是比较容易的部分。最难的部分是Debezium开云体育官方注册网址Apache Cassandra连接器

Cassandra连接器测试

版本1.9, Cassandra连接器为Cassandra 3以及Cassandra 4提供支持。卡桑德拉4在Java 11中工作就像有魅力一样但是在Java 11上运行Cassandra 3是不可能的(或者至少需要一些破解)。该连接器的现有测试实现没有像我们在所有其他DB连接器的测试中那样在容器中运行Cassandra,而是以嵌入式模式运行Cassandra,即在与测试本身相同的JVM和进程中运行Cassandra。因此,如果要使用Java 11(或17)运行测试,Cassandra 3连接器模块的测试将失败。

显而易见的解决方案是在Java 8的容器中运行Cassandra。这听起来不错,但这种方法有一个陷阱。Cassandra连接器需要访问Cassandra日志文件,因为它从中获取CDC事件,因此测试需要访问容器中的Cassandra文件。类中的临时目录可以很容易地解决这个问题目标目录,将其作为卷挂载到运行Cassandra的容器中。在容器中运行的Cassandra以后可以使用这个挂载的卷来存储它的数据。

真正的问题开始于您尝试在测试之后进行清理。当Cassandra在容器中以专用用户名为卡珊德拉,它很可能不存在于测试机器上(或者使用不同的UID/GID),当它尝试删除带有Cassandra文件的临时目录时,清理会失败。这些文件是在装载到容器中的临时目录中创建的,而不是在Docker FS overlay中,因此它们出现在目标目录中。文件是由卡珊德拉用户(很可能与运行测试的用户不同),运行测试的用户没有足够的权限删除由创建的文件卡珊德拉用户。在一些包装器脚本中,试图在Cassandra退出时从Cassandra的容器中删除它们,结果发现非常麻烦,而且不太可靠。

最有希望的解决方案是使用相同的容器启动第二个容器卡珊德拉在第一个Cassandra容器已经停止后,用户可以访问挂载的卷并清理文件。

我们考虑了两种运行容器的选项:

我们在项目的其余部分使用了Fabric8插件,这建议在本例中也使用它,以便在整个项目中保持一致性。另一方面,使用测试容器将使测试对开发人员来说更加方便(毕竟他们实际使用测试!),因为它允许直接从IDE运行测试,而无需手动启动容器。

最后,这个决定是由这样一个事实驱动的:在Fabric8插件中运行一个清理容器是不可能的。Maven不允许在同一阶段执行不同的配置,因此不可能停止Cassandra容器post-integration-test阶段,同时在此阶段运行一个清理容器。测试容器允许在需要时以编程方式启动和停止容器,让我们直接在测试代码中定义图像,因此不需要任何额外的东西Dockerfile,而清理容器只是隐藏在测试本身中的实现细节。能够直接从IDE运行测试,而无需手动启动和停止使用数据库的容器,是这些功能之上的一个很好的好处。开云体育电动老虎机

使用Testcontainers时唯一棘手的事情是当我们试图使用Docker的删除日志文件时cmd命令时,Testcontainers随机失败,表示容器没有启动,尽管事实上所有Cassandra文件都被删除了。容器可能运行得太快,以至于在Testcontainers注意到它之前就完成了。最后,我们通过增加一个短睡眠并在容器中执行执行清理的附加命令。

使用Testcontainers的最终清理代码如下所示:

@AfterClass public static void tearDownClass()抛出IOException, InterruptedException {destroyTestKeyspace();cassandra.stop ();GenericContainer清理= new GenericContainer(new ImageFromDockerfile() .withDockerfileFromBuilder(builder - .>builder .from("eclipse-temurin:8-jre-focal") .volume("/var/lib/cassandra") .cmd("sleep", "10") //给TC一些时间来发现容器正在运行。.build())) . withfilesystembind (cassandraDir, CASSANDRA_SERVER_DIR, BindMode.READ_WRITE);cleanup.start ();清理。execInContainer("rm", "-rf", CASSANDRA_SERVER_DIR + "/data", CASSANDRA_SERVER_DIR + "/cdc_raw_directory", CASSANDRA_SERVER_DIR + "/commitlog", CASSANDRA_SERVER_DIR + "/hints", CASSANDRA_SERVER_DIR + "/saved_caches");cleanup.stop ();}

一旦我们用Cassandra测试解决了这个问题,我们就基本完成了,并准备在Debezium的主代码中使用Java 11,在我们的测试中使用Java 17。开云体育官方注册网址

开放的问题

我们需要更多的战斗测试,以确保在Java 11/17中一切都能正常工作。您在测试和错误报告方面的帮助在这里非常有价值,非常受欢迎。目前,我们意识到一个与Java更新相关的小问题尚未解决。有些ide无法区分maven.compiler.releasemaven.compiler.testRelease(或者我们不太清楚如何设置它)。例如,这个测试使用文本块在IDE中被标记为错误:

在IntelliJ Idea中使用文本块进行测试。

您可以手动将Java级别设置为17,但在这种情况下,您可能会无意中在非测试代码中使用Java > 11特性,而IDE不会告诉您(诚然,这不是一个太大的问题,因为下一个Maven构建,例如在CI上,将捕获该问题)。此外,Idea会在代码中的任何变化时重置代码级别pom.xml文件。你解决这个问题了吗?或者您使用的IDE不存在混合不同Java级别的问题?请在讨论中分享你的经验!

Vojtěch Juranek

Vojta是红帽公司的软件工程师。他住在捷克共和国。


关于Debe开云体育官方注册网址zium

开云体育官方注册网址Debezium是一个开源的分布式平台,它将现有数据库转换为事件流,因此应用程序几乎可以立即看到并响应数据库中提交的每一个行级更改。开云体育电动老虎机开云体育官方注册网址Debezium是建立在卡夫卡并提供卡夫卡连接监控特定数据库管理系统的兼容连接器。开云体育电动老虎机开云体育官方注册网址Debezium在Kafka日志中记录了数据更改的历史,所以你的应用程序可以在任何时候停止和重新启动,并且可以很容易地使用它没有运行时错过的所有事件,确保所有事件都被正确和完整地处理。开云体育官方注册网址Debezium是开源Apache许可证,版本2.0

参与

我们希望您觉得Debezium有趣开云体育官方注册网址且有用,并愿意尝试一下。在Twitter上关注我们@开云体育官方注册网址debezium在Zulip上和我们聊天,或加入我们的邮件列表与社区对话。所有的代码都是开源的GitHub上,因此在本地构建代码并帮助我们改进现有连接器并添加更多连接器。如果您发现了问题或对我们如何改进Debezium有想法,请告诉我们开云体育官方注册网址记录问题

Baidu
map