Kafka Connect简介

我们知道过去对于Kafka的定义是分布式,分区化的,带备份机制的日志提交服务。也就是一个分布式的消息队列,这也是他最常见的用法。但是Kafka不止于此,打开最新的官网。

我们看到Kafka最新的定义是:Apache Kafka® is a distributed streaming platform

分布式流处理平台。

这里也清晰的描述了Kafka的特点:Kafka用于构建实时数据管道和流式应用程序。它具有水平可扩展性、容错性、速度极快,并在数千家公司投入生产。

所以现在的Kafka已经不仅是一个分布式的消息队列,更是一个流处理平台。这源于它于0.9.0.0和0.10.0.0引入的两个全新的组件Kafka Connect与Kafka Streaming。

Kafka Connect简介

我们知道消息队列必须存在上下游的系统,对消息进行搬入搬出。比如经典的日志分析系统,通过flume读取日志写入kafka,下游由storm进行实时的数据处理。

Kafka Connect的作用就是替代Flume,让数据传输这部分工作可以由Kafka Connect来完成。Kafka Connect是一个用于在Apache Kafka和其他系统之间可靠且可靠地传输数据的工具。它可以快速地将大量数据集合移入和移出Kafka。

Kafka Connect的导入作业可以将数据库或从应用程序服务器收集的数据传入到Kafka,导出作业可以将Kafka中的数据传递到查询系统,也可以传输到批处理系统以进行离线分析。

Kafka Connect功能包括:

  • 一个通用的Kafka连接的框架 - Kafka Connect规范化了其他数据系统与Kafka的集成,简化了连接器开发,部署和管理
  • 分布式和独立模式 - 支持大型分布式的管理服务,也支持小型生产环境的部署
  • REST界面 - 通过易用的REST API提交和管理Kafka Connect
  • 自动偏移管理 - 只需从连接器获取一些信息,Kafka Connect就可以自动管理偏移量提交过程,因此连接器开发人员无需担心连接器开发中偏移量提交这部分的开发
  • 默认情况下是分布式和可扩展的 - Kafka Connect构建在现有的组管理协议之上。可以添加扩展集群
  • 流媒体/批处理集成 - 利用Kafka现有的功能,Kafka Connect是桥接流媒体和批处理数据系统的理想解决方案

运行Kafka Connect

Kafka Connect目前支持两种运行模式:独立和集群。

独立模式

在独立模式下,只有一个进程,这种更容易设置和使用。但是没有容错功能。

启动:
> bin/connect-standalone.sh config/connect-standalone.properties connector1.properties [connector2.properties ...]
独立模式配置

第一个参数config/connect-standalone.properties是一些基本的配置:

这几个在独立和集群模式下都需要设置:

#bootstrap.servers   kafka集群列表
bootstrap.servers=localhost:9092
#key.converter key的序列化转换器 比如json的 key.converter=org.apache.kafka.connect.json.JsonConverter
#value.converter value的序列化转换器
value.converter=org.apache.kafka.connect.json.JsonConverter #独立模式特有的配置:
#offset.storage.file.filename 用于存储偏移量的文件
offset.storage.file.filename =/home/kafka/connect.offsets
独立模式连接器配置(配置文件)

后面的参数connector1.properties [connector2.properties ...] 可以多个,是连接器配置内容

这里我们配置一个从文件读取数据并存入kafka的配置:

connect-file-sink.properties

  • name - 连接器的唯一名称。尝试再次使用相同名称注册将失败。

  • connector.class - 连接器的Java类 此连接器的类的全名或别名。这里我们选择FileStreamSink

  • tasks.max - 应为此连接器创建的最大任务数。如果连接器无法达到此级别的并行性,则可能会创建更少的任务。

  • key.converter - (可选)覆盖worker设置的默认密钥转换器。

  • value.converter - (可选)覆盖worker设置的默认值转换器。

    下面两个必须设置一个:

    • topics - 以逗号分隔的主题列表,用作此连接器的输入
    • topics.regex - 用作此连接器输入的主题的Java正则表达式
name=local-file-sink
connector.class=FileStreamSink
tasks.max=1
file=test.sink.txt
topics=connect-test

可以在连接器中配置转换器

需要指定参数:

  • transforms - 转换的别名列表,指定将应用转换的顺序。
  • transforms.$alias.type - 转换的完全限定类名。
  • transforms.$alias.$transformationSpecificConfig 转换的配置属性

例如,我们把刚才的文件转换器的内容添加字段

首先设置connect-standalone.properties

key.converter.schemas.enable = false
value.converter.schemas.enable = false

设置connect-file-source.properties

name=local-file-source
connector.class=FileStreamSource
tasks.max=1
file=test.txt
topic=connect-test
transforms=MakeMap, InsertSource
transforms.MakeMap.type=org.apache.kafka.connect.transforms.HoistField$Value
transforms.MakeMap.field=line
transforms.InsertSource.type=org.apache.kafka.connect.transforms.InsertField$Value
transforms.InsertSource.static.field=data_source
transforms.InsertSource.static.value=test-file-source

没有转换前的结果:

"foo"
"bar"
"hello world"

转换后:

{"line":"foo","data_source":"test-file-source"}
{"line":"bar","data_source":"test-file-source"}
{"line":"hello world","data_source":"test-file-source"}

常用转换类型:

  • InsertField - 使用静态数据或记录元数据添加字段
  • ReplaceField - 过滤或重命名字段
  • MaskField - 用类型的有效空值替换字段(0,空字符串等)
  • ValueToKey Value转换为Key
  • HoistField - 将整个事件作为单个字段包装在Struct或Map中
  • ExtractField - 从Struct和Map中提取特定字段,并在结果中仅包含此字段
  • SetSchemaMetadata - 修改架构名称或版本
  • TimestampRouter - 根据原始主题和时间戳修改记录主题
  • RegexRouter - 根据原始主题,替换字符串和正则表达式修改记录主题

集群模式

集群模式下,可以扩展,容错。

启动:
> bin/connect-distributed.sh config/connect-distributed.properties

在集群模式下,Kafka Connect在Kafka主题中存储偏移量,配置和任务状态。

集群模式配置

connect-distributed.properties

#也需要基本的配置
bootstrap.servers=localhost:9092
key.converter=org.apache.kafka.connect.json.JsonConverter
value.converter=org.apache.kafka.connect.json.JsonConverter #还有一些配置要注意
#group.id(默认connect-cluster) - Connect的组id 请注意,这不得与使用者的组id 冲突
group.id=connect-cluster #用于存储偏移的主题; 此主题应具有许多分区
offset.storage.topic=connect-offsets
offset.storage.replication.factor=1 #用于存储连接器和任务配置的主题 只能一个分区
config.storage.topic=connect-configs
config.storage.replication.factor=1 #用于存储状态的主题; 此主题可以有多个分区
status.storage.topic=connect-status
status.storage.replication.factor=1

在集群模式下,配置并不会在命令行传进去,而是需要REST API来创建,修改和销毁连接器。

集群模式连接器配置(REST API)

可以配置REST API服务器,支持http与https

listeners=http://localhost:8080,https://localhost:8443

默认情况下,如果未listeners指定,则REST服务器使用HTTP协议在端口8083上运行。

以下是当前支持的REST API:

  • GET /connectors - 返回活动连接器列表
  • POST /connectors - 创建一个新的连接器; 请求主体应该是包含字符串name字段的JSON对象和包含config连接器配置参数的对象字段
  • GET /connectors/{name} - 获取有关特定连接器的信息
  • GET /connectors/{name}/config - 获取特定连接器的配置参数
  • PUT /connectors/{name}/config - 更新特定连接器的配置参数
  • GET /connectors/{name}/status - 获取连接器的当前状态,包括它是否正在运行,失败,暂停等,分配给哪个工作人员,错误信息(如果失败)以及所有任务的状态
  • GET /connectors/{name}/tasks - 获取当前为连接器运行的任务列表
  • GET /connectors/{name}/tasks/{taskid}/status - 获取任务的当前状态,包括它是否正在运行,失败,暂停等,分配给哪个工作人员,以及错误信息是否失败
  • PUT /connectors/{name}/pause - 暂停连接器及其任务,这将停止消息处理,直到恢复连接器
  • PUT /connectors/{name}/resume - 恢复暂停的连接器(如果连接器未暂停,则不执行任何操作)
  • POST /connectors/{name}/restart - 重新启动连接器(通常是因为它已经失败)
  • POST /connectors/{name}/tasks/{taskId}/restart - 重启个别任务(通常因为失败)
  • DELETE /connectors/{name} - 删除连接器,暂停所有任务并删除其配置

连接器开发指南

kakfa允许开发人员自己去开发一个连接器。

核心概念

要在Kafka和其他系统之间复制数据,用户需要创建一个Connector

Connector有两种形式:

SourceConnectors从另一个系统导入数据,例如,JDBCSourceConnector将关系数据库导入Kafka

SinkConnectors导出数据,例如,HDFSSinkConnector将Kafka主题的内容导出到HDFS文件

和对应的Task:

SourceTaskSinkTask

Task形成输入输出流,开发Task要注意偏移量的问题。

每个流应该是一系列键值记录。还需要定期提交已处理的数据的偏移量,以便在发生故障时,处理可以从上次提交的偏移量恢复。Connector还需要是动态的,实现还负责监视外部系统是否存在任何更改。

开发一个简单的连接器

开发连接器只需要实现两个接口,即ConnectorTask

这里我们简单开发一个FileStreamConnector。

此连接器是为在独立模式下使用,SourceConnectorSourceTask读取文件的每一行,SinkConnectorSinkTask每个记录写入一个文件。

连接器示例:

继承SourceConnector,添加字段(要读取的文件名和要将数据发送到的主题)

public class FileStreamSourceConnector extends SourceConnector {
private String filename;
private String topic;

定义实际读取数据的类

@Override
public Class<? extends Task> taskClass() {
return FileStreamSourceTask.class;
}

FileStreamSourceTask下面定义该类。接下来,我们添加一些标准的生命周期方法,start()stop()

@Override
public void start(Map<String, String> props) {
// The complete version includes error handling as well.
filename = props.get(FILE_CONFIG);
topic = props.get(TOPIC_CONFIG);
} @Override
public void stop() {
// Nothing to do since no background monitoring is required.
}

最后,实施的真正核心在于taskConfigs()

@Override
public List<Map<String, String>> taskConfigs(int maxTasks) {
ArrayList<Map<String, String>> configs = new ArrayList<>();
// Only one input stream makes sense.
Map<String, String> config = new HashMap<>();
if (filename != null)
config.put(FILE_CONFIG, filename);
config.put(TOPIC_CONFIG, topic);
configs.add(config);
return configs;
}

任务示例:

源任务

实现SourceTask 创建FileStreamSourceTask继承SourceTask

public class FileStreamSourceTask extends SourceTask {
String filename;
InputStream stream;
String topic; @Override
public void start(Map<String, String> props) {
filename = props.get(FileStreamSourceConnector.FILE_CONFIG);
stream = openOrThrowError(filename);
topic = props.get(FileStreamSourceConnector.TOPIC_CONFIG);
} @Override
public synchronized void stop() {
stream.close();
}

接下来,我们实现任务的主要功能,即poll()从输入系统获取事件并返回以下内容的方法List

@Override
public List<SourceRecord> poll() throws InterruptedException {
try {
ArrayList<SourceRecord> records = new ArrayList<>();
while (streamValid(stream) && records.isEmpty()) {
LineAndOffset line = readToNextLine(stream);
if (line != null) {
Map<String, Object> sourcePartition = Collections.singletonMap("filename", filename);
Map<String, Object> sourceOffset = Collections.singletonMap("position", streamOffset);
records.add(new SourceRecord(sourcePartition, sourceOffset, topic, Schema.STRING_SCHEMA, line));
} else {
Thread.sleep(1);
}
}
return records;
} catch (IOException e) {
// Underlying stream was killed, probably as a result of calling stop. Allow to return
// null, and driving thread will handle any shutdown if necessary.
}
return null;
}
接收任务

不像SourceConnectorSinkConnectorSourceTaskSinkTask有非常不同的接口,因为SourceTask采用的是拉接口,并SinkTask使用推接口。两者共享公共生命周期方法,但SinkTask完全不同:

public abstract class SinkTask implements Task {
public void initialize(SinkTaskContext context) {
this.context = context;
} public abstract void put(Collection<SinkRecord> records); public void flush(Map<TopicPartition, OffsetAndMetadata> currentOffsets) {
}

这是一个简单的例子,它们有简单的结构化数据 - 每一行只是一个字符串。几乎所有实用的连接器都需要具有更复杂数据格式的模式。要创建更复杂的数据,您需要使用Kafka Connect dataAPI。

Schema schema = SchemaBuilder.struct().name(NAME)
.field("name", Schema.STRING_SCHEMA)
.field("age", Schema.INT_SCHEMA)
.field("admin", new SchemaBuilder.boolean().defaultValue(false).build())
.build(); Struct struct = new Struct(schema)
.put("name", "Barbara Liskov")
.put("age", 75);

更多Kafka相关技术文章:

什么是Kafka?
Kafka监控工具汇总
Kafka快速入门
Kafka核心之Consumer
Kafka核心之Producer

更多实时计算,Flink,Kafka等相关技术博文,欢迎关注实时流式计算

Apache Kafka® is a distributed streaming platform的更多相关文章

  1. 1.1 Introduction中 Apache Kafka™ is a distributed streaming platform. What exactly does that mean?(官网剖析)(博主推荐)

    不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Apache Kafka™ is a distributed streaming p ...

  2. Apache Kafka: Next Generation Distributed Messaging System---reference

    Introduction Apache Kafka is a distributed publish-subscribe messaging system. It was originally dev ...

  3. Apache Kafka学习 (一)

    前言:最近公司开始要研究大数据的消息记录,于是开始研究kafka. 市面上kafka的书很少,有的也版本比较落后,于是仗着自己英文还不错,上官网直接学习. ^_^ 1. 开始 - 基本概念 学习一样东 ...

  4. Putting Apache Kafka To Use: A Practical Guide to Building a Stream Data Platform-part 1

    转自: http://www.confluent.io/blog/stream-data-platform-1/ These days you hear a lot about "strea ...

  5. Apache Kafka - How to Load Test with JMeter

    In this article, we are going to look at how to load test Apache Kafka, a distributed streaming plat ...

  6. How Cigna Tuned Its Spark Streaming App for Real-time Processing with Apache Kafka

    Explore the configuration changes that Cigna’s Big Data Analytics team has made to optimize the perf ...

  7. Introducing KSQL: Streaming SQL for Apache Kafka

    Update: KSQL is now available as a component of the Confluent Platform. I’m really excited to announ ...

  8. Offset Management For Apache Kafka With Apache Spark Streaming

    An ingest pattern that we commonly see being adopted at Cloudera customers is Apache Spark Streaming ...

  9. KSQL: Streaming SQL for Apache Kafka

    Few weeks back, while I was enjoying my holidays in the south of Italy, I started receiving notifica ...

随机推荐

  1. shell 编程生成日期文件;Server虚拟机上进行Web服务器配置

    shell 编程生成日期文件 1. 请编写一个脚本,命名为sh01.sh,其功能是: 键盘输入文件名(要求使用名字全拼作为文件名). 自动创建3个文件. 1个为系统当天日期(CCYYMMDD). 1个 ...

  2. sql 查询哪些字段重复及(in和exict的区别)

    select count(1),content_id,keyword_id from tb_content_keyword_relation group by content_id,keyword_i ...

  3. 欢迎访问阿里云Go Module代理仓库服务

    简介 go module公共代理仓库,代理并缓存go模块.你可以利用该代理来避免DNS污染导致的模块拉取缓慢或失败的问题,加速你的构建. 地址 https://mirrors.aliyun.com/g ...

  4. The difference between Virtual DOM and DOM

    dom是结构化的文本信息的抽象,是结构化的文本信息在内存中的表示 是操作结构化文本信息的api. Follow: Follow React attacks us with the virtual DO ...

  5. [GXOI/GZOI2019]旅行者 (最短路)

    题意 给定一个有向图,其中一些顶点为关键点.求这些关键点两两之间最小距离. 题解 考试时没怎么想写了50分暴力走了.以为是什么强连通分量的解法,结果就是个最短路.直接从关键点跑一次最短路dis[0], ...

  6. vim文本编辑器——文件导入、命令查找、导入命令执行结果、自定义快捷键、ab命令、快捷键的保存

    1.文件的导入(r): 导入前: 导入后: 在光标处,将tmp目录下的zhbb文件的内容导入到了当前文件. 2.命令的查找: 3.导入命令的执行结果: 光标所在行为导入的位置. 4.自定义快捷键: ( ...

  7. Reactive Extensions (Rx) 入门(5) —— Rx的事件编程

    译文:https://blog.csdn.net/fangxing80/article/details/7749907 原文:http://www.atmarkit.co.jp/fdotnet/int ...

  8. 洛谷P2580 于是他错误的点名开始了 题解

    qwq!为什么!木有非结构体非指针的题解怎么阔以!所以, 我来辽~咻咻咻~ 题面 来分析, 我们可以先建一棵树,来存储整个名单, 然后再判断 ; i <= n; i++) { root = ; ...

  9. 服务器使用bbr加速配置

    服务器内核升级: 以centos7为例,配置之前可使用以下命令查看内核版本,若是4.0以上则无需对内核升级: uname -r 对内核升级的方法: 直接使用以下命令进行内核版本的下载: rpm --i ...

  10. UmiJS可插拔的企业级 react 应用框架,配合ant-design-pro使用

    入门非常简单 # 安装 $ yarn global add umi # 或者 npm install -g umi # 新建应用 $ mkdir myapp && cd myapp # ...