上一篇【第70篇】Kafka多数据中心高可用——跨数据中心的Kafka高可用
下一篇【第72篇】Kafka Connect深度解析——Connector是如何工作的
摘要
Kafka Connect是Kafka生态中负责数据集成的主力工具。它把"从A系统读、写到B系统"这个ETL场景标准化成了可插拔的Connector架构。很多人知道要用Connect,但第一次配置时总被各种参数搞懵。
本文将手把手带你用Kafka Connect搭建一条MySQL → Kafka → Elasticsearch的实时数据管道。从Connect集群启动、JDBC Source Connector配置、ES Sink Connector配置,到全链路验证,每一步都有可运行的命令和配置。10分钟后,你就能看到MySQL的数据实时出现在Elasticsearch里。
一、Kafka Connect 架构速览
先搞清楚Connect的本质:
【Kafka Connect 架构图】
┌─────────────────────────────────────────────────┐
│ Kafka Connect Cluster │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Worker 1 │ │ Worker 2 │ │
│ │ (Standalone │ │ (Distributed │ │
│ │ /Distributed)│ │ Mode) │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────┐ │
│ │ Kafka Topic │ │
│ │ mysql-orders (3 partitions) │ │
│ └──────────────────┬───────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ ES Sink │ │ ES Sink │ │
│ │ Connector │ │ Connector │ │
│ │ (Task×3) │ │ (Task×3) │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────┘
│
▼
┌──────────────────┐
│ Elasticsearch │
│ Index: orders │
└──────────────────┘
核心概念:
| 概念 | 含义 | 类比 |
|---|---|---|
| Connector | 数据管道的定义(从哪来、到哪去) | 蓝图 |
| Task | Connector的实际执行单元(并行度) | 工人 |
| Worker | 运行Connector/Task的进程 | 工地 |
| Source Connector | 从外部系统读数据写入Kafka | 进口 |
| Sink Connector | 从Kafka读数据写入外部系统 | 出口 |
二、启动Connect集群(Distributed模式)
2.1 为什么选Distributed模式
【Standalone vs Distributed】
Standalone(单机):
┌────────────────────┐
│ 所有Connector跑在一个进程 │
│ → 挂了全挂(无HA) │
│ → 无法横向扩展 │
└────────────────────┘
Distributed(分布式)★推荐:
┌────────────────────┐
│ 多个Worker组成集群 │
│ → 自动负载均衡 │
│ → Worker挂了自动迁移Task │
│ → 支持Rest API管理 │
└────────────────────┘
2.2 Worker配置文件
# connect-distributed.properties
# ===== 核心配置 =====
# 集群唯一名称(同一集群的Worker要用同一个)
group.id=connect-cluster
# REST API监听地址
rest.host.name=0.0.0.0
rest.port=8083
# Kafka集群地址(Connect用自己的Kafka存offset和状态)
bootstrap.servers=localhost:9092
# 内部Topic配置(Connect自动创建,不要手动建)
offset.storage.topic=connect-offsets
offset.storage.replication.factor=3
offset.storage.partitions=25
config.storage.topic=connect-configs
config.storage.replication.factor=3
status.storage.topic=connect-status
status.storage.replication.factor=3
# KEY/VALUE 转换器(消息格式)
key.converter=org.apache.kafka.connect.json.JsonConverter
value.converter=org.apache.kafka.connect.json.JsonConverter
key.converter.schemas.enable=false
value.converter.schemas.enable=false
# 并行度
tasks.max=4
2.3 启动Worker
# 启动第一个Worker
export CLASSPATH=/path/to/connector-plugins/*
bin/connect-distributed.sh \
config/connect-distributed.properties &
# 等待启动完成(看到 "Started" 日志)
# REST API可用:http://localhost:8083
# 验证集群状态
curl http://localhost:8083/ | jq .
# 预期输出:
# {
# "version": "3.6.0",
# "commit": "abc123",
# "kafka_cluster_id": "xyz789"
# }
三、部署JDBC Source Connector(MySQL → Kafka)
3.1 下载JDBC Connector插件
# Confluent官方的JDBC Connector
# 下载地址:https://www.confluent.io/hub/confluentinc/kafka-connect-jdbc
# 解压到Connect的插件目录
mkdir -p /opt/kafka/plugins
tar -xzf confluentinc-kafka-connect-jdbc-*.tar.gz \
-C /opt/kafka/plugins/
# 把MySQL驱动也放进去
cp mysql-connector-j-8.0.*.jar /opt/kafka/plugins/
# 重启所有Worker(加载新插件)
# 或者热加载(如果配置了plugin.path)
3.2 创建JDBC Source Connector
# 创建MySQL Source Connector
curl -X POST http://localhost:8083/connectors \
-H "Content-Type: application/json" \
-d '{
"name": "mysql-orders-source",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector",
"tasks.max": "2",
# === 数据库连接 ===
"connection.url": "jdbc:mysql://localhost:3306/orders_db?useSSL=false",
"connection.user": "kafka_user",
"connection.password": "kafka_pass",
# === 要同步的表 ===
"table.whitelist": "orders,order_items",
"mode": "timestamp+incrementing",
"timestamp.column.name": "updated_at",
"incrementing.column.name": "id",
# === Topic配置 ===
"topic.prefix": "mysql-",
# === 轮询间隔 ===
"poll.interval.ms": "5000",
# === 批量大小 ===
"batch.max.rows": "1000"
}
}' | jq .
3.3 配置参数详解
【JDBC Source 关键参数】
┌──────────────────────────────────────────────────────┐
│ 参数 │ 说明 │
├─────────────────────────┼─────────────────────┤
│ mode │ 增量检测模式 │
│ • "bulk" │ 全表扫描(首次用) │
│ • "incrementing" │ 按自增ID拉取 │
│ • "timestamp" │ 按时间戳列拉取 │
│ • "timestamp+incrementing" │ ★推荐:两者结合 │
├─────────────────────────┼─────────────────────┤
│ topic.prefix │ Topic名称前缀 │
│ → 实际Topic: mysql-orders │
├──────────────────────────────────────────────────────┤
│ poll.interval.ms │ 每次轮询间隔(毫秒) │
│ → 5秒检查一次新数据 │
├──────────────────────────────────────────────────────┤
│ timestamp.initial │ 首次启动时如何处理已有数据 │
│ • "latest" │ 跳过历史数据(只同步新) │
│ • "earliest" │ 同步全部历史数据 ★ │
└──────────────────────────────────────────────────────┘
3.4 验证Source Connector
# 查看Connector状态
curl http://localhost:8083/connectors/mysql-orders-source/status | jq .
# 预期输出:
# {
# "name": "mysql-orders-source",
# "connector": { "state": "RUNNING", "worker_id": "..." },
# "tasks": [
# { "id": 0, "state": "RUNNING", "worker_id": "..." },
# { "id": 1, "state": "RUNNING", "worker_id": "..." }
# ],
# "type": "source"
# }
# 检查Topic是否已创建
bin/kafka-topics.sh --bootstrap-server localhost:9092 \
--list | grep mysql-
# 预期看到:mysql-orders, mysql-order_items
# 消费数据验证
bin/kafka-console-consumer.sh \
--bootstrap-server localhost:9092 \
--topic mysql-orders \
--from-beginning \
--property print.key=true
四、部署ES Sink Connector(Kafka → Elasticsearch)
4.1 下载ES Connector插件
# Confluent官方的Elasticsearch Connector
# 下载地址:https://www.confluent.io/hub/confluentinc/kafka-connect-elasticsearch
tar -xzf confluentinc-kafka-connect-elasticsearch-*.tar.gz \
-C /opt/kafka/plugins/
# 重启Worker加载插件
4.2 创建ES Sink Connector
curl -X POST http://localhost:8083/connectors \
-H "Content-Type: application/json" \
-d '{
"name": "es-orders-sink",
"config": {
"connector.class": "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector",
"tasks.max": "2",
# === Kafka侧配置 ===
"topics": "mysql-orders",
"value.conversion.schemas.enable": "false",
# === ES侧配置 ===
"connection.url": "http://localhost:9200",
"type.name": "_doc",
"key.ignore": "true",
# === 写入行为 ===
"behavior.on.malformation": "IGNORE",
"max.buffered.records": "10000",
"batch.size": "2000",
"linger.ms": "500",
# === ID映射 ===
"key.ignore": "true",
"schemas.enable": "false"
}
}' | jq .
4.3 Sink Connector参数详解
【ES Sink 关键参数】
┌──────────────────────────────────────────────────────┐
│ 参数 │ 说明 │
├────────────────────────┼──────────────────────┤
│ connection.url │ ES集群地址 │
│ │ 支持多个(逗号分隔) │
├────────────────────────┼──────────────────────┤
│ type.name │ ES的type(7.x后固定 │
│ │ 为_doc) │
├────────────────────────┼──────────────────────┤
│ key.ignore │ 是否忽略消息的Key │
│ • true │ 用消息内容生成ES _id │
│ • false │ 用Kafka消息Key作为 │
│ │ ES _id │
├────────────────────────┼──────────────────────┤
│ topics.regex │ 用正则匹配多个Topic │
│ │ 替代单个topics配置 │
├────────────────────────┼──────────────────────┤
│ max.buffered.records │ 最大缓冲记录数 │
│ │ 调大可提升吞吐 │
└──────────────────────────────────────────────────────┘
五、全链路验证
5.1 端到端测试
-- Step 1: 在MySQL中插入一条测试数据
USE orders_db;
INSERT INTO orders (id, user_id, amount, status, created_at, updated_at)
VALUES (1001, 501, 99.9, 'PAYED', NOW(), NOW());
-- 确认数据已写入
SELECT * FROM orders WHERE id = 1001;
# Step 2: 检查Kafka Topic中是否出现这条消息
bin/kafka-console-consumer.sh \
--bootstrap-server localhost:9092 \
--topic mysql-orders \
--from-beginning \
--max-messages 1
# 预期输出(JSON格式):
# {"schema":{...},"payload":{"id":1001,"user_id":501,...}}
# Step 3: 检查Elasticsearch中是否出现这条文档
curl -X GET "http://localhost:9200/orders/_search?pretty" \
-H "Content-Type: application/json" \
-d '{
"query": { "match": { "id": 1001 }}
}'
# 预期输出包含:
# {
# "hits": {
# "total": { "value": 1 },
# "hits": [
# { "_index": "orders", "_id": "...", "_source": { "id": 1001, ... }}
# ]
# }
# }
5.2 延迟测量
# 测量端到端延迟(MySQL → Kafka → ES)
# 在MySQL中写入带时间戳的记录
mysql> INSERT INTO orders (id, user_id, amount, created_at, updated_at)
-> VALUES (2001, 601, 50.0, NOW(3), NOW(3));
# 记录写入时间
MYSQL_TIME=$(date +%s%3N)
# 轮询ES直到出现这条记录
while true; do
RESULT=$(curl -s -X GET "http://localhost:9200/orders/_search" \
-H "Content-Type: application/json" \
-d "{\"query\":{\"match\":{\"id\":2001}}}")
if echo "$RESULT" | grep -q "\"found\":true"; then
ES_TIME=$(date +%s%3N)
LATENCY=$((ES_TIME - MYSQL_TIME))
echo "端到端延迟: ${LATENCY}ms"
break
fi
sleep 0.5
done
# 典型延迟:500ms ~ 3000ms(取决于 poll.interval.ms)
六、生产环境部署要点
6.1 高可用配置
# connect-distributed.properties(生产环境增强)
# 增加内部Topic的副本数
offset.storage.replication.factor=3
config.storage.replication.factor=3
status.storage.replication.factor=3
# 启用Connector的自动重启
# Connect会监控Task状态,失败时自动重启
status.storage.replication.factor=3
# REST API绑定内网地址(不要暴露到公网)
rest.host.name=192.168.1.50
6.2 监控Connect集群
# 查看所有Connector的状态
curl http://localhost:8083/connectors?expand=status | jq .
# 查看Worker集群信息
curl http://localhost:8083/workers | jq .
# 查看Connector的tasks分布
curl http://localhost:8083/connectors/mysql-orders-source/tasks | jq .
# Prometheus JMX Exporter配置(监控Connect)
rules:
- pattern: 'kafka.connect<type=connector-metrics,
connector=(.*)><>RecordReadTotal'
name: kafka_connect_records_read_total
labels:
connector: '$1'
- pattern: 'kafka.connect<type=connector-metrics,
connector=(.*)><>RecordWriteTotal'
name: kafka_connect_records_write_total
labels:
connector: '$1'
- pattern: 'kafka.connect<type=task-metrics,
connector=(.*), task=(.*)><>RecordErrorsTotal'
name: kafka_connect_record_errors_total
labels:
connector: '$1'
task: '$2'
本篇小结
今天我们手把手搭建了一条MySQL → Kafka → Elasticsearch的实时数据管道:
- Connect架构:Worker集群 + Connector(Source/Sink)+ Task(并行执行单元)
- 启动集群:用Distributed模式,配置内部Topic(offset/config/status)
- JDBC Source:配置
mode=timestamp+incrementing实现增量同步 - ES Sink:配置
connection.url和key.ignore完成写入 - 全链路验证:插入→Kafka消费验证→ES查询验证,三步确认数据流转正常
核心要点:Connector的配置80%的时间花在"上下游系统的认证授权"上,先把数据库/ES的账号权限配好,再调试Connector参数。
下一篇,我们将深入Connect的内部机制——Connector是怎么被加载的、Task是怎么分配到Worker的、offset是怎么管理的,用源码视角彻底理解Connect的工作原理。
上一篇【第70篇】Kafka多数据中心高可用——跨数据中心的Kafka高可用
下一篇【第72篇】Kafka Connect深度解析——Connector是如何工作的
297

被折叠的 条评论
为什么被折叠?



