flink の高度なバージョン以降、kafka データを使用する 1 つの方法は Datastream で、もう 1 つは tableApi です。
Shangguan.com Kafka | Apache Flink
カフカソース
kafka-client が組み込まれた flink と kafka に依存するコネクタを導入します。
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka</artifactId>
<version>1.16.2</version>
</dependency>
説明書
KafkaSource<String> source = KafkaSource.<String>builder()
.setBootstrapServers(brokers)
.setTopics("input-topic")
.setGroupId("my-group")
.setStartingOffsets(OffsetsInitializer.earliest())
.setValueOnlyDeserializer(new SimpleStringSchema())
.build();
env.fromSource(source, WatermarkStrategy.noWatermarks(), "Kafka Source");
とてもシンプルで一目瞭然。
トピックとパーティション
多个topic
KafkaSource.builder().setTopics("topic-a", "topic-b");
正则匹配多个topic
KafkaSource.builder().setTopicPattern("topic.*");
指定分区
final HashSet<TopicPartition> partitionSet = new HashSet<>(Arrays.asList(
new TopicPartition("topic-a", 0), // Partition 0 of topic "topic-a"
new TopicPartition("topic-b", 5))); // Partition 5 of topic "topic-b"
KafkaSource.builder().setPartitions(partitionSet);
逆シリアル化
import org.apache.kafka.common.serialization.StringDeserializer;
KafkaSource.<String>builder()
.setDeserializer(KafkaRecordDeserializationSchema.valueOnly(StringDeserializer.class));
実際には、インターフェイス DeserializationSchema の deserialize() メソッドを実装して、バイトを必要な型に変換します。
消費の原点
KafkaSource.builder()
// 从消费组提交的位点开始消费,不指定位点重置策略
.setStartingOffsets(OffsetsInitializer.committedOffsets())
// 从消费组提交的位点开始消费,如果提交位点不存在,使用最早位点
.setStartingOffsets(OffsetsInitializer.committedOffsets(OffsetResetStrategy.EARLIEST))
// 从时间戳大于等于指定时间戳(毫秒)的数据开始消费
.setStartingOffsets(OffsetsInitializer.timestamp(1657256176000L))
// 从最早位点开始消费
.setStartingOffsets(OffsetsInitializer.earliest())
// 从最末尾位点开始消费
.setStartingOffsets(OffsetsInitializer.latest());
有界/無界モード
Kafka ソースは、ストリーミング操作モードとバッチ操作モードの両方をサポートします。デフォルトでは、KafkaSource はストリーミング モードで実行するように設定されているため、Flink ジョブが失敗するかキャンセルされるまでジョブは停止しません。setBounded(OffsetsInitializer)
指定した停止オフセットを使用して、Kafka ソースをバッチ モードで実行できます 。すべてのパーティションが停止オフセットに達すると、Kafka ソースは終了します。
ストリーミング モードで実行する場合、 setUnbounded(OffsetsInitializer)
停止消費ポイントを指定することもでき、すべてのパーティションが指定された停止オフセットに達すると、Kafka Source は操作を終了します。
99%の人はこれを使用できないと推定されています。つまり、終了オフセット点を設定します。
その他のプロパティ
上記のプロパティに加えて、setProperties(Properties) および setProperty(String, String) を使用して、Kafka Source および Kafka Consumer の任意のプロパティを設定できます。KafkaSource には次の構成項目があります。
client.id.prefix
、Kafka Consumer に使用されるクライアント ID プレフィックスを指定しますpartition.discovery.interval.ms
、Kafka Source が新しいパーティションをチェックする時間間隔を定義します。以下の「動的パーティションチェック」セクションを参照してください。register.consumer.metrics
Kafka Consumer を Flink に登録するかどうかを指定するインジケーターcommit.offsets.on.checkpoint
チェックポイント中に消費サイトを Kafka ブローカーに送信するかどうかを指定することは 依然として役立ちます。
Kafka コンシューマーの構成については、 Apache Kafka のドキュメントを参照してください。
次の構成項目が指定されている場合でも、ビルダーはこれらの構成項目をオーバーライドすることに注意してください。
key.deserializer
常に ByteArrayDeserializer に設定しますvalue.deserializer
常に ByteArrayDeserializer に設定しますauto.offset.reset.strategy
OffsetsInitializer#getAutoOffsetResetStrategy() によってオーバーライドされますpartition.discovery.interval.ms
バッチモードでは -1 に上書きされます
動的パーティションチェック
Flink ジョブを再起動せずにトピックの拡張や新しいトピックの作成などのシナリオを処理するために、提供されたトピック/パーティション サブスクリプション モードで新しいパーティションを定期的にチェックするように Kafka ソースを構成できます。動的パーティションチェックを有効にするには、 partition.discovery.interval.ms
設定を負以外の値に設定します。
KafkaSource.builder()
.setProperty("partition.discovery.interval.ms", "10000"); // 每 10 秒检查一次新分区
パーティションチェック機能は デフォルトでは 有効になっていません 。この機能を有効にするには、パーティションのチェック間隔を明示的に設定する必要があります。
Kafkaの消費容量はパーティションに関係するため、消費容量が足りない場合は動的にパーティションを追加する必要があるため、これは拡張用です。
イベント時間とウォーターマーク
デフォルトでは、Kafka ソースは Kafka メッセージ内のタイムスタンプをイベント時間として使用します。独自のウォーターマーク戦略を定義して、メッセージからイベント時間を抽出し、ウォーターマークをダウンストリームに送信できます。
env.fromSource(kafkaSource, new CustomWatermarkStrategy(), "Kafka Source With Custom Watermark Strategy");
消費サイトの提出
Kafka ソースは、 Flink のチェックポイントのステータスが Kafka ブローカー上の送信場所と一致していることを保証するために、チェックポイントが完了したときに現在の消費場所を送信します。チェックポイントが有効になっていない場合、Kafka ソースは、Kafka コンシューマーの内部サイト タイミング自動送信ロジックに依存します。自動送信機能は、 と 2 つの enable.auto.commit
Kafka コンシューマー構成アイテムによってauto.commit.interval.ms
構成されます。
注: Kafka ソースは、 失敗したジョブを回復するためにブローカー上のコミット サイトに依存しません。送信サイトは、ブローカー側で監視するために、Kafka コンシューマーおよびコンシューマー グループの消費の進行状況をレポートするためにのみ使用されます。
ここでは、消費オフセットがkafkaとflinkのどちらで管理されるかについて説明します。
例えば
.setProperty("enable.auto.commit","true") .setProperty(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG,"100")
そして、envにはenv.enableCheckpoint()がありません
このとき、メッセージが flink に入っていれば、メッセージが処理されたか失敗したかに関係なく、100ms 後に消費されたとみなされ、オフセットは +1 されます。
ただし、env.enableCheckpoint() を実行すると、チェックポイントが送信される前にオフセットが送信されます。チェックポイントと密接に関係しています。チェックポイントが失敗すると、オフセットは送信されません。
Kafka セキュリティ認定
KafkaSource.builder()
.setProperty("security.protocol", "SASL_PLAINTEXT")
.setProperty("sasl.mechanism", "PLAIN")
.setProperty("sasl.jaas.config", "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"username\" password=\"password\";");
上記の方がよく使われます
もう 1 つのより複雑な例では、セキュリティ プロトコルとして SASL_SSL を使用し、SASL メカニズムとして SCRAM-SHA-256 を使用しています。
KafkaSource.builder()
.setProperty("security.protocol", "SASL_SSL")
// SSL 配置
// 配置服务端提供的 truststore (CA 证书) 的路径
.setProperty("ssl.truststore.location", "/path/to/kafka.client.truststore.jks")
.setProperty("ssl.truststore.password", "test1234")
// 如果要求客户端认证,则需要配置 keystore (私钥) 的路径
.setProperty("ssl.keystore.location", "/path/to/kafka.client.keystore.jks")
.setProperty("ssl.keystore.password", "test1234")
// SASL 配置
// 将 SASL 机制配置为 as SCRAM-SHA-256
.setProperty("sasl.mechanism", "SCRAM-SHA-256")
// 配置 JAAS
.setProperty("sasl.jaas.config", "org.apache.kafka.common.security.scram.ScramLoginModule required username=\"username\" password=\"password\";");
Kafkaクライアントが依存するクラスパスをジョブJAR内で再設定(クラスの再配置)した場合、ログインモジュール(ログインモジュール)のクラスパスが異なる可能性がありますので、実際のクラスパスに合わせて上記の設定を書き換えてください。 JAR 内のログイン モジュール。
カフカシンク
KafkaSink
データ ストリームは 1 つ以上の Kafka トピックに書き込むことができます。
説明書
DataStream<String> stream = ...;
KafkaSink<String> sink = KafkaSink.<String>builder()
.setBootstrapServers(brokers)
.setRecordSerializer(KafkaRecordSerializationSchema.builder()
.setTopic("topic-name")
.setValueSerializationSchema(new SimpleStringSchema())
.build()
)
.setDeliveryGuarantee(DeliveryGuarantee.AT_LEAST_ONCE)
.build();
stream.sinkTo(sink);
KafkaSink をビルドするときは、次のプロパティを指定する必要があります。
- ブートストラップサーバー、
setBootstrapServers(String)
- メッセージシリアライザー(Serializer)、
setRecordSerializer(KafkaRecordSerializationSchema)
- セマンティック保証を使用する場合は
DeliveryGuarantee.EXACTLY_ONCE
、次のようにする必要があります。setTransactionalIdPrefix(String)
シリアライザー
KafkaRecordSerializationSchema.builder()
.setTopicSelector((element) -> {<your-topic-selection-logic>})
.setValueSerializationSchema(new SimpleStringSchema())
.setKeySerializationSchema(new SimpleStringSchema())
.setPartitioner(new FlinkFixedPartitioner())
.build();
メッセージボディ(値)のシリアル化方法とトピックの選択方法を指定する必要があります。また、 Flink の代わりに Kafka が提供するシリアライザーをsetKafkaKeySerializer(Serializer)
または を通じて使用することもできます。setKafkaValueSerializer(Serializer)
耐障害性
KafkaSink
合計 3 つの異なるセマンティック保証がサポートされています ( DeliveryGuarantee
)。DeliveryGuarantee.AT_LEAST_ONCE
および の 場合 DeliveryGuarantee.EXACTLY_ONCE
、Flink チェックポイントを有効にする必要があります。デフォルトで KafkaSink
使用されます DeliveryGuarantee.NONE
。ここでは、さまざまなセマンティック保証について説明します。
Kerberos ベースの Flink セキュリティを有効にすると、提供されたプロパティ構成に次の 2 つの設定を含めるだけで (内部 Kafka クライアントに渡すことにより)、Flink Kafka Consumer またはProducer を使用して Kafka に対する認証を行うことができます。
DeliveryGuarantee.NONE
保証はありません。Kafka ブローカーが原因でメッセージが失われたり、Flink の障害によりメッセージが重複したりする可能性があります。DeliveryGuarantee.AT_LEAST_ONCE
: チェックポイント中、シンクは Kafka バッファー内のすべてのデータが Kafka プロデューサによって確認されるまで待機します。メッセージは、Kafka ブローカー側で発生するイベントによって失われることはありませんが、Flink が古いデータを再処理するため、Flink の再起動時に重複する可能性があります。DeliveryGuarantee.EXACTLY_ONCE
: このモードでは、Kafka シンクはチェックポイントで送信されたトランザクションを通じてすべてのデータを書き込みます。したがって、コンシューマーがコミットされたデータのみを読み取る場合 (「Kafka コンシューマー構成」を参照isolation.level
)、Flink の再起動時にデータの重複は発生しません。ただし、これによりデータはチェックポイントが完了した後にのみ表示されるため、必要に応じてチェックポイント間隔を調整してください。異なるジョブのトランザクションが相互に影響を与えないように、トランザクション ID のプレフィックス (transactionIdPrefix) が異なるアプリケーションで一意であることを確認してください。さらに、Kafka のトランザクション タイムアウトを最大チェックポイント間隔 + 最大再起動時間よりも大幅に大きく調整することを強くお勧めします。そうしないと、コミットされていないトランザクションの Kafka の期限切れによりデータ損失が発生します。-
Kerberos認証を有効にする
-
Flink は、Kerberos 構成の Kafka インストールを認証するために、Kafka コネクタを通じて最上級のサポートを提供します。で Flink を設定するだけです
flink-conf.yaml
。次のように Kafka の Kerberos 認証を有効にします。
1. 次のように設定して Kerberos チケットを構成します。 security.kerberos.login.use-ticket-cache
: デフォルトでは、この値はtrue
Flink がkinit
管理されたチケット キャッシュ内の Kerberos チケットを使用しようとすることを意味します。知らせ!YARN にデプロイされた Flink ジョブで Kafka コネクタを使用する場合、チケット キャッシュを使用した Kerberos 認証は機能しません。security.kerberos.login.keytab
およびsecurity.kerberos.login.principal
: Kerberos キータブを使用するには、これら 2 つのプロパティの値を設定します。
2. AppendKafkaClient
tosecurity.kerberos.login.contexts
: これは、構成された Kerberos チケットを Kafka 認証のために Kafka ログイン コンテキストに提供するように Flink に指示します。security.protocol
に設定されます (SASL_PLAINTEXT
デフォルトはNONE
): Kafka ブローカーとの通信に使用されるプロトコル。これは、スタンドアロンの Flink 展開を使用する場合にも機能しますSASL_SSL
。SSL用に Kafka クライアントを構成する方法については、こちらを参照してください。sasl.kerberos.service.name
に設定されます (kafka
デフォルトはkafka
): この値は、sasl.kerberos.service.name
Kafka ブローカー構成に使用される値と一致する必要があります。クライアントとサーバーの構成間でサービス名が一致しないと、認証が失敗します。
トラブルシューティング
データが失われた
Kafka の構成によっては、Kafka が書き込みを確認した後でもデータ損失が発生する可能性があります。特に、Kafka の構成で次のプロパティを設定することを忘れないでください。
acks
log.flush.interval.messages
log.flush.interval.ms
log.flush.*
UnknownTopicOrPartitionException
このエラーの考えられる原因の 1 つは、Kafka ブローカーの再起動後または再起動中など、新しいリーダーの選出が進行中であることです。これは再試行可能な例外であるため、Flink ジョブは再起動して通常の操作を再開できるはずです。これは、プロデューサ設定のプロパティを変更することによって回避することもできます retries
。ただし、これによりメッセージの順序が変更される可能性があり、 max.in.flight.requests.per.connection
これを 1 に設定することで回避できます。
プロデューサーフェンス例外
FlinkKafkaProducer
このエラーは、生成されたエラー transactional.id
と他のアプリケーションで使用されているエラーとの間の競合によって発生します 。ほとんどの場合、 FlinkKafkaProducer
生成された ID には taskName + "-" + operatorUid
すべてため、これらの競合するアプリケーションは、同じジョブ グラフの Flink ジョブも使用します。 この問題を解決するには、setTransactionalIdPrefix()
メソッドを使用してデフォルトの動作をオーバーライドし、異なるジョブに異なるプレフィックスを割り当てること ができます 。transactional.id