架构师成长之路:Kafka连接器深度解读之错误处理和死信队列

Kafka连接器是Kafka的一部分,是在Kafka和其它技术之间构建流式管道的一个强有力的框架。它可用于将数据从多个地方(包括数据库、消息队列和文本文件)流式注入到Kafka,以及从Kafka将数据流式传输到目标端(如文档存储、NoSQL、数据库、对象存储等)中。

现实世界并不完美,出错是难免的,因此在出错时Kafka的管道能尽可能优雅地处理是最好的。一个常见的场景是获取与特定序列化格式不匹配的主题的消息(比如预期为Avro时实际为JSON,反之亦然)。自从Kafka 2.0版本发布以来,Kafka连接器包含了错误处理选项,即将消息路由到死信队列的功能,这是构建数据管道的常用技术。

在本文中将介绍几种处理问题的常见模式,并说明如何实现。

失败后立即停止

有时可能希望在发生错误时立即停止处理,可能遇到质量差的数据是由于上游的原因导致的,必须由上游来解决,继续尝试处理其它的消息已经没有意义。

架构师成长之路:Kafka连接器深度解读之错误处理和死信队列

 

这是Kafka连接器的默认行为,也可以使用下面的配置项显式地指定:

errors.tolerance = none

在本示例中,该连接器配置为从主题中读取JSON格式数据,然后将其写入纯文本文件。注意这里为了演示使用的是FileStreamSinkConnector连接器,不建议在生产中使用。

curl -X POST http://localhost:8083/connectors -H "Content-Type: application/json" -d '{
 "name": "file_sink_01", "config": { "connector.class": "org.apache.kafka.connect.file.FileStreamSinkConnector", "topics":"test_topic_json", "value.converter":"org.apache.kafka.connect.json.JsonConverter", "value.converter.schemas.enable": false, "key.converter":"org.apache.kafka.connect.json.JsonConverter", "key.converter.schemas.enable": false, "file":"/data/file_sink_01.txt" } }'

主题中的某些JSON格式消息是无效的,连接器会立即终止,进入以下的FAILED状态:

$ curl -s "http://localhost:8083/connectors/file_sink_01/status"| \
 jq -c -M '[.name,.tasks[].state]'["file_sink_01","FAILED"]

查看Kafka连接器工作节点的日志,可以看到错误已经记录并且任务已经终止:

org.apache.kafka.connect.errors.ConnectException: Tolerance exceeded in error handler
 at org.apache.kafka.connect.runtime.errors.RetryWithToleranceOperator.execAndHandleError(RetryWithToleranceOperator.java:178)…Caused by: org.apache.kafka.connect.errors.DataException: Converting byte[] to Kafka Connect data failed due to serialization error: at org.apache.kafka.connect.json.JsonConverter.toConnectData(JsonConverter.java:334)…Caused by: org.apache.kafka.common.errors.SerializationException: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('b' (code 98)): was expecting double-quote to start field name at [Source: (byte[])"{brokenjson-:"bar 1"}"; line: 1, column: 3]

要修复管道,需要解决源主题上的消息问题。除非事先指定,Kafka连接器是不会简单地“跳过”无效消息的。如果是配置错误(例如指定了错误的序列化转换器),那最好了,改正之后重新启动连接器即可。不过如果确实是该主题的无效消息,那么需要找到一种方式,即不要阻止所有其它有效消息的处理。

静默忽略无效的消息

如果只是希望处理一直持续下去:

errors.tolerance = all

架构师成长之路:Kafka连接器深度解读之错误处理和死信队列

 

在实际中大概如下:

curl -X POST http://localhost:8083/connectors -H "Content-Type: application/json" -d '{
 "name": "file_sink_05", "config": { "connector.class": "org.apache.kafka.connect.file.FileStreamSinkConnector", "topics":"test_topic_json", "value.converter":"org.apache.kafka.connect.json.JsonConverter", "value.converter.schemas.enable": false, "key.converter":"org.apache.kafka.connect.json.JsonConverter", "key.converter.schemas.enable": false, "file":"/data/file_sink_05.txt", "errors.tolerance": "all" } }'

启动连接器之后(还是原来的源主题,其中既有有效的,也有无效的消息),就可以持续地运行:

$ curl -s "http://localhost:8083/connectors/file_sink_05/status"| \
 jq -c -M '[.name,.tasks[].state]'["file_sink_05","RUNNING"]

这时即使连接器读取的源主题上有无效的消息,也不会有错误写入Kafka连接器工作节点的输出,而有效的消息会按照预期写入输出文件:

$ head data/file_sink_05.txt
{foo=bar 1}{foo=bar 2}{foo=bar 3}…

是否可以感知数据的丢失?

配置了errors.tolerance = all之后,Kafka连接器就会忽略掉无效的消息,并且默认也不会记录被丢弃的消息。如果确认配置errors.tolerance = all,那么就需要仔细考虑是否以及如何知道实际上发生的消息丢失。在实践中这意味着基于可用指标的监控/报警ÿ

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值