此连接器可访问由Apache Kafka提供的事件流。


Flink提供特殊的Kafka连接器,用于从/到Kafka主题读取和写入数据。 Flink Kafka Consumer集成了Flink的检查点机制,以提供一次性处理语义。为了达到这个目的,Flink并不完全依靠Kafka的消费者群体偏移跟踪,而是跟踪和检查点内部的抵消。


请为您的用例和环境选择一个包(maven artifact id)和类名。对于大多数用户来说,FlinkKafkaConsumer08(flink-connector-kafka的一部分)是适当的。


Maven DependencySupported sinceConsumer and 
Producer Class name
Kafka versionNotes
flink-connector-kafka-0.8_2.101.0.0FlinkKafkaConsumer08
FlinkKafkaProducer08
0.8.xUses the SimpleConsumer API of Kafka internally. Offsets are committed to ZK by Flink.
flink-connector-kafka-0.9_2.101.0.0FlinkKafkaConsumer09
FlinkKafkaProducer09
0.9.xUses the new Consumer API Kafka.
flink-connector-kafka-0.10_2.101.2.0FlinkKafkaConsumer010
FlinkKafkaProducer010
0.10.xThis connector supports Kafka messages with timestamps both for producing and consuming.

FlinkKafkaProducer010 0.10.x此连接器支持具有生产和消费时间戳的Kafka消息。

然后,导入您的maven项目中的连接器:


<dependency>

  <groupId> org.apache.flink </ groupId>

  <artifactId> flink-connector-kafka-0.8_2.10 </ artifactId>

  <version> 1.2.0 </ version>

</dependency>


请注意,流连接器当前不是二进制分发的一部分。在这里查看如何链接到它们进行集群执行。


安装Apache Kafka

按照Kafka快速启动的说明下载代码并启动服务器(启动Zookeeper,启动应用程序前需要启动Kafka服务器)。

如果Kafka和Zookeeper服务器在远程机器上运行,则config / server.properties文件中的advertised.host.name设置必须设置为机器的IP地址(当然如果集群之间的hosts配置好,也是可以那个tname的)。


Kafka消费者

Flink的Kafka消费者称为FlinkKafkaConsumer08(或Kafka 0.9.0.x版本为09)。它提供访问一个或多个Kafka主题。


构造函数接受以下参数:


<1>主题名称(Topic)/主题名称列表(Topic Name List)

<2>用于反序列化Kafka数据的DeserializationSchema / KeyedDeserializationSchema

<3>Kafka消费者的属性配置。需要以下属性:

“bootstrap.servers”(逗号分隔的Kafka经纪人名单)

“zookeeper.connect”(逗号分隔的Zookeeper服务器列表)(仅适用于Kafka 0.8)

“group.id”消费者组的ID


例:

<Java代码>


Properties properties= new Properties();

properties.setProperty(“bootstrap.servers”,“localhost:9092”);

//仅需要Kafka 0.8

properties.setProperty(“zookeeper.connect”,“localhost:2181”);

properties.setProperty(“group.id”,“test”);

DataStream <String> stream = env

.addSource(new FlinkKafkaConsumer08 <>(“topic”,new SimpleStringSchema(),properties));


当前的FlinkKafkaConsumer实现将建立来自客户端的连接(当调用构造函数时)用于查询主题(topics)和分区列表(partitions)。


为了使其工作,消费者需要能够从提交作业的机器访问消费者到Flink群集。如果您在客户端遇到Kafka消费者的任何问题,客户端日志可能包含有关失败请求的信息等。


DeserializationSchema


Flink Kafka Consumer需要知道如何将Kafka中的二进制数据转换为Java / Scala对象。 DeserializationSchema允许用户指定这样的模式。对每个Kafka消息调用T deserialize(byte [] message))方法,从Kafka传递值。


从AbstractDeserializationSchema开始,通常有助于将生成的Java / Scala类型描述为Flink的类型系统。实现DeserializationSchema的用户需要自己实现getProducedType(...)方法。


对于访问Kafka消息的键和值,KeyedDeserializationSchema具有以下反序列化方法`T deserialize(byte [] messageKey,byte [] message,String topic,int partition,long offset)`。


为方便起见,Flink提供以下模式:


<1> TypeInformationSerializationSchema(和TypeInformationKeyValueSerializationSchema),它基于Flink的TypeInformation创建一个模式。如果数据都是由Flink写入和读取的,这很有用。该模式是其他通用序列化方法的一个性能强大的Flink特有的替代方案。


<2> JsonDeserializationSchema(和JSONKeyValueDeserializationSchema)将序列化的JSON转换为ObjectNode对象,可以使用objectNode.get(“field”)as(Int / String / ...)()从中访问这些字段。 KeyValue objectNode包含一个包含所有字段的“键”和“值”字段,以及一个可选的“元数据”字段,用于显示此消息的偏移/分区/主题。


Kafka 消费者和容错


使用Flink的检查点(checkpointing)功能,Flink Kafka消费者将消耗主题记录,并以一致的方式定期检查其所有Kafka偏移量(offsets)以及其他操作的状态(state)。在作业失败的情况下,Flink将将流程序恢复到最新检查点的状态,并从存储在检查点中的偏移量开始重新从Kafka记录。


因此,绘图检查点的间隔定义了在发生故障的情况下,程序可能需要多少回退。


要使用kafka消费者容错机制,需要在执行环境中启用拓扑的检查点:


<Java代码>


StreamExecutionEnvironment enV = StreamExecutionEnvironment.getExecutionEnvironment();

env.enableCheckpointing(5000); //检查点每5000毫秒


另请注意,如果有足够的slots可用于重新启动拓扑,Flink只能重新启动拓扑。因此,如果拓扑失败,由于任务管理器的丢失,必须之后仍然有足够的slots可用。 YARN上的Flink支持自动重新启动丢失的YARN容器。


如果未启用检查点,则Kafka消费者将定期向Zookeeper提交偏移量(在0.9+之后的版本,kafka集群自己可以管理消费组实际消费偏移量)。


Kafka消费者和时间戳(Timestamp)提取/水印(Watermark)排放


在许多情况下,记录的时间戳被嵌入(显式或隐式)在记录本身。此外,用户可能想要周期地或以不规则的方式发射水印,例如,基于包含当前事件时间水印的Kafka流中的特殊记录。对于这些情况,Flink Kafka Consumer允许指定AssignerWithPeriodic水印或AssignerWithPunctuatedWatermarks。


您可以按照此处指定自定义时间戳提取器/水印发射器,或者使用预定义时间戳提取器/水印发射器。这样做后,您可以通过以下方式将其传递给您的消费者:


<Java代码>


Properties properties= new Properties();

properties.setProperty(“bootstrap.servers”,“localhost:9092”);

//仅需要Kafka 0.8

properties.setProperty(“zookeeper.connect”,“localhost:2181”);

properties.setProperty(“group.id”,“test”);


FlinkKafkaConsumer08 <String> myConsumer =

    new FlinkKafkaConsumer08 <>(“topic”,new SimpleStringSchema(),properties);

myConsumer.assignTimestampsAndWatermarks(new CustomWatermarkEmitter());


DataStream <String> stream = env

.addSource(myConsumer)

.print();


在内部,每个Kafka分区执行一个分配器的实例。当指定了这样一个分配器时,对于从Kafka读取的每个记录,将调用extractTimestamp(T element,long previousElementTimestamp)为记录分配时间戳,并为水印getCurrentWatermark()(用于周期性的)或Watermark checkAndGetNextWatermark(T lastElement,long extractTimestamp)(用于标点符号)来确定是否应发出新的水印以及哪个时间戳。


Kafka 生产者


Flink的Kafka生产者称为FlinkKafkaProducer08(或Kafka 0.9.0.x版本为09)等。它允许将一串记录写入一个或多个Kafka主题。


例:


Java,Kafka 0.10+


DataStream<String> stream = ...;FlinkKafkaProducer010Configuration myProducerConfig = FlinkKafkaProducer010.writeToKafkaWithTimestamps(
        stream,                     // input stream
        "my-topic",                 // target topic
        new SimpleStringSchema(),   // serialization schema
        properties);                // custom configuration for KafkaProducer (including broker list)// the following is necessary for at-least-once delivery guaranteemyProducerConfig.setLogFailuresOnly(false);   // "false" by defaultmyProducerConfig.setFlushOnCheckpoint(true);  // "false" by default


上述示例演示了创建Flink Kafka Producer以将流写入单个Kafka目标主题的基本用法。对于更高级的用法,还有其他构造函数变体允许提供以下内容:


<1> 提供自定义属性:生产者允许为内部KafkaProducer提供自定义属性配置。有关如何配置卡夫卡生产者的详细信息,请参阅Apache Kafka文档。

<2> 自定义分区器:要将记录分配给特定分区,可以向构造函数提供KafkaPartitioner的实现。将为流中的每个记录调用此分区器,以确定记录将被发送到哪个精确分区。

<3> 高级序列化模式:与消费者类似,生产者还允许使用名为KeyedSerializationSchema的高级序列化模式,该模式允许分别对密钥和值进行序列化。它还允许覆盖目标主题,以便一个生产者实例可以将数据发送到多个主题。


Kafka生产者和容错


使用Flink的检查点功能,Flink Kafka Producer可以提供至少一次传送保证。


除了启用Flink的检查点之外,还应该适当地配置setLogFailuresOnly(boolean)和setFlushOnCheckpoint(boolean)的setter方法,如上一节中的上述示例所示:


<1> setLogFailuresOnly(boolean):启用此功能将使生产者仅记录失败,而不是捕获和重新抛出它们。这基本上记录了成功的记录,即使它没有写到目标卡夫卡话题。这必须至少禁用一次。

<2> setFlushOnCheckpoint(boolean):启用此功能后,Flink的检查点将在检查点之前等待Kafka确认之前的任何即时记录,然后再检查点。这样可以确保检查点之前的所有记录都已写入Kafka。这必须至少启用一次。

注意:默认情况下,重试次数设置为“0”。这意味着当setLogFailuresOnly设置为false时,生产者立即失败,包括领导更改。该值默认设置为“0”,以避免由重试引起的目标主题中的重复消息。对于大多数经纪人更改的生产环境,我们建议将重试次数设置为更高的值。


注意:目前没有Kafka的交易生产商,所以Flink不能保证一次交付到Kafka主题。


在Kafka 0.10中使用Kafka时间戳和Flink事件时间


自从Apache Kafka 0.10+以来,Kafka的消息可以携带时间戳,指示事件发生的时间(请参阅Apache Flink中的“事件时间”)或消息已写入Kafka代理的时间。


如果Flink中的时间特性设置为TimeCharacteristic.EventTime(StreamExecutionEnvironment.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)),则FlinkKafkaConsumer010将发送带有时间戳的记录。


卡夫卡消费者不会发出水印。为了发出水印,可以使用使用assignTimestampsAndWatermarks方法的“Kafka消费者和时间戳提取/水印排放”中所述的相同机制。


在使用Kafka的时间戳记时,不需要定义时间戳提取器。 extractTimestamp()方法的previousElementTimestamp参数包含Kafka消息携带的时间戳。


Kafka消费者的时间戳提取器将如下所示:


public long extractTimestamp(Long element, long previousElementTimestamp) {
    return previousElementTimestamp;}


如果设置了setWriteTimestampToKafka(true),FlinkKafkaProducer010只会发出记录时间戳。


FlinkKafkaProducer010.FlinkKafkaProducer010Configuration config = FlinkKafkaProducer010.writeToKafkaWithTimestamps(streamWithTimestamps,topic,new SimpleStringSchema(),standardProps);

config.setWriteTimestampToKafka(true);


Kafka连接器指标


Flink的Kafka连接器通过Flink的度量系统提供了一些指标来分析连接器的行为。生产商通过Flink的度量系统为所有支持的版本导出Kafka的内部度量。消费者从Kafka 0.9版开始导出所有指标。 Kafka文档列出了其文档中的所有导出指标。


除了这些指标之外,所有消费者都会显示每个主题分区的当前偏移量和承诺偏移量。 current-offsets是指分区中当前的偏移量。这是指我们检索并发射成功的最后一个元素的偏移量。承诺偏移量是最后一次提交的偏移量。


Flafink的Kafka消费者将补偿返回给Zookeeper(Kafka 0.8)或Kafka经纪人(Kafka 0.9+)。如果禁用了检查点,则定期提交偏移量。通过检查点,一旦流媒体拓扑结构中的所有运算符都已经确认他们已经创建了状态的检查点,则提交发生。这为用户提供至少一次语义用于提交给Zookeer或代理的偏移量。对于检查点到Flink的偏移量,系统提供了一次保证。


致力于ZK或经纪人的抵销也可用于跟踪卡夫卡消费者的阅读进度。每个分区中的承诺偏移量和最近的偏移量之间的差异称为消费者滞后。如果Flink拓扑结构正在消耗数据比新增数据慢的数据,滞后将会增加,消费者将落后。对于大型生产部署,我们建议监控该度量值,以避免延迟。


启用Kerberos身份验证(仅适用于0.9及更高版本)


Flink通过Kafka连接器提供一流的支持,以验证配置为Kerberos的Kafka安装。简单地在Flink-conf.yaml中配置Flink来启用Kafka的Kerberos身份验证:


通过设置以下内容配置Kerberos凭据 - 

security.kerberos.login.use-ticket-cache:默认情况下,Flink将尝试在由kinit管理的票据缓存中使用Kerberos凭据。请注意,在YARN上部署的Flink作业中使用Kafka连接器时,使用票证缓存的Kerberos授权将无法正常工作。使用Mesos进行部署也是如此,因为Mesos部署不支持使用ticket cache的授权。

security.kerberos.login.keytab和security.kerberos.login.principal:要使用Kerberos keytabs,请为这两个属性设置值。

将KafkaClient附加到security.kerberos.login.contexts中:这将告诉Flink将配置的Kerberos凭据提供给Kafka登录上下文以用于Kafka身份验证。

一旦启用基于Kerberos的Flink安全性,您可以使用Flink Kafka Consumer或Producer通过在提供的属性配置中将以下两个设置包含在传递给内部Kafka客户端的情况下,来验证Kafka:


将security.protocol设置为SASL_PLAINTEXT(默认为NONE):用于与Kafka经纪人沟通的协议。当使用独立的Flink部署时,还可以使用SASL_SSL;请参阅如何在此配置Kafka客户端的SSL。

将sasl.kerberos.service.name设置为kafka(默认kafka):此值应与用于Kafka代理配置的sasl.kerberos.service.name匹配。客户端和服务器配置之间的服务名称不匹配将导致身份验证失败。

有关Kerberos安全性的Flink配置的更多信息,请参见此处。您还可以在这里进一步了解Flink如何内部设置基于Kerberos的安全性。




在最后,加上一个简单的例子,或许对大家的开发没有任何作用,但也希望对一些初学者有一定的参考价值。


package cn.xfhuang.flink;


import java.util.Properties;


import org.apache.flink.streaming.api.datastream.DataStream;

import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import org.apache.flink.streaming.api.transformations.StreamTransformation;

import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010;

import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer010;

import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer010.FlinkKafkaProducer010Configuration;

import org.apache.flink.streaming.util.serialization.SimpleStringSchema;


public class KafkaSourceSinkSample {

public static void KafkaProducerSample(){

Properties properties = new Properties();

properties.setProperty("bootstrap.servers", "localhost:9092");

properties.setProperty("group.id", "test");

DataStream<String> dataStream = null;

StreamTransformation<String> streamTrans = null;

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

dataStream = new DataStream<String>(env,streamTrans); 

FlinkKafkaProducer010Configuration<String> myProducerConfig = FlinkKafkaProducer010.writeToKafkaWithTimestamps(

dataStream,                 // input stream

       "my-topic",                 // target topic

       new SimpleStringSchema(),   // serialization schema

       properties);                // custom configuration for KafkaProducer (including broker list)


// the following is necessary for at-least-once delivery guarantee

myProducerConfig.setLogFailuresOnly(false);   

myProducerConfig.setFlushOnCheckpoint(true);  

}

public static DataStream<String> KafkaConsumerSample(){

DataStream<String> stream = null;

 Properties properties = new Properties();

 properties.setProperty("bootstrap.servers", "localhost:9092");

 properties.setProperty("group.id", "test");

 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

 env.enableCheckpointing(5000); //get checkpoint as interval 5000 ms


 stream = env

 .addSource(new FlinkKafkaConsumer010<>("topic", new SimpleStringSchema(), properties));

 return stream;

}

public static void main(String[] args){

KafkaProducerSample();

DataStream<String> stream = KafkaConsumerSample();

        stream.print(); //standard print

}

}