web-dev-qa-db-ja.com

Kafkaストリーム-ステートストアが別のインスタンスに移行された可能性があります

Kafka Streamsのインタラクティブクエリ機能をテストするための基本的なアプリケーションを作成しています。コードは次のとおりです。

public static void main(String [] args){

    StreamsBuilder builder = new StreamsBuilder();

    KeyValueBytesStoreSupplier waypointsStoreSupplier = Stores.persistentKeyValueStore("test-store");
    StoreBuilder waypointsStoreBuilder = Stores.keyValueStoreBuilder(waypointsStoreSupplier, Serdes.ByteArray(), Serdes.Integer());

    final KStream<byte[], byte[]> waypointsStream = builder.stream("sample1");

    final KStream<byte[], TruckDriverWaypoint> waypointsDeserialized =  waypointsStream
                                                                        .mapValues(CustomSerdes::deserializeTruckDriverWaypoint)
                                                                        .filter((k,v) -> v.isPresent())
                                                                        .mapValues(Optional::get);

    waypointsDeserialized.groupByKey().aggregate(
            () -> 1,
            (aggKey, newWaypoint, aggValue) -> {

                aggValue = aggValue + 1;
                return aggValue;

            }, Materialized.<byte[], Integer, KeyValueStore<Bytes, byte[]>>as("test-store").withKeySerde(Serdes.ByteArray()).withValueSerde(Serdes.Integer())
    );

    final KafkaStreams streams = new KafkaStreams(builder.build(), new StreamsConfig(createStreamsProperties()));

    streams.cleanUp();
    streams.start();    

    ReadOnlyKeyValueStore<byte[], Integer> keyValueStore = streams.store("test-store", QueryableStoreTypes.keyValueStore());

    KeyValueIterator<byte[], Integer> range = keyValueStore.all();
    while (range.hasNext()) {
        KeyValue<byte[], Integer> next = range.next();
        System.out.println(next.value);

    }

    Runtime.getRuntime().addShutdownHook(new Thread(streams::close));

}


protected static Properties createStreamsProperties() {

    final Properties streamsConfiguration = new Properties();

    streamsConfiguration.put(StreamsConfig.APPLICATION_ID_CONFIG, "random167");
    streamsConfiguration.put(StreamsConfig.CLIENT_ID_CONFIG, "client-id");
    streamsConfiguration.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
    streamsConfiguration.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
    streamsConfiguration.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, Serdes.String().getClass().getName());
    streamsConfiguration.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, Serdes.Integer().getClass().getName());
    //streamsConfiguration.put(StreamsConfig.COMMIT_INTERVAL_MS_CONFIG, 10000);

    return streamsConfiguration;
}

だから私の問題は、これを実行するたびにこれと同じエラーが発生することです:

Exception in thread "main" org.Apache.kafka.streams.errors.InvalidStateStoreException: the state store, test-store, may have migrated to another instance.

アプリケーションのインスタンスを1つだけ実行していて、消費しているトピックにはパーティションが1つしかありません。

私が間違っていることについて何か考えはありますか?

8
Anouer Hermassi

競合状態になっているようです。 kafkaは、KafkaStreams::start()のjavadocをストリームします。

すべてのスレッドを開始して、KafkaStreamsインスタンスを開始します。この関数は、クライアントのライフサイクル中に一度だけ呼び出されることが期待されています。スレッドはバックグラウンドで開始されるため、このメソッドはブロックしません。

https://kafka.Apache.org/10/javadoc/index.html?org/Apache/kafka/streams/KafkaStreams.html

streams.store()の直後にstreams.start()を呼び出していますが、まだ完全に初期化されていない状態になっていると思います。

これはテスト用のコードのようですので、そこにThread.sleep(5000)などを追加して試してみてください。 (これは本番環境のソリューションではありません)トピックへの入力率によっては、ストアがイベントでいっぱいになり始めるのに少し時間がかかるため、KeyValueIteratorに実際に処理するものがあります/ print。

11
Kyle Fransham

おそらくOPには適用されませんが、他の人を助けるかもしれません:

KTableのストアを取得しようとするときは、KTableのトピックが最初に存在することを確認してください。存在しない場合、この例外が発生します。

2
Ghurdyl

ストアを消費する前にStorebuilderを呼び出せませんでした。

0
promoth kumar