Flink流连接器之Kafka【三】【事件时间与水印、分区计划、容错、Kerberos身份验证】

您所在的位置:网站首页 kafka消费指定时间戳之后的数据 Flink流连接器之Kafka【三】【事件时间与水印、分区计划、容错、Kerberos身份验证】

Flink流连接器之Kafka【三】【事件时间与水印、分区计划、容错、Kerberos身份验证】

2023-08-05 13:50| 来源: 网络整理| 查看: 265

一.Kafka使用者和时间戳提取/水印发射

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

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

val properties = new Properties() properties.setProperty("bootstrap.servers" , "master:9092,slave01:9092,slave02:9092") properties.setProperty("group.id" , "spark") properties.setProperty("enable.auto.commit" , "true") properties.setProperty("auto.commit.interval.ms" ,"5000") /** * 配置下次重新消费的话,从哪里开始消费: * latest:从上一次提交的offset位置开始的 * earlist:从头开始进行(重复消费数据) */ properties.setProperty("auto.offset.reset" , "latest") // 配置序列化和反序列化 properties.setProperty("key.deserializer" , "org.apache.kafka.common.serialization.StringDeserializer") properties.setProperty("value.deserializer" , "org.apache.kafka.common.serialization.StringDeserializer") //获取数据源 kafka val consumer : FlinkKafkaConsumer09[String] = new FlinkKafkaConsumer09[String]( "spark", new SimpleStringSchema(), properties ) //consumer.assignTimestampsAndWatermarks(new CustomWatermarkEmitter()) // FlinkKafkaConsumer08中使用 val kafkaDataStream : DataStream[String] = env.addSource(consumer) // 添加flink的水印处理 , 允许得最大延迟时间是2S val watermarkDataStream = kafkaDataStream.assignTimestampsAndWatermarks(new AssignerWithPeriodicWatermarks[String] { var currentTimestamp: Long = 0L val maxDelayTime = 2000L var watermark: Watermark = _ // 获取当前的水印 override def getCurrentWatermark = { watermark = new Watermark(currentTimestamp - maxDelayTime) watermark } // 时间戳抽取操作 override def extractTimestamp(t: String, l: Long) = { val timeStamp = 0L currentTimestamp = Math.max(timeStamp, currentTimestamp) currentTimestamp } })

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

注意:如果水印分配器依靠从Kafka读取的记录来推进其水印(通常是这种情况),则所有主题和分区都需要具有连续的记录流。否则,整个应用程序的水印将无法使用,并且所有基于时间的操作(例如时间窗口或带有计时器的功能)都无法取得进展。单个空闲的Kafka分区会导致此行为。计划对Flink进行改进以防止这种情况的发生(请参阅FLINK-5479:FlinkKafkaConsumer中的按分区水印应考虑空闲分区)。同时,一种可能的解决方法是将心跳消息发送到所有消耗的分区,以提高空闲分区的水印。

二.Kafka Producer

Flink的Kafka Producer被调用FlinkKafkaProducer011(或010用于Kafka 0.10.0.x版本等,或仅FlinkKafkaProducer用于Kafka> = 1.0.0版本)。它允许将记录流写入一个或多个Kafka主题。

val stream: DataStream[String] = ... val myProducer = new FlinkKafkaProducer011[String]( "master:9092,slave01:9092,slave02:9092", // broker list "spark", // target topic new SimpleStringSchema) // serialization schema // versions 0.10+ allow attaching the records' event timestamp when writing them to Kafka; // this method is not available for earlier Kafka versions myProducer.setWriteTimestampToKafka(true) stream.addSink(myProducer)

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

提供自定义属性:生产者允许提供内部的自定义属性配置KafkaProducer。自定义分区程序:要将记录分配给特定的分区,可以为FlinkKafkaPartitioner构造函数提供一个实现。将为流中的每条记录调用此分区程序,以确定应将记录发送到目标主题的确切分区。高级序列化架构:类似于使用者,生产者还允许使用高级序列化架构KeyedSerializationSchema,该架构允许分别对键和值进行序列化。它还允许覆盖目标主题,以便一个生产者实例可以将数据发送到多个主题。 三.Kafka Producer分区计划

默认情况下,如果未为Flink Kafka Producer指定自定义分区程序,则生产者将使用一个FlinkFixedPartitioner将每个Flink Kafka Producer并行子任务映射到单个Kafka分区(即,接收器子任务接收到的所有记录都将以相同的结尾Kafka分区)。

可以通过扩展FlinkKafkaPartitioner类来实现自定义分区程序。所有Kafka版本的构造函数都允许在实例化生产者时提供自定义分区程序。请注意,分区器实现必须是可序列化的,因为它们将在Flink节点之间传输。另外,请记住,由于分区不属于生产者检查点状态的一部分,因此在作业失败时分区器中的任何状态都将丢失。

也可以完全避免使用某种分区程序,而只需让Kafka通过它们的附加键(使用提供的序列化模式为每条记录确定)对书面记录进行分区即可。为此,请在实例化生产者时提供自定义分区程序。提供null作为自定义分区很重要;如上所述,如果未指定自定义分区程序,FlinkFixedPartitioner则使用。

四.Kafka生产者与容错

Kafka 0.8 在0.9之前,Kafka没有提供任何机制来保证至少一次或完全一次语义。

Kafka 0.9和0.10 启用Flink的检查点后,FlinkKafkaProducer09和FlinkKafkaProducer010 可以提供至少一次的交付保证。

除了使用Flink的检查点,你还应该适当地配置setter方法setLogFailuresOnly(boolean)和setFlushOnCheckpoint(boolean)。

setLogFailuresOnly(boolean):默认情况下设置为false。启用此功能将使生产者仅记录故障,而不是捕获并重新抛出故障。这实际上说明了成功的记录,即使从未将其写入目标Kafka主题也是如此。必须至少一次禁用此功能。setFlushOnCheckpoint(boolean):默认情况下设置为true。启用此功能后,Flink的检查点将在Kafka确认检查点时等待所有即时记录,然后再执行检查点。这样可以确保将检查点之前的所有记录都写入Kafka。必须至少启用一次。

总之,0.9和0.10版本Kafka生产者在默认情况下具有-至少一次保证,与setLogFailureOnly设置为false和setFlushOnCheckpoint设置为true一样。

注意:默认情况下,重试次数设置为“ 0”。这意味着当setLogFailuresOnly设置为时false,生产者将立即因包括领导者变更在内的错误而失败。默认情况下,该值设置为“ 0”,以避免在目标主题中由重试引起的重复消息。对于大多数频繁更改代理的生产环境,建议将重试次数设置为较高的值。

注意:目前尚无Kafka的事务处理生产者,因此Flink无法保证一次准确地将消息发送到Kafka主题中。

Kafka 0.11及更高版本 启用Flink的检查点后,FlinkKafkaProducer011(FlinkKafkaProducer对于Kafka> = 1.0.0版本)可以提供一次准确的交付保证。

除了启用Flink的检查点之外,还可以通过将适当的semantic参数传递给FlinkKafkaProducer011(FlinkKafkaProducer对于Kafka> = 1.0.0版本)来选择三种不同的操作模式:

Semantic.NONE:Flink不能保证任何事情。产生的记录可能会丢失或可以重复。Semantic.AT_LEAST_ONCE(默认设置):类似于FlinkKafkaProducer010中的setFlushOnCheckpoint(true)。这样可以保证不会丢失任何记录(尽管可以重复记录)。Semantic.EXACTLY_ONCE:使用Kafka事务提供一次精确的语义。每当使用事务写入Kafka时,请不要忘记为使用Kafka记录的任何应用程序设置所需的设置:isolation.level(read_committed 或read_uncommitted-后者是默认值)。

注意事项 Semantic.EXACTLY_ONCE模式依赖于提交从所述检查点恢复之后在采取检查点之前启动的事务的能力。如果Flink应用程序崩溃到完成重启之间的时间大于Kafka的事务超时时间,则将丢失数据(Kafka将自动中止超过超时时间的事务)。请记住,请根据预期停机时间适当配置事务超时。

Kafka Producer默认transaction.max.timeout.ms设置为15分钟。此属性不允许为生产者设置大于其值的事务超时。 FlinkKafkaProducer011默认情况下,将transaction.timeout.ms生产者配置中的属性设置为1小时,因此transaction.max.timeout.ms在使用该Semantic.EXACTLY_ONCE模式之前应增加 该属性。

在KafkaConsumer的read_committed模式下,任何未完成(未中止或未完成)的事务将阻止所有未完成的事务从给定的Kafka主题进行的所有读取。换句话说,在以下事件序列之后:

用户transaction1使用它启动并写了一些记录用户开始transaction2使用它并写了一些进一步的记录用户提交 transaction2

即使来自transaction2的记录已经提交,在transaction1提交或中止之前,消费者也看不到它们。这有两个含义:

首先,在Flink应用程序的正常工作过程中,用户可以预期在Kafka主题中生成的记录的可见性延迟,该延迟等于完成检查点之间的平均时间。其次,在Flink应用程序失败的情况下,将阻止读者阅读此应用程序正在写入的主题,直到应用程序重新启动或经过配置的事务超时时间为止。仅适用于有多个代理/应用程序写入同一个Kafka主题的情况。 注意: Semantic.EXACTLY_ONCE模式每个FlinkKafkaProducer011实例使用一个固定大小的KafkaProducers池。每个检查点都使用其中一个生产者。如果并发检查点的数量超过池大小,FlinkKafkaProducer011 将引发异常,并使整个应用程序失败。请相应地配置最大池大小和最大并发检查点数。

注意:请Semantic.EXACTLY_ONCE采取一切可能的措施,以免留下任何为处理的transactions,而这将有必要阻止消费者继续阅读Kafka主题。但是,如果Flink应用程序在第一个检查点之前失败,则在重新启动此类应用程序后,系统中将不会包含有关先前池大小的信息。因此,FlinkKafkaProducer011.SAFE_SCALE_DOWN_FACTOR在第一个检查点完成之前按比例缩小大于Flink的比例来缩小Flink应用程序是不安全的。

五.Kafka 0.10+中使用Kafka时间戳和Flink事件时间

从Apache Kafka 0.10+开始,Kafka的消息可以带有时间戳,指示事件发生的时间或消息已被写入Kafka代理的时间。

在FlinkKafkaConsumer010将消费带有时间戳的记录,如果在Flink时间特性被设定为TimeCharacteristic.EventTime(StreamExecutionEnvironment.setStreamTimeCharacteristic(TimeCharacteristic.EventTime))。

Kafka使用者不会发出水印。为了发出水印,适用与上述使用该assignTimestampsAndWatermarks方法的“Kafka消费者和时间戳提取/水印发射”中所述的相同机制。

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

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

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

该FlinkKafkaProducer010只发出了纪录的时间戳,使用setWriteTimestampToKafka(true)设置。

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和committed-offsets。current-offsets是指当前分区中的偏移量。这是指我们成功检索并发出的最后一个元素的偏移量。committed-offsets是最后提交的偏移量。

Flink中的Kafka消费者将offsets提交给Zookeeper(Kafka 0.8)或Kafka broker(Kafka 0.9+)。如果禁用了检查点,则将定期提交偏移量。使用检查点时,一旦流拓扑中的所有操作都确认已创建其状态的检查点,就会进行提交。这为用户提供了至少一次提交给Zookeeper或代理的偏移量的语义。对于指向Flink的偏移量,系统仅提供一次保证。

提交给ZK或代理的偏移量也可以用于跟踪Kafka消费者的读取进度。每个分区中提交的偏移量和最新偏移量之间的差称为使用者延迟。如果Flink拓扑使用主题的数据的速度比添加新数据的速度慢,则延迟将增加,并且消费方将落后。对于大型生产部署,我们建议监视该指标以避免增加延迟。

七.启用Kerberos身份验证【仅适用于0.9+及更高版本】

Flink通过Kafka连接器提供一流的支持,以验证为Kerberos配置的Kafka安装。只需配置Flink flink-conf.yaml即可为Kafka启用Kerberos身份验证,如下所示: 1.通过设置以下内容配置Kerberos凭据:

security.kerberos.login.use-ticket-cache:默认为true并且Flink将尝试在所管理的票证缓存中使用Kerberos凭据kinit。请注意,在YARN上部署的Flink作业中使用Kafka连接器时,使用票证缓存的Kerberos授权将不起作用。使用Mesos进行部署时也是如此,因为Mesos部署不支持使用票证缓存进行授权。security.kerberos.login.keytab和security.kerberos.login.principal:要改为使用Kerberos键表,请为这两个属性设置值。

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

一旦启用了基于Kerberos的Flink安全性,就可以通过Flink Kafka消费者或生产者向Kafka进行身份验证,只需在传递给内部Kafka客户端的提供的属性配置中简单地包含以下两个设置即可:

设置security.protocol为SASL_PLAINTEXT【默认NONE】:用于与Kafka代理进行通信的协议。使用独立的Flink部署时,也可以使用SASL_SSL;设置sasl.kerberos.service.name为kafka【默认kafka】:此值应与sasl.kerberos.service.name用于Kafka代理配置的值匹配。客户端和服务器配置之间的服务名称不匹配将导致身份验证失败。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3