Перейти к содержимому
Последнее обновление

Doris Kafka Connector

Kafka Connect — масштабируемый и надёжный инструмент интеграции данных для их передачи между Apache Kafka и другими системами. Сообщество Doris предоставляет плагин doris-kafka-connector, который записывает данные из топиков Kafka в Doris.

Сценарии использования​

Для непрерывной записи данных из Kafka в Doris выберите конфигурацию, соответствующую источнику данных и среде выполнения:

Сценарий использованияВозможностьРаздел документации
Локальная проверка или тестирование при разработкеЗапустите Kafka Connect в режиме Standalone и создайте Doris Sink Connector с помощью локального файла конфигурацииРазвёртывание в режиме Standalone
Развёртывание в рабочей среде или кластереЗапустите Kafka Connect в режиме Distributed и управляйте коннекторами через REST APIРазвёртывание в режиме Distributed
Синхронизация обычных данных JSONИспользуйте JsonConverter или StringConverter для чтения топика Kafka и записи в таблицу DorisСинхронизация обычных данных JSON
Синхронизация данных CDC, полученных с помощью DebeziumЗадайте converter.mode=debezium_ingestion и при необходимости включите синхронизацию удаленийСинхронизация данных, полученных с помощью Debezium
Синхронизация данных, сериализованных в Avro или ProtobufИспользуйте Confluent Avro Converter или Protobuf Converter и настройте адрес Schema RegistryСинхронизация данных, сериализованных в Avro, Синхронизация данных, сериализованных в Protobuf
Преобразование сообщений Kafka перед записьюИспользуйте Kafka Connect SMT для добавления полей или преобразования форматов времени в сообщенияхПреобразование данных с помощью Kafka Connect SMT
Доступ к кластеру Kafka с аутентификацией SSLНастройте параметры SSL в Kafka Connect Worker и во встроенном потребителеДоступ к кластеру Kafka с аутентификацией SSL
Сохранение записей, которые не удалось преобразоватьНастройте очередь недоставленных сообщений Kafka ConnectНастройка очереди недоставленных сообщений

Сведения о версиях​

Версия коннектораВерсия KafkaВерсия DorisВерсия Java
1.0.02.4+2.0+8
1.1.02.4+2.0+8
24.0.02.4+2.0+8
25.0.02.4+2.0+8
26.0.02.4+2.0+8
26.1.02.4+2.0+8

Подготовка Doris Kafka Connector​

Для использования Doris Kafka Connector можно скачать JAR-пакет или добавить зависимость Maven.

Скачивание JAR-пакета​

Скачайте JAR-пакет doris-kafka-connector со страницы загрузки Doris. При развёртывании Kafka Connect поместите JAR-пакет в каталог $KAFKA_HOME/plugins.

Использование зависимости Maven​

В проекте Maven добавьте следующую зависимость:

<dependency>
<groupId>org.apache.doris</groupId>
<artifactId>doris-kafka-connector</artifactId>
<version>26.1.0</version>
</dependency>

Развёртывание в режиме Standalone​

Режим Standalone подходит для локальной проверки или тестирования при разработке. Как правило, его не рекомендуется использовать в рабочих средах.

1. Подготовьте каталог плагинов​

Создайте каталог plugins в $KAFKA_HOME и поместите в него скачанный JAR-пакет doris-kafka-connector.

2. Настройте Kafka Connect Worker​

Отредактируйте $KAFKA_HOME/config/connect-standalone.properties:

# Modify the broker address
bootstrap.servers=127.0.0.1:9092

# Set this to the plugins directory you created
# Note: use Kafka's direct path here. For example: plugin.path=/opt/kafka/plugins
plugin.path=$KAFKA_HOME/plugins

# It is recommended to increase Kafka's max.poll.interval.ms to more than 30 minutes (default is 5 minutes)
# This avoids consumers being kicked out of the consumer group due to Stream Load consumption timeouts
max.poll.interval.ms=1800000
consumer.max.poll.interval.ms=1800000

3. Настройте Doris Sink Connector​

Создайте doris-connector-sink.properties в каталоге $KAFKA_HOME/config:

name=test-doris-sink
connector.class=org.apache.doris.kafka.connector.DorisSinkConnector
topics=topic_test
doris.topic2table.map=topic_test:test_kafka_tbl
doris.urls=10.10.10.1
doris.http.port=8030
doris.query.port=9030
doris.user=root
doris.password=
doris.database=test_db
buffer.count.records=10000
buffer.flush.time=120
buffer.size.bytes=5000000
enable.combine.flush=true
key.converter=org.apache.kafka.connect.storage.StringConverter
value.converter=org.apache.kafka.connect.json.JsonConverter
value.converter.schemas.enable=false

4. Запустите режим Standalone​

$KAFKA_HOME/bin/connect-standalone.sh -daemon $KAFKA_HOME/config/connect-standalone.properties $KAFKA_HOME/config/doris-connector-sink.properties

Развёртывание в режиме Distributed​

Режим Distributed подходит для многоузловых кластеров Kafka Connect. В этом режиме сначала запускают Kafka Connect Worker, а затем создают коннекторы и управляют ими через REST API.

1. Подготовьте каталог плагинов​

Создайте каталог plugins в $KAFKA_HOME и поместите в него скачанный JAR-пакет doris-kafka-connector.

2. Настройте Kafka Connect Worker​

Отредактируйте $KAFKA_HOME/config/connect-distributed.properties:

# Modify the broker address
bootstrap.servers=127.0.0.1:9092

# Modify group.id; it must be the same across the same cluster
group.id=connect-cluster

# Set this to the plugins directory you created
# Note: use Kafka's direct path here. For example: plugin.path=/opt/kafka/plugins
plugin.path=$KAFKA_HOME/plugins

# It is recommended to increase Kafka's max.poll.interval.ms to more than 30 minutes (default is 5 minutes)
# This avoids consumers being kicked out of the consumer group due to Stream Load consumption timeouts
max.poll.interval.ms=1800000
consumer.max.poll.interval.ms=1800000

3. Запустите режим Distributed​

$KAFKA_HOME/bin/connect-distributed.sh -daemon $KAFKA_HOME/config/connect-distributed.properties
примечание

При первом запуске Kafka Connect создаёт в кластере Kafka три топика: config.storage.topic, offset.storage.topic и status.storage.topic. Они используются для хранения общих конфигураций коннекторов, данных о смещениях и обновлений состояния. Подробнее см. в разделе Начало работы с Kafka Connect.

4. Создайте коннектор​

curl -i http://127.0.0.1:8083/connectors -H "Content-Type: application/json" -X POST -d '{
"name":"test-doris-sink-cluster",
"config":{
"connector.class":"org.apache.doris.kafka.connector.DorisSinkConnector",
"topics":"topic_test",
"doris.topic2table.map":"topic_test:test_kafka_tbl",
"doris.urls":"10.10.10.1",
"doris.user":"root",
"doris.password":"",
"doris.http.port":"8030",
"doris.query.port":"9030",
"doris.database":"test_db",
"enable.combine.flush":"true",
"buffer.count.records":"10000",
"buffer.flush.time":"120",
"buffer.size.bytes":"5000000",
"key.converter":"org.apache.kafka.connect.storage.StringConverter",
"value.converter":"org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable":"false"
}
}'

5. Управляйте коннектором​

Через REST API Kafka Connect можно просматривать состояние коннектора, приостанавливать, возобновлять, удалять или перезапускать его. Подробнее об API см. в разделе REST-интерфейс Connect.

# View Connector status
curl -i http://127.0.0.1:8083/connectors/test-doris-sink-cluster/status -X GET

# Delete the current Connector
curl -i http://127.0.0.1:8083/connectors/test-doris-sink-cluster -X DELETE

# Pause the current Connector
curl -i http://127.0.0.1:8083/connectors/test-doris-sink-cluster/pause -X PUT

# Resume the current Connector
curl -i http://127.0.0.1:8083/connectors/test-doris-sink-cluster/resume -X PUT

# Restart a task within the Connector
curl -i http://127.0.0.1:8083/connectors/test-doris-sink-cluster/tasks/0/restart -X POST

Дополнительные настройки для рабочей среды​

Доступ к кластеру Kafka с аутентификацией SSL​

Для доступа к кластеру Kafka с аутентификацией SSL через Kafka Connect необходимо предоставить файл сертификата для проверки открытого ключа брокера Kafka, например client.truststore.jks. Добавьте следующую конфигурацию в connect-distributed.properties:

# Connect worker
security.protocol=SSL
ssl.truststore.location=/var/ssl/private/client.truststore.jks
ssl.truststore.password=test1234

# Embedded consumer for sink connectors
consumer.security.protocol=SSL
consumer.ssl.truststore.location=/var/ssl/private/client.truststore.jks
consumer.ssl.truststore.password=test1234

Подробнее о подключении к кластеру Kafka с аутентификацией SSL через Kafka Connect см. в разделе Настройка Kafka Connect.

Настройка очереди недоставленных сообщений​

По умолчанию любая ошибка при преобразовании приводит к сбою коннектора. Следующая конфигурация позволяет продолжать работу при таких ошибках и записывать сведения о каждой ошибке и неудачной операции вместе с проблемной записью в очередь недоставленных сообщений:

errors.tolerance=all
errors.deadletterqueue.topic.name=test_error_topic
errors.deadletterqueue.context.headers.enable=true
errors.deadletterqueue.topic.replication.factor=1

Параметры конфигурации​

Следующие параметры используются для создания Doris Sink Connector. Другие общие параметры Kafka Connect Sink см. в разделе connect_configuring.

КлючДопустимые значенияЗначение по умолчаниюОбязательныйОписание
name--ДаИмя приложения Connect. Должно быть уникальным в среде Kafka Connect.
connector.class--Даorg.apache.doris.kafka.connector.DorisSinkConnector.
topics--ДаСписок топиков, на которые оформлена подписка. Разделяйте несколько топиков запятыми, например topic1,topic2.
doris.urls--ДаАдрес подключения к Doris FE. Разделяйте несколько адресов запятыми, например 10.20.30.1,10.20.30.2,10.20.30.3.
doris.http.port--ДаПорт протокола HTTP в Doris.
doris.query.port--ДаПорт протокола MySQL в Doris.
doris.user--ДаИмя пользователя Doris.
doris.password--ДаПароль Doris.
doris.database--ДаБаза данных для записи. При записи в несколько баз данных параметр можно оставить пустым; в этом случае имя базы данных необходимо указать в topic2table.map.
doris.enable.tlstrue,
false
falseНетВключать ли TLS для подключений к Doris по HTTP и MySQL.
doris.tls.ca-certificate-path-Пустая строкаНетЛокальный путь на Worker к цепочке сертификатов CA в формате PEM. Если значение пустое, коннектор не загружает пользовательский CA и использует стандартное хранилище доверенных сертификатов соответствующего клиента.
doris.tls.skip-hostname-verificationtrue,
false
falseНетПропускать ли проверку имени хоста, сохраняя проверку CA.
doris.tls.excluded-protocolshttp,
mysql
Пустая строкаНетПротоколы Doris, которые не используют TLS, через запятую.
doris.topic2table.map--ДаСопоставление топиков с таблицами, например topic1:tb1,topic2:tb2. Если значение пустое, по умолчанию в качестве имени целевой таблицы используется имя топика. Формат для нескольких баз данных: topic1:db1.tbl1,topic2:db2.tbl2.
load.modelstream_load,
tvf
stream_loadНетРежим записи в Doris. Установите для этого параметра значение tvf, чтобы выполнять запись через S3 TVF.
buffer.count.records-50000НетКоличество записей, записываемых за одну операцию Stream Load.
buffer.flush.time-120НетИнтервал сброса буфера в секундах. Значение по умолчанию — 120 секунд.
buffer.size.bytes-104857600(100MB)НетОбъём данных, записываемых за одну операцию Stream Load.
enable.combine.flushtrue,
false
falseНетОбъединять ли данные из всех разделов в одну операцию записи. Значение по умолчанию — false. При включении гарантируется только семантика at_least_once.
jmx-trueНетПолучать ли внутренние метрики мониторинга коннектора через JMX. См. Doris-Connector-JMX.
label.prefix-${name}НетПрефикс метки Stream Load при загрузке данных. По умолчанию используется имя приложения коннектора.
auto.redirect-trueНетПеренаправлять ли запросы Stream Load. При включении Stream Load перенаправляется через FE на BE, которому необходимо записать данные, а сведения о BE больше не отображаются.
sink.properties.*-'sink.properties.format':'json',
'sink.properties.read_json_by_line':'true'
НетПараметры загрузки Stream Load. Например, задайте разделитель столбцов с помощью 'sink.properties.column_separator':','. Подробное описание параметров см. в руководстве по Stream Load.

Для включения Group Commit, например в режиме sync_mode: "sink.properties.group_commit":"sync_mode". Group Commit поддерживает три режима: off_mode, sync_mode и async_mode. Подробнее об использовании см. в разделе Group Commit.

Для включения частичного обновления столбцов, например обновления столбца col2: "sink.properties.partial_columns":"true", "sink.properties.columns":"col2".
sink.s3.endpoint--Только в режиме записи TVFАбсолютный адрес конечной точки HTTP или HTTPS объектного хранилища, совместимого с S3.
sink.s3.region--Только в режиме записи TVFРегион объектного хранилища.
sink.s3.bucket--Только в режиме записи TVFБакет для промежуточного хранения данных.
sink.s3.prefix--Только в режиме записи TVFПрефикс ключей объектов для промежуточного хранения данных.
sink.s3.access-key--Только в режиме записи TVFКлюч доступа к объектному хранилищу.
sink.s3.secret-key--Только в режиме записи TVFСекретный ключ объектного хранилища.
sink.s3.path-style-accesstrue,
false
falseНетИспользовать ли адресацию path-style для доступа к объектному хранилищу в режиме записи TVF.
delivery.guaranteeat_least_once,
exactly_once
at_least_onceНетГарантия согласованности данных при чтении из Kafka и загрузке в Doris. Поддерживаются at_least_once и exactly_once. Значение по умолчанию — at_least_once. Для гарантии exactly_once необходимо обновить Doris до версии 2.1.0 или более поздней.
converter.modenormal,
debezium_ingestion
normalНетРежим преобразования типов входных данных при чтении коннектором данных из Kafka. normal означает обычное чтение данных Kafka без специального преобразования типов. debezium_ingestion означает, что требуется специальное преобразование типов, если входные данные Kafka получены с помощью инструментов CDC (Change Data Capture), таких как Debezium.
debezium.schema.evolutionnone,
basic
noneНетПри сборе данных из исходных систем баз данных (например, MySQL) через Debezium добавленные при изменении схемы поля можно синхронизировать с Doris. none означает, что изменения схемы исходной системы баз данных не синхронизируются с Doris. basic означает, что операции изменения данных в исходной базе данных синхронизируются. Поскольку изменения схемы столбцов — опасные операции, которые могут случайно удалить столбцы из схемы таблицы Doris, сейчас поддерживается только добавление столбцов из источника. При переименовании столбца старый столбец остаётся без изменений, а коннектор добавляет новый столбец в целевую таблицу и записывает в него новые данные из переименованного столбца.
enable.delete-falseНетСинхронизировать ли записи об удалении при синхронизации через Debezium. Значение по умолчанию — false. При синхронизации без Debezium необходимо добавить в сообщение маркер удаления.
database.time_zone-UTCНетКогда для converter.mode задан режим, отличный от normal, этот параметр определяет преобразование часового пояса для типов данных даты и времени, таких как datetime, date и timestamp. Значение по умолчанию — UTC.
avro.topic2schema.filepath--НетРазбирает содержимое Avro в топике, читая локальный файл схемы Avro, что устраняет зависимость от Confluent Schema Registry. Этот параметр необходимо использовать вместе с префиксом key.converter или value.converter. Например, настройте локальные файлы схем Avro для топиков avro-user и avro-product: "value.converter.avro.topic2schema.filepath":"avro-user:file:///opt/avro_user.avsc, avro-product:file:///opt/avro_product.avsc". Подробнее об использовании см. #32.
record.tablename.field--НетЕсли этот параметр включён, данные из одного топика могут поступать в несколько таблиц Doris. Подробнее о настройке см. #58.
max.retries-10НетМаксимальное количество повторных попыток после ошибки до завершения задачи со сбоем.
retry.interval.ms-6000НетВремя ожидания перед повторной попыткой после ошибки в миллисекундах. Значение по умолчанию — 6000 миллисекунд.
behavior.on.null.valuesignore,
fail
ignoreНетСпособ обработки записей со значениями null. По умолчанию они пропускаются.

Сопоставление типов​

Doris Kafka Connector использует примитивные или логические типы Kafka Connect для определения типа данных столбца. Примитивные типы — это простые типы данных, представленные с помощью Kafka Connect Schema. Логические типы обычно представлены с помощью Struct для описания сложных типов или типов даты и времени.

Примитивные типы Kafka​

Примитивный тип KafkaТип Doris
INT8TINYINT
INT16SMALLINT
INT32INT
INT64BIGINT
FLOAT32FLOAT
FLOAT64DOUBLE
BOOLEANBOOLEAN
STRINGSTRING
BYTESSTRING

Логические типы Kafka​

Логический тип KafkaТип Doris
org.apache.kafka.connect.data.DecimalDECIMAL
org.apache.kafka.connect.data.DateDATE
org.apache.kafka.connect.data.TimeSTRING
org.apache.kafka.connect.data.TimestampDATETIME

Логические типы Debezium​

Логический тип DebeziumТип Doris
io.debezium.time.DateDATE
io.debezium.time.TimeString
io.debezium.time.MicroTimeDATETIME
io.debezium.time.NanoTimeDATETIME
io.debezium.time.ZonedTimeDATETIME
io.debezium.time.TimestampDATETIME
io.debezium.time.MicroTimestampDATETIME
io.debezium.time.NanoTimestampDATETIME
io.debezium.time.ZonedTimestampDATETIME
io.debezium.data.VariableScaleDecimalDOUBLE

Настройка коннектора для различных сценариев работы с данными​

Синхронизация обычных данных JSON​

Этот сценарий предназначен для записи обычных сообщений JSON из топика Kafka в таблицу Doris.

  1. Просмотрите пример данных в Kafka:

    kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test-data-topic --from-beginning
    {"user_id":1,"name":"Emily","age":25}
    {"user_id":2,"name":"Benjamin","age":35}
    {"user_id":3,"name":"Olivia","age":28}
    {"user_id":4,"name":"Alexander","age":60}
    {"user_id":5,"name":"Ava","age":17}
    {"user_id":6,"name":"William","age":69}
    {"user_id":7,"name":"Sophia","age":32}
    {"user_id":8,"name":"James","age":64}
    {"user_id":9,"name":"Emma","age":37}
    {"user_id":10,"name":"Liam","age":64}
  2. Создайте целевую таблицу в Doris:

    CREATE TABLE test_db.test_kafka_connector_tbl (
    user_id BIGINT NOT NULL COMMENT "user id",
    name VARCHAR(20) COMMENT "name",
    age INT COMMENT "age"
    )
    DUPLICATE KEY(user_id)
    DISTRIBUTED BY HASH(user_id) BUCKETS 12;
  3. На машине, где развёрнут Kafka Connect, отправьте задачу загрузки с помощью curl:

    curl -i http://127.0.0.1:8083/connectors -H "Content-Type: application/json" -X POST -d '{
    "name":"test-doris-sink-cluster",
    "config":{
    "connector.class":"org.apache.doris.kafka.connector.DorisSinkConnector",
    "tasks.max":"10",
    "topics":"test-data-topic",
    "doris.topic2table.map":"test-data-topic:test_kafka_connector_tbl",
    "doris.urls":"10.10.10.1",
    "doris.user":"root",
    "doris.password":"",
    "doris.http.port":"8030",
    "doris.query.port":"9030",
    "doris.database":"test_db",
    "buffer.count.records":"10000",
    "buffer.flush.time":"120",
    "buffer.size.bytes":"5000000",
    "enable.combine.flush":"true",
    "key.converter":"org.apache.kafka.connect.storage.StringConverter",
    "value.converter":"org.apache.kafka.connect.json.JsonConverter",
    "value.converter.schemas.enable":"false"
    }
    }'

Синхронизация данных, полученных с помощью Debezium​

Этот сценарий предназначен для записи в Doris через Kafka данных MySQL CDC, полученных с помощью Debezium.

  1. В базе данных MySQL есть следующая таблица с данными:

    CREATE TABLE test.test_user (
    user_id int NOT NULL,
    name varchar(20),
    age int,
    PRIMARY KEY (user_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

    INSERT INTO test.test_user VALUES (1, 'zhangsan', 20);
    INSERT INTO test.test_user VALUES (2, 'lisi', 21);
    INSERT INTO test.test_user VALUES (3, 'wangwu', 22);
  2. Создайте целевую таблицу в Doris:

    CREATE TABLE test_db.test_user (
    user_id BIGINT NOT NULL COMMENT "user id",
    name VARCHAR(20) COMMENT "name",
    age INT COMMENT "age"
    )
    UNIQUE KEY(user_id)
    DISTRIBUTED BY HASH(user_id) BUCKETS 12;
  3. Разверните компонент Debezium connector for MySQL. Подробные инструкции см. в разделе Debezium connector for MySQL.

  4. Создайте задачу загрузки doris-kafka-connector. Предположим, что данные таблицы MySQL, полученные с помощью Debezium, находятся в топике mysql_debezium.test.test_user:

    curl -i http://127.0.0.1:8083/connectors -H "Content-Type: application/json" -X POST -d '{
    "name":"test-debezium-doris-sink",
    "config":{
    "connector.class":"org.apache.doris.kafka.connector.DorisSinkConnector",
    "tasks.max":"10",
    "topics":"mysql_debezium.test.test_user",
    "doris.topic2table.map":"mysql_debezium.test.test_user:test_user",
    "doris.urls":"10.10.10.1",
    "doris.user":"root",
    "doris.password":"",
    "doris.http.port":"8030",
    "doris.query.port":"9030",
    "doris.database":"test_db",
    "buffer.count.records":"10000",
    "buffer.flush.time":"30",
    "buffer.size.bytes":"5000000",
    "enable.combine.flush":"true",
    "converter.mode":"debezium_ingestion",
    "enable.delete":"true",
    "key.converter":"org.apache.kafka.connect.json.JsonConverter",
    "value.converter":"org.apache.kafka.connect.json.JsonConverter"
    }
    }'

Синхронизация данных, сериализованных в Avro​

Этот сценарий предназначен для чтения топика Kafka с данными, сериализованными в Avro, и их разбора с помощью Confluent Avro Converter.

curl -i http://127.0.0.1:8083/connectors -H "Content-Type: application/json" -X POST -d '{
"name":"doris-avro-test",
"config":{
"connector.class":"org.apache.doris.kafka.connector.DorisSinkConnector",
"topics":"avro_topic",
"tasks.max":"10",
"doris.topic2table.map":"avro_topic:avro_tab",
"doris.urls":"127.0.0.1",
"doris.user":"root",
"doris.password":"",
"doris.http.port":"8030",
"doris.query.port":"9030",
"doris.database":"test",
"buffer.count.records":"100000",
"buffer.flush.time":"120",
"buffer.size.bytes":"10000000",
"enable.combine.flush":"true",
"key.converter":"io.confluent.connect.avro.AvroConverter",
"key.converter.schema.registry.url":"http://127.0.0.1:8081",
"value.converter":"io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url":"http://127.0.0.1:8081"
}
}'

Синхронизация данных, сериализованных в Protobuf​

Этот сценарий предназначен для чтения топика Kafka с данными, сериализованными в Protobuf, и их разбора с помощью Confluent Protobuf Converter.

curl -i http://127.0.0.1:8083/connectors -H "Content-Type: application/json" -X POST -d '{
"name":"doris-protobuf-test",
"config":{
"connector.class":"org.apache.doris.kafka.connector.DorisSinkConnector",
"topics":"proto_topic",
"tasks.max":"10",
"doris.topic2table.map":"proto_topic:proto_tab",
"doris.urls":"127.0.0.1",
"doris.user":"root",
"doris.password":"",
"doris.http.port":"8030",
"doris.query.port":"9030",
"doris.database":"test",
"buffer.count.records":"100000",
"buffer.flush.time":"120",
"buffer.size.bytes":"10000000",
"enable.combine.flush":"true",
"key.converter":"io.confluent.connect.protobuf.ProtobufConverter",
"key.converter.schema.registry.url":"http://127.0.0.1:8081",
"value.converter":"io.confluent.connect.protobuf.ProtobufConverter",
"value.converter.schema.registry.url":"http://127.0.0.1:8081"
}
}'

Преобразование данных с помощью Kafka Connect SMT​

Этот сценарий предназначен для добавления полей или преобразования форматов в отдельных сообщениях Kafka перед записью в Doris. В следующем примере InsertField добавляет статическое поле, а TimestampConverter преобразует временную метку типа Bigint в строку времени.

Пример исходных данных:

{
"registertime": 1513885135404,
"userid": "User_9",
"regionid": "Region_3",
"gender": "MALE"
}

Создайте коннектор:

curl -i http://127.0.0.1:8083/connectors -H "Content-Type: application/json" -X POST -d '{
"name":"insert_field_tranform",
"config":{
"connector.class":"org.apache.doris.kafka.connector.DorisSinkConnector",
"tasks.max":"1",
"topics":"users",
"doris.topic2table.map":"users:kf_users",
"buffer.count.records":"10000",
"buffer.flush.time":"10",
"buffer.size.bytes":"5000000",
"doris.urls":"127.0.0.1:8030",
"doris.user":"root",
"doris.password":"123456",
"doris.http.port":"8030",
"doris.query.port":"9030",
"doris.database":"testdb",
"key.converter":"org.apache.kafka.connect.storage.StringConverter",
"value.converter":"org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable":"false",
"transforms":"InsertField,TimestampConverter",
"transforms.InsertField.type":"org.apache.kafka.connect.transforms.InsertField$Value",
"transforms.InsertField.static.field":"repo",
"transforms.InsertField.static.value":"Apache Doris",
"transforms.TimestampConverter.type":"org.apache.kafka.connect.transforms.TimestampConverter$Value",
"transforms.TimestampConverter.field":"registertime",
"transforms.TimestampConverter.format":"yyyy-MM-dd HH:mm:ss.SSS",
"transforms.TimestampConverter.target.type":"string"
}
}'

После обработки SMT данные из примера принимают следующий вид:

{
"userid": "User_9",
"regionid": "Region_3",
"gender": "MALE",
"repo": "Apache Doris",
"registertime": "2017-12-21 03:38:55.404"
}

Здесь repo — статическое поле, добавленное с помощью InsertField, а registertime — строка времени, полученная с помощью TimestampConverter. Другие примеры преобразований отдельных сообщений Kafka Connect Single Message Transforms (SMT) см. в документации SMT.

Рекомендации​

Доступ к среде Doris с включённым TLS из Kafka Connect​

При записи в кластер Doris с включённым TLS добавьте следующие параметры в конфигурацию коннектора:

{
"doris.urls":"doris-fe.example.com",
"doris.http.port":"8040",
"doris.query.port":"9030",
"doris.enable.tls":"true",
"doris.tls.ca-certificate-path":"/etc/kafka-connect/certs/doris-ca.pem"
}

Указывайте в doris.urls только имена хостов; не добавляйте схему или порт. Если путь к CA не настроен, коннектор не загружает пользовательский CA и использует стандартное хранилище доверенных сертификатов соответствующего клиента.

Разместите файл CA в соответствии с режимом развёртывания Kafka Connect:

  • Standalone: поместите файл CA на хост Worker и укажите его локальный путь.
  • Distributed: поместите файл CA по одинаковому локальному пути на каждом Worker, поскольку задача может быть назначена любому Worker.
  • Kubernetes: смонтируйте один и тот же Secret или том в каждый Pod Kafka Connect Worker и укажите путь монтирования.

Использование режима записи S3 TVF​

Режим записи TVF сохраняет данные в формате JSON в объектном хранилище, совместимом с S3, а затем записывает их в Doris через S3 TVF. Убедитесь, что Kafka Connect и Doris имеют доступ к объектному хранилищу и что целевая таблица Doris уже существует. Добавьте следующие параметры в конфигурацию коннектора:

{
"load.model":"tvf",
"enable.combine.flush":"true",
"delivery.guarantee":"at_least_once",
"sink.properties.columns":"id,name,age",
"sink.s3.endpoint":"$YOUR_S3_ENDPOINT",
"sink.s3.region":"$YOUR_S3_REGION",
"sink.s3.bucket":"$YOUR_S3_BUCKET",
"sink.s3.prefix":"$YOUR_S3_PREFIX",
"sink.s3.access-key":"$YOUR_S3_ACCESS_KEY",
"sink.s3.secret-key":"$YOUR_S3_SECRET_KEY"
}

sink.properties.columns должен содержать список столбцов целевой таблицы в порядке записи. Коннектор не удаляет промежуточные объекты автоматически; при необходимости настройте политику жизненного цикла объектного хранилища.

Часто задаваемые вопросы​

При чтении данных JSON возникает ошибка JsonConverter with schemas.enable requires "schema" and "payload" fields​

Сообщение об ошибке:

Caused by: org.apache.kafka.connect.errors.DataException: JsonConverter with schemas.enable requires "schema" and "payload" fields and may not contain additional fields. If you are trying to deserialize plain JSON data, set schemas.enable=false in your converter configuration.
at org.apache.kafka.connect.json.JsonConverter.toConnectData(JsonConverter.java:337)
at org.apache.kafka.connect.storage.Converter.toConnectData(Converter.java:91)
at org.apache.kafka.connect.runtime.WorkerSinkTask.lambda$convertAndTransformRecord$4(WorkerSinkTask.java:536)
at org.apache.kafka.connect.runtime.errors.RetryWithToleranceOperator.execAndRetry(RetryWithToleranceOperator.java:180)
at org.apache.kafka.connect.runtime.errors.RetryWithToleranceOperator.execAndHandleError(RetryWithToleranceOperator.java:214)

Причина:

При использовании org.apache.kafka.connect.json.JsonConverter данные должны соответствовать полям schema и payload.

Решение:

Используйте один из следующих способов:

  1. Замените org.apache.kafka.connect.json.JsonConverter на org.apache.kafka.connect.storage.StringConverter.
  2. Установите для value.converter.schemas.enable или key.converter.schemas.enable значение false в соответствующем файле конфигурации.
    • Режим Standalone: измените config/connect-standalone.properties.
    • Режим Distributed: измените config/connect-distributed.properties.

Превышено время ожидания чтения, потребитель исключён из группы потребителей​

Сообщение об ошибке:

org.apache.kafka.clients.consumer.CommitFailedException: Offset commit cannot be completed since the consumer is not part of an active group for auto partition assignment; it is likely that the consumer was kicked out of the group.
at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.sendOffsetCommitRequest(ConsumerCoordinator.java:1318)
at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.doCommitOffsetsAsync(ConsumerCoordinator.java:1127)
at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.commitOffsetsAsync(ConsumerCoordinator.java:1093)
at org.apache.kafka.clients.consumer.KafkaConsumer.commitAsync(KafkaConsumer.java:1590)
at org.apache.kafka.connect.runtime.WorkerSinkTask.doCommitAsync(WorkerSinkTask.java:361)
at org.apache.kafka.connect.runtime.WorkerSinkTask.doCommit(WorkerSinkTask.java:376)
at org.apache.kafka.connect.runtime.WorkerSinkTask.commitOffsets(WorkerSinkTask.java:467)
at org.apache.kafka.connect.runtime.WorkerSinkTask.commitOffsets(WorkerSinkTask.java:381)
at org.apache.kafka.connect.runtime.WorkerSinkTask.iteration(WorkerSinkTask.java:221)
at org.apache.kafka.connect.runtime.WorkerSinkTask.execute(WorkerSinkTask.java:206)
at org.apache.kafka.connect.runtime.WorkerTask.doRun(WorkerTask.java:204)
at org.apache.kafka.connect.runtime.WorkerTask.run(WorkerTask.java:259)
at org.apache.kafka.connect.runtime.isolation.Plugins.lambda$withClassLoader$1(Plugins.java:181)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)

Решение:

Увеличьте значение параметра Kafka max.poll.interval.ms в соответствии с вашим сценарием. Значение по умолчанию — 300000.

  • Режим Standalone: добавьте max.poll.interval.ms и consumer.max.poll.interval.ms в config/connect-standalone.properties и настройте их значения.
  • Режим Distributed: добавьте max.poll.interval.ms и consumer.max.poll.interval.ms в config/connect-distributed.properties и настройте их значения.

После изменения параметров перезапустите Kafka Connect.

При обновлении Doris Kafka Connector с 1.0.0 или 1.1.0 до 24.0.0 возникают ошибки cleanup.policy=compact​

Сообщение об ошибке:

org.apache.kafka.common.config.ConfigException: Topic 'connect-status' supplied via the 'status.storage.topic' property is required to have 'cleanup.policy=compact' to guarantee consistency and durability of connector and task statuses, but found the topic currently has 'cleanup.policy=delete'. Continuing would likely result in eventually losing connector and task statuses and problems restarting this Connect cluster in the future. Change the 'status.storage.topic' property in the Connect worker configurations to use a topic with 'cleanup.policy=compact'.
at org.apache.kafka.connect.util.TopicAdmin.verifyTopicCleanupPolicyOnlyCompact(TopicAdmin.java:581)
at org.apache.kafka.connect.storage.KafkaTopicBasedBackingStore.lambda$topicInitializer$0(KafkaTopicBasedBackingStore.java:47)
at org.apache.kafka.connect.util.KafkaBasedLog.start(KafkaBasedLog.java:247)
at org.apache.kafka.connect.util.KafkaBasedLog.start(KafkaBasedLog.java:231)
at org.apache.kafka.connect.storage.KafkaStatusBackingStore.start(KafkaStatusBackingStore.java:228)
at org.apache.kafka.connect.runtime.AbstractHerder.startServices(AbstractHerder.java:164)
at org.apache.kafka.connect.runtime.distributed.DistributedHerder.run

Решение:

Измените политику очистки топиков connect-configs и connect-status на compact:

$KAFKA_HOME/bin/kafka-configs.sh --alter --entity-type topics --entity-name connect-configs --add-config cleanup.policy=compact --bootstrap-server 127.0.0.1:9092
$KAFKA_HOME/bin/kafka-configs.sh --alter --entity-type topics --entity-name connect-status --add-config cleanup.policy=compact --bootstrap-server 127.0.0.1:9092

Ошибка изменения схемы в режиме преобразования debezium_ingestion​

Сообщение об ошибке:

[2025-01-07 14:26:20,474] WARN [doris-normal_test_sink-connector|task-0] Table 'test_sink' cannot be altered because schema evolution is disabled. (org.apache.doris.kafka.connector.converter.RecordService:183)
[2025-01-07 14:26:20,475] ERROR [doris-normal_test_sink-connector|task-0] WorkerSinkTask{id=doris-normal_test_sink-connector-0} Task threw an uncaught and unrecoverable exception. Task is being killed and will not recover until manually restarted. Error: Cannot alter table org.apache.doris.kafka.connector.model.TableDescriptor@67cd8027 because schema evolution is disabled (org.apache.kafka.connect.runtime.WorkerSinkTask:612)
org.apache.doris.kafka.connector.exception.SchemaChangeException: Cannot alter table org.apache.doris.kafka.connector.model.TableDescriptor@67cd8027 because schema evolution is disabled
at org.apache.doris.kafka.connector.converter.RecordService.alterTableIfNeeded(RecordService.java:186)
at org.apache.doris.kafka.connector.converter.RecordService.checkAndApplyTableChangesIfNeeded(RecordService.java:150)
at org.apache.doris.kafka.connector.converter.RecordService.processStructRecord(RecordService.java:100)
at org.apache.doris.kafka.connector.converter.RecordService.getProcessedRecord(RecordService.java:305)
at org.apache.doris.kafka.connector.writer.DorisWriter.putBuffer(DorisWriter.java:155)
at org.apache.doris.kafka.connector.writer.DorisWriter.insertRecord(DorisWriter.java:124)
at org.apache.doris.kafka.connector.writer.StreamLoadWriter.insert(StreamLoadWriter.java:151)
at org.apache.doris.kafka.connector.service.DorisDefaultSinkService.insert(DorisDefaultSinkService.java:154)
at org.apache.doris.kafka.connector.service.DorisDefaultSinkService.insert(DorisDefaultSinkService.java:135)
at org.apache.doris.kafka.connector.DorisSinkTask.put(DorisSinkTask.java:97)
at org.apache.kafka.connect.runtime.WorkerSinkTask.deliverMessages(WorkerSinkTask.java:583)
at org.apache.kafka.connect.runtime.WorkerSinkTask.poll(WorkerSinkTask.java:336)
at org.apache.kafka.connect.runtime.WorkerSinkTask.iteration(WorkerSinkTask.java:237)
at org.apache.kafka.connect.runtime.WorkerSinkTask.execute(WorkerSinkTask.java:206)
at org.apache.kafka.connect.runtime.WorkerTask.doRun(WorkerTask.java:202)
at org.apache.kafka.connect.runtime.WorkerTask.run(WorkerTask.java:257)
at org.apache.kafka.connect.runtime.isolation.Plugins.lambda$withClassLoader$1(Plugins.java:177)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)

Решение:

В режиме преобразования debezium_ingestion изменения схемы по умолчанию отключены. Задайте debezium.schema.evolution=basic, чтобы включить изменения схемы.

Учтите, что включение изменения схемы не даёт строгой гарантии того, что в таблице Doris останется только изменённый столбец. Конкретные ограничения см. в описании параметра debezium.schema.evolution. Чтобы на стороне источника и получателя оставался только один столбец, рекомендуется сначала вручную добавить изменённый столбец в таблицу Doris, а затем перезапустить задачу коннектора. Коннектор продолжит чтение с последнего необработанного offset, сохраняя согласованность данных.

На этой странице