web-dev-qa-db-ja.com

Kafka __consumer_offsetsトピックからの読み方

私は、現在の高レベル消費者がどのオフセットに取り組んでいるかを見つけようとしています。 Kafka 0.8.2.1、no "offset.storage"をKafka-which、私は、オフセットがKafkaに保存されることを意味すると思います(Zkシェルでこのパスをチェックすることで、Zookeeperにオフセットが保存されていないことも確認しました:/consumers/consumer_group_name/offsets/topic_name/partition_number

私は__consumer_offsetsどのコンシューマがオフセットの値を保存するかを確認するトピックですが、機能しませんでした...

私は次を試しました:

次のようにコンソールコンシューマ用の設定ファイルを作成しました。

=> more kafka_offset_consumer.config 

 exclude.internal.topics=false

コンソールコンシューマスクリプトの2つのバージョンを試しました。

#1:
bin/kafka-console-consumer.sh --consumer.config kafka_offset_consumer.config --topic __consumer_offsets --zookeeper localhost:2181

#2
./bin/kafka-simple-consumer-Shell.sh --topic __consumer_offsets --partition 0 --broker-list localhost:9092 --formatter "kafka.server.OffsetManager\$OffsetsMessageFormatter" --consumer.config kafka_offset_consumer.config

どちらも機能しませんでした-消費者が積極的にオフセットを消費/保存していても、そこに座っているだけで何も印刷しません。

他の設定/プロパティがありませんか?

ありがとう!

マリーナ

21
Marina

__ consumer_offsetsトピックからも消費しようとすると、この質問に出会いました。私は異なるKafka=バージョンについてそれを理解することができ、見つけたものを共有すると思った

Kafka 0.8.2.x

:これはZookeeper接続を使用します

#Create consumer config
echo "exclude.internal.topics=false" > /tmp/consumer.config
#Consume all offsets
./kafka-console-consumer.sh --consumer.config /tmp/consumer.config \
--formatter "kafka.server.OffsetManager\$OffsetsMessageFormatter" \
--zookeeper localhost:2181 --topic __consumer_offsets --from-beginning

Kafka 0.9.x.xおよび0.10.x.x

#Create consumer config
echo "exclude.internal.topics=false" > /tmp/consumer.config
#Consume all offsets
./kafka-console-consumer.sh --new-consumer --consumer.config /tmp/consumer.config \
--formatter "kafka.coordinator.GroupMetadataManager\$OffsetsMessageFormatter" \
--bootstrap-server localhost:9092 --topic __consumer_offsets --from-beginning

0.11.x.x-2.xの場合

#Create consumer config
echo "exclude.internal.topics=false" > /tmp/consumer.config
#Consume all offsets
./kafka-console-consumer.sh --consumer.config /tmp/consumer.config \
--formatter "kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter" \
--bootstrap-server localhost:9092 --topic __consumer_offsets --from-beginning
49
Dayo

OK、私は問題が何であるかを理解しました。私のKafka=は実際にZookeeperをオフセットストレージとして使用していましたが、Kafka ...ではありませんでした。誤ったコンテンツ:

やっていた

ls  /consumers/consumer_group_name/offsets/topic_name/partition_number

そこには何も見えません代わりに、コンテンツを「取得」する必要がありました。これは、以下のように、消費者に対して正しいオフセットを表示しました。

get /consumers/consumer_group_name/offsets/topic_name/partition_number 
185530404
cZxid = 0x70789ad05
ctime = Mon Nov 23 17:49:46 GMT 2015
mZxid = 0x7216cdc5c
mtime = Thu Dec 03 20:18:57 GMT 2015
pZxid = 0x70789ad05
cversion = 0
dataVersion = 3537384
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0
4
Marina

Kafka 0.11、 (Scala)ソースコードはここにあります

Java変換、Consumerプロセスから)が必要な場合は、_ConsumerRecord<byte[], byte[]> consumerRecord_を取得するとしましょう。

  1. キーを取得し(キーが最初にnullでないか確認してください)、GroupMetadataManager.readMessageKey(consumerRecord.key)を使用します。それは異なる型を返す可能性があるので、if ( ... instanceof OffsetKey)をチェックしてからキャストすると、そこからさまざまな値を取得できます。

  2. オフセットのKafka=レコード値)を取得するには、String.valueOf(GroupMetadataManager.readOffsetMessageValue(consumerRecord.value))を使用できます

最小限のJava Scala=コードから翻訳された例...

_byte[] key = consumerRecord.key;
if (key != null) {
    Object o = GroupMetadataManager.readMessageKey(key);
    if (o != null && o instanceOf OffsetKey) {
        OffsetKey offsetKey = (OffsetKey) o;
        Object groupTopicPartition = offsetKey.key;
        byte[] value = consumerRecord.value;
        String formattedValue = String.valueOf(GroupMetadataManager.readOffsetMessageValue(value);
       // TODO: Print, store, or compute results with the new key and value 
    }
}
_

これらの生のメッセージを消費するのではなく、AdminClient APIを使用してグループを記述することもできます。


Scalaソースコードの抽出

_def writeTo(consumerRecord: ConsumerRecord[Array[Byte], Array[Byte]], output: PrintStream) {
  Option(consumerRecord.key).map(key => GroupMetadataManager.readMessageKey(ByteBuffer.wrap(key))).foreach {
    // Only print if the message is an offset record.
    // We ignore the timestamp of the message because GroupMetadataMessage has its own timestamp.
    case offsetKey: OffsetKey =>
      val groupTopicPartition = offsetKey.key
      val value = consumerRecord.value
      val formattedValue =
        if (value == null) "NULL"
        else GroupMetadataManager.readOffsetMessageValue(ByteBuffer.wrap(value)).toString
      output.write(groupTopicPartition.toString.getBytes(StandardCharsets.UTF_8))
      output.write("::".getBytes(StandardCharsets.UTF_8))
      output.write(formattedValue.getBytes(StandardCharsets.UTF_8))
      output.write("\n".getBytes(StandardCharsets.UTF_8))
    case _ => // no-op
  }
_
4
cricket_007

--from-beginningを追加すると、少なくともいくつかの結果が得られるはずです。少なくとも、私が試したときはそうでした。また、その引数を指定せずに、そのコンシューマーがリッスンしている間にさらにメッセージを読み取る(およびオフセットコミットをトリガーする)場合、そこにメッセージを表示する必要があります。

3

Kafka-2.Xの場合、以下のコマンドを使用します

kafka-console-consumer --bootstrap-server localhost:9092 --topic __consumer_offsets --formatter "kafka.coordinator.group.GroupMetadataManager$OffsetsMessageFormatter"

0
Nitin Gupta