背景
前の今日、我々は変換動作フィルタの別の古典的な使用を与える、オペレーティングマップカフカストリームにメッセージをご紹介します。まだ開発導入の具体例の組み合わせがあります。
デモ機能
所定のフィルタ処理フィルタまたは論理に従ってリアルタイムでメッセージごとBenpianフィルタの使用プレゼンテーション、すなわち。今日はメッセージ・フォーマットを使用し、トピックを入力し、次のとおりです。
{「名」:「ジョージ・RRマーティン」、「タイトル」:「氷と炎の歌」}
{「名前」:「CSルイス」、「タイトル」:「銀のいす」}
私たちは、名前が出力トピックに送信されたすべてのメッセージの「ジョージ・RRマーティン」でフィルタリングしていきます。
プロジェクトを初期化します
プロジェクトディレクトリを作成します。
mkdirフィルタストリーム
CDフィルタストリーム/
構成アイテム
次のように、ディレクトリフィルタストリームでbuild.gradleファイルを作成:
buildscript { リポジトリ{ jcenter() } の依存{ クラスパス'com.github.jengelman.gradle.plugins:影:4.0.2' } } プラグイン{ ID「Javaの ID "com.google.protob"バージョン"0.8.10" } プラグインの適用: 'com.github.johnrengelman.shadow' リポジトリ{ mavenCentral() jcenter() 達人{ URL 'http://packages.confluent.io/maven' } } グループ'huxihx.kafkastreams' = sourceCompatibilityを1.8 targetCompatibility = '1.8' バージョン= '0.0.1' 依存関係{ 実装'com.google.protobuf:いるProtobuf-javaの:3.0.0' 実装'org.slf4j:SLF4J -シンプル:1.7.26' 実装'org.apache.kafka:カフカストリーム:2.3.0' 実装「COM。 google.protobuf:いるProtobuf-javaの:3.9.1' testCompileグループ: 'JUnitの'、名前: 'JUnitの'バージョン'4.12' } いるProtobuf { generatedFilesBaseDir = "$ PROJECTDIR / SRC /" protoc { アーティファクト=「com.google .protobuf:protoc:3.0.0' } } ジャー{ マニフェスト{ 属性( 'クラスパス':configurations.compile.collect {it.getName()} .join(」「)、 「メインクラス」: 'huxihx.kafkastreams.FilteredStreamsApp " ) } } shadowJar { archiveName = "kstreams・変換・スタンドアロン- 。$ {バージョン} $ {拡張子}" }
その後のGradleラッパーパッケージをダウンロードするには、次のコマンドを実行します。
Gradleのラッパー
当社のコンフィギュレーション・ファイルのパラメータを保存するために、ムービーストリームディレクトリのフォルダに名前のコンフィギュレーションを作成した後:
mkdir設定
dev.propertiesのと呼ばれるファイルを作成します。
application.id =フィルタリングアプリの
bootstrap.servers = localhostを:9092input.topic.name =出版
input.topic.partitions = 1
input.topic.replication.factor = 1output.topic.name =フィルタ-出版
output.topic.partitions = 1output.topic.replication.factor = 1
メッセージのスキーマを作成します。
次のステップは、受信メッセージと送信メッセージのスキーマを作成することです。私達はちょうど今日のフィルタを行うため、同じ形式の入力と出力するので、あなただけのスキーマを作成することができます。まず、フィルタストリーム内のファイルコマンドは、スキーマを保存するフォルダを作成します。
ます。mkdir -pのsrc /メイン/プロト
次のように、publication.protoファイルを作成した後:
構文=「proto3」。
huxihx.kafkastreams.protoパッケージ。
メッセージ公開{
文字列名= 1。
文字列のタイトル= 2;
}
対応するJavaクラスをコンパイルするには、次のコマンドを実行するために、ファイルを保存した後:
./gradlewビルド
PublicationOuterClass:この時点では、SRC /メイン/ javaの/ huxihx / kafkastreams /プロトで生成されたJavaクラスを参照してくださいする必要があります。
SERDESを作成します
このステップのSERDESと同じの最後の記事なので、コードに直接行くことはありません。
ます。mkdir -pのsrc /メイン/ javaの/ huxihx / kafkastreams / SERDES
メインフローの開発
SRC /メイン/ javaの/ huxihx / kafkastreamsでFilteredStreamsApp.javaファイルの作成:
パッケージhuxihx.kafkastreams。 輸入huxihx.kafkastreams.proto.PublicationOuterClass。 輸入huxihx.kafkastreams.serdes.ProtobufSerdes。 輸入org.apache.kafka.clients.admin.AdminClient。 輸入org.apache.kafka.clients.admin.NewTopic; 輸入org.apache.kafka.common.serialization.Serde。 輸入org.apache.kafka.common.serialization.Serdes。 輸入org.apache.kafka.streams.KafkaStreams。 輸入org.apache.kafka.streams.StreamsBuilder。 輸入org.apache.kafka.streams.StreamsConfig; 輸入org.apache.kafka.streams.Topology。 輸入org.apache.kafka.streams.kstream.Consumed; 輸入org.apache.kafka.streams.kstream.Produced; 輸入java.io.FileInputStream; インポートにjava.io.IOException; 輸入はjava.util.ArrayList; 輸入java.util.HashMapを; 輸入はjava.util.List; 輸入java.util.Map; 輸入java.util.Properties; 輸入java.util.Set; 輸入java.util.concurrent.CountDownLatch。 パブリッククラスFilteredStreamsApp { プライベートプロパティbuildStreamsProperties(プロパティenvProps){ プロパティの小道具=新しいプロパティ(); props.put(StreamsConfig.APPLICATION_ID_CONFIG、envProps.getProperty( "application.id")); props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG、envProps.getProperty( "bootstrap.servers")); } props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG、Serdes.String()のgetClass()。)。 props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG、Serdes.String()のgetClass()。)。 小道具を返します。 プライベート無効preCreateTopics(プロパティenvPropsは)例外{スロー 地図<文字列、オブジェクト>設定=新しいHashMapを<>(); config.put( "bootstrap.servers"、envProps.getProperty( "bootstrap.servers")); (AdminClientクライアント= AdminClient.create(設定)){しようと 設定し、<文字列> existingTopics = client.listTopics()名()(取得)。。。 一覧<NewTopic>トピック=新しいArrayListを<>(); ストリングinputTopic = envProps.getProperty( "input.topic.name")。 (もし!existingTopics.contains(inputTopic)){ トピック。 Integer.parseInt(envProps.getProperty( "input.topic.partitions")) Short.parseShort(envProps。 } 列outputTopic = envProps.getProperty( "output.topic.name")。 (!existingTopics.contains(outputTopic)){もし topics.add(新しいNewTopic(outputTopic、 Integer.parseInt(envProps.getProperty( "output.topic.partitions"))、 Short.parseShort(envProps.getProperty(「output.topic .replication.factor ")))); } client.createTopics(トピック)。 試みる(FileInputStreamの入力=新しいFileInputStreamを(filePathに)){ envProps.load(入力)。 } envPropsを返します。 } プライベートトポロジbuildTopology(プロパティenvProps、最終Serde <PublicationOuterClass.Publication> publicationSerde){ 最終StreamsBuilderビルダー=新しいStreamsBuilder()。 最終列inputTopic = envProps.getProperty( "input.topic.name")。 最終列outputTopic = envProps.getProperty( "output.topic.name")。 builder.stream(inputTopic、Consumed.with(Serdes.String()、publicationSerde)) .filter((キー、出版物) - > "ジョージ・RRマーティン" .equals(publication.getName())) プロデュース.TO(outputTopic、 .with(Serdes.String()、publicationSerde))。 リターンbuilder.build(); } パブリック静的無効メイン(文字列[] args){例外をスロー (args.length <1){場合 (「環境設定ファイルを指定しなければなりません。」)新をスロー。 } FilteredStreamsAppアプリ=新しいFilteredStreamsApp()。 プロパティenvProps = app.loadEnvProperties(引数[0])。 プロパティstreamProps = app.buildStreamsProperties(envProps)。 app.preCreateTopics(envProps)。 トポロジトポロジ= app.buildTopology(envProps、新しいProtobufSerdes <>(PublicationOuterClass.Publication.parser()))。 Runtime.getRuntime()。addShutdownHook(新しいスレッド( "ストリーム-JVMシャットダウンフック"){ 最終KafkaStreamsは=新しいKafkaStreams(トポロジー、streamProps)をストリーム; 最終たCountDownLatchラッチ=新しいたCountDownLatch(1)。 @Override 公共ボイドラン(){ streams.close()。 latch.countDown(); } })。 {試みる streams.startを(); latch.await(); }キャッチ(例外e){ System.exitと(1)。 } でSystem.exit(0); } }
生産者と消費者筆記テスト
次のようにSRC /メイン/ javaの/ huxihx / kafkastreams /テスト/ TestProducer.javaとTestConsumer.javaで、内容は以下のとおりです。
パッケージhuxihx.kafkastreams.tests。 輸入huxihx.kafkastreams.proto.PublicationOuterClass。 輸入huxihx.kafkastreams.serdes.ProtobufSerializer。 輸入org.apache.kafka.clients.producer.KafkaProducer。 輸入org.apache.kafka.clients.producer.Producer。 輸入org.apache.kafka.clients.producer.ProducerRecord; 輸入java.util.Arrays。 輸入はjava.util.List; 輸入java.util.Properties; パブリッククラスTestProducer { //测试输入事件 プライベート静的最終一覧<PublicationOuterClass.Publication> TEST_PUBLICATIONS =は、Arrays.asList( PublicationOuterClass.Publication.newBuilder() .setName( "ジョージ・RRマーティン")。のsetTitle( "氷と炎の歌")。ビルド()、 PublicationOuterClass.Publication.newBuilder() .setName( "CSルイス")。のsetTitle( "銀のいす")。(ビルド)、 PublicationOuterClass.Publication.newBuilder() .setName( "CSルイス")。のsetTitle( "Perelandra" ).build()、 PublicationOuterClass.Publication.newBuilder() .setName( "ジョージ・RRマーティン")。のsetTitle( "ファイア&ブラッド")。ビルド()、 PublicationOuterClass.Publication.newBuilder() .setName( "JRRトールキン" ).setTitle( "ホビット")。(ビルド)、 PublicationOuterClass.Publication.newBuilder() .setName( "JRRトールキン")。のsetTitle() "ロードオブザリング"。ビルド()、 PublicationOuterClass.Publication.newBuilder() .setName( "ジョージ・RRマーティン")。のsetTitle( "春の夢")。、)(ビルド PublicationOuterClass.Publication.newBuilderを() .setName( "JRRトールキン")。のsetTitle( "旅の仲間") .build()、 PublicationOuterClass.Publication.newBuilder() .setName( "ジョージ・RRマーティン")のsetTitle( "アイスドラゴン")の構築())。。。 パブリック静的無効メイン(文字列[] args){ プロパティ小道具=新しいプロパティ(); props.put( "bootstrap.servers"、 "localhostを:9092"); 小道具。 props.put( "key.serializer"、 "org.apache.kafka.common.serialization.StringSerializer"); props.put( "value.serializer"、新ProtobufSerializer <PublicationOuterClass.Publication>()のgetClass()。); (最終生産<文字列、PublicationOuterClass.Publication>プロデューサー=新しいKafkaProducer <>(小道具)){試みる TEST_PUBLICATIONS.stream() .MAP( - >新しいProducerRecord <文字列、PublicationOuterClass.Publication>( "出版"、出版)出版) .forEach(プロデューサー::送ります)。 } } }
パッケージhuxihx.kafkastreams.tests。 輸入com.google.protobuf.Parser。 輸入huxihx.kafkastreams.proto.PublicationOuterClass。 輸入huxihx.kafkastreams.serdes.ProtobufDeserializer。 輸入org.apache.kafka.clients.consumer.ConsumerRecord; 輸入org.apache.kafka.clients.consumer.ConsumerRecords。 輸入org.apache.kafka.clients.consumer.KafkaConsumer; 輸入org.apache.kafka.common.serialization.Deserializer。 輸入org.apache.kafka.common.serialization.StringDeserializer。 輸入java.time.Duration。 輸入java.util.Arrays。 輸入java.util.HashMapを; 輸入java.util.Map; 輸入java.util.Properties; パブリッククラスTestConsumer { パブリック静的無効メイン(文字列[] args){ //为输出事件构造いるProtobufデシリアライザ デシリアライザ<PublicationOuterClass.Publication>デシリアライザ=新しいProtobufDeserializer <>(); 地図<文字列、パーサ<PublicationOuterClass.Publication >>設定=新しいHashMapの<>(); config.put( "パーサ"、PublicationOuterClass.Publication.parser()); deserializer.configure(設定、偽); プロパティの小道具=新しいプロパティ(); props.put( "bootstrap.servers"、 "localhostを:9092"); props.put( "group.id"、 "試験群")。 props.put( "enable.auto.commit"、 "真"); props.put(「auto.commit.interval。 KafkaConsumer <文字列、PublicationOuterClass.Publication>消費者=新しいKafkaConsumer <>(小道具、新しいStringDeserializer()、デシリアライザ)。 consumer.subscribe(は、Arrays.asList( "フィルタ-出版物")); 一方、(TRUE){ ConsumerRecords <文字列、PublicationOuterClass.Publication>レコード= consumer.poll(Duration.ofSeconds(1))。 (レコードConsumerRecord <文字列、PublicationOuterClass.Publication>レコード)のため System.out.printf(record.offset() "=%dを、キー=%sは、値=%S%nをオフセット"、record.key() 、record.value())。 } } }
テスト
まず、我々はプロジェクトをビルドするには、次のコマンドを実行します。
./gradlew shadowJar
カフカは、カフカストリーム適用後に実行し、クラスタを起動します。
ビルド/ libsに/ kstreams・変換・スタンドアロン-0.0.1.jar -jar javaの設定/ dev.properties
その後TestProducerはテストイベントを送信開始します。
ビルド/ libsに/ kstreams・変換・スタンドアロン-0.0.1.jar -cp javaのhuxihx.kafkastreams.tests.TestProducer
カフカストリーム検証が最後TestConsumerフィルター出版指定されたメッセージを開始します。
ビルド/ libsに/ kstreams・変換・スタンドアロン-0.0.1.jar -cp javaのhuxihx.kafkastreams.tests.TestConsumer
.......
オフセット= 0、キー= nullを、値=名:「ジョージ・RRマーティン」
タイトル:「氷と炎の歌」オフセット= 1、キー= nullを、値=名: "ジョージ・RRマーティン"
タイトル: "ファイア&ブラッド"オフセット= 2、キー= nullを、値=名:「ジョージ・RRマーティン」
タイトル:「春の夢」オフセット= 3、キー= nullを、値=名:「ジョージ・RRマーティン」
タイトル:「アイスドラゴン」
概要
次〜つまり、リアルタイムの値が主要なメッセージを変更し、再入力の使い方をご紹介