Debezium系列之:基于内容的路由
一、基于内容路由的概念
默认情况下,Debezium 将从表中读取的所有更改事件流式传输到单个静态主题。但是,在某些情况下,可能希望根据事件内容将所选事件重新路由到其他主题。基于内容的路由消息传递模式中描述了基于内容路由消息的过程。要在 Debezium 中应用此模式,可以使用基于内容的路由单消息转换 (SMT) 来编写针对每个事件评估的表达式。
根据评估事件的方式,SMT 将事件消息路由到原始目标主题,或将其重新路由到在表达式中指定的主题。
注意:
- 基于内容的路由 SMT 正在积极开发中。发出的消息的结构或其他细节可能会随着开发的进行而改变。
虽然可以使用 Java 创建自定义 SMT 来编码路由逻辑,但使用自定义编码的 SMT 有其缺点。例如:
- 有必要预先编译转换并将其部署到 Kafka Connect。
- 每次更改都需要重新编译和重新部署代码,导致操作不灵活。
基于内容的路由 SMT 支持与 JSR 223(Java™ 平台脚本)集成的脚本语言。
Debezium 不附带任何 JSR 223 API 的实现。要在 Debezium 中使用表达式语言,必须下载该语言的 JSR 223 脚本引擎实现。例如,对于 Groovy 3,您可以从 https://groovy-lang.org/ 下载其 JSR 223 实现。GraalVM JavaScript 的 JSR223 实现可在 https://github.com/graalvm/graaljs 获得。获得脚本引擎文件后,将它们与语言实现使用的任何其他 JAR 文件一起添加到 Debezium 连接器插件目录中。
二、部署
- 出于安全原因,基于内容的路由 SMT 不包含在 Debezium 连接器压缩包中。
- 相反,它在单独的工件 debezium-scripting-2.2.1.Final.tar.gz 中提供。
要将基于内容的路由 SMT 与 Debezium 连接器插件一起使用,您必须将 SMT 构件显式添加到您的 Kafka Connect 环境中。重要提示:在路由 SMT 出现在 Kafka Connect 实例中之后,任何被允许向该实例添加连接器的用户都可以运行脚本表达式。为确保脚本表达式只能由授权用户运行,请确保在添加路由 SMT 之前保护 Kafka Connect 实例及其配置接口。
安装 Zookeeper、Kafka、Kafka Connect 和一个或多个 Debezium 连接器后,安装过滤器 SMT 的剩余任务是:
- 下载脚本 SMT 存档
- 将存档的内容提取到 Kafka Connect 环境的 Debezium 插件目录中。
- 获取 JSR-223 脚本引擎实现并将其内容添加到 Kafka Connect 环境的 Debezium 插件目录中。
- 重新启动 Kafka Connect 进程以获取新的 JAR 文件。
Groovy 语言需要类路径中的以下库:
- groovy
- groovy-json (optional)
- groovy-jsr223
JavaScript 语言在类路径中需要以下库:
- graalvm.js
- graalvm.js.scriptengine
三、示例:基本配置
要配置 Debezium 连接器以根据事件内容路由更改事件记录,可以在连接器的 Kafka Connect 配置中配置 ContentBasedRouter SMT。
配置基于内容的路由 SMT 需要指定定义过滤条件的正则表达式。在配置中,创建一个定义路由条件的正则表达式。该表达式定义了评估事件记录的模式。它还指定目标主题的名称,匹配模式的事件被路由到该目标主题。指定的模式可能会指定一种事件类型,例如表插入、更新或删除操作。还可以定义一个模式来匹配特定列或行中的值。
例如,要将所有更新 (u) 记录重新路由到更新主题,您可以将以下配置添加到您的连接器配置中:
...
transforms=route
transforms.route.type=io.debezium.transforms.ContentBasedRouter
transforms.route.language=jsr223.groovy
transforms.route.topic.expression=value.op == 'u' ? 'updates' : null
...
前面的示例指定使用 Groovy 表达式语言。
与模式不匹配的记录被路由到默认主题。
自定义配置
前面的示例显示了一个简单的 SMT 配置,该配置旨在仅处理包含操作字段的 DML 事件。连接器可能发出的其他类型的消息(心跳消息、墓碑消息或有关事务或架构更改的元数据消息)不包含此字段。为避免处理失败,您可以定义一个 SMT 谓词语句,选择性地将转换仅应用于特定事件。
四、在基于内容的路由表达式中使用的变量
Debezium 将某些变量绑定到 SMT 的评估上下文中。当创建表达式来指定控制路由目标的条件时,SMT 可以查找并解释这些变量的值以评估表达式中的条件。
下表列出了 Debezium 绑定到基于内容的路由 SMT 的评估上下文中的变量:
表 1. 基于内容的路由表达式变量
名称 | 描述 | 类型 |
---|---|---|
key | 消息的密钥。 | org.apache.kafka.connect.data.Struct |
value | 消息的值。 | org.apache.kafka.connect.data.Struct |
keySchema | 消息密钥的架构。 | org.apache.kafka.connect.data.Schema |
valueSchema | 消息密匙的结构。 | org.apache.kafka.connect.data.Schema |
topic | 目标主题的名称。 | String |
headers | 消息头的 Java 映射。关键字段是标题名称。 headers 变量公开以下属性:值(对象类型)模式(类型为 org.apache.kafka .connect .data .Schema) | java.util.Map<String, io.debezium.transforms.scripting.RecordHeader> |
表达式可以对其变量调用任意方法。表达式应解析为一个布尔值,该值确定 SMT 如何处理消息。当表达式中的路由条件计算结果为真时,将保留消息。当路由条件评估为 false 时,消息将被删除。
表达式不应导致任何副作用。也就是说,他们不应该修改他们传递的任何变量。
五、有选择地应用转换的选项
除了 Debezium 连接器在发生数据库更改时发出的更改事件消息外,连接器还会发出其他类型的消息,包括心跳消息以及关于架构更改和事务的元数据消息。由于这些其他消息的结构不同于 SMT 旨在处理的更改事件消息的结构,因此最好将连接器配置为有选择地应用 SMT,以便它仅处理预期的数据更改消息。可以使用以下方法之一将连接器配置为有选择地应用 SMT:
- 为转换配置 SMT 谓词。
- 使用 SMT 的 topic.regex 配置选项。
更多内容可以参考博主下面的技术博客:
六、语言细节
表达基于内容的路由条件的方式取决于使用的脚本语言。例如,如基本配置示例所示,当您使用 Groovy 作为表达式语言时,以下表达式将所有更新 (u) 记录重新路由到更新主题,同时将其他记录路由到默认主题:
value.op == 'u' ? 'updates' : null
其他语言使用不同的方法来表达相同的条件。
Debezium MongoDB 连接器将 after 和 patch 字段作为序列化的 JSON 文档而不是结构发出。要将 ContentBasedRouting SMT 与 MongoDB 连接器一起使用,必须首先将 JSON 中的数组字段展开到单独的文档中。
可以通过应用 MongoDB ExtractNewDocumentState SMT 来执行此操作。
还可以采用在表达式中使用 JSON 解析器的方法,为每个数组项生成单独的输出文档。
例如,如果使用 Groovy 作为表达式语言,请将 groovy-json 工件添加到类路径中,然后添加一个表达式,例如(new groovy.json.JsonSlurper()).parseText(value.after).last_name == ‘Kretchmar’。
Javascript
当使用 JavaScript 作为表达语言时,可以调用 Struct#get() 方法来指定基于内容的路由条件,如下例所示:
value.get('op') == 'u' ? 'updates' : null
Javascript with Graal.js
当使用带有 Graal.js 的 JavaScript 创建基于内容的路由条件时,使用的方法类似于使用 Groovy 的方法。例如:
value.op == 'u' ? 'updates' : null
七、配置选项
属性 | 默认值 | 描述 |
---|---|---|
topic.regex | 一个可选的正则表达式,用于评估事件的目标主题的名称以确定是否应用条件逻辑。如果目标主题的名称与 topic.regex 中的值匹配,则转换会在将事件传递给主题之前应用条件逻辑。如果主题名称与 topic.regex 中的值不匹配,则 SMT 将事件原封不动地传递给主题。 | |
language | 编写表达式所用的语言。必须以 jsr223. 开头,例如 jsr223.groovy 或 jsr223.graal.js。Debezium 仅支持通过 JSR 223 API(“Java™ 平台脚本”)进行引导。 | |
topic.expression | 要为每条消息计算的表达式。必须评估为 String 值,其中非 null 的结果将消息重新路由到新主题,而 null 值将消息路由到默认主题。 | |
null.handling.mode | keep | 指定转换如何处理空(逻辑删除)消息。您可以指定以下选项之一:保持:默认,传递消息。降低:完全删除消息。评价:将条件逻辑应用于消息。 |