web-dev-qa-db-fra.com

Kafka comment lire le sujet __consumer_offsets

J'essaie de savoir ce qui compense mes consommateurs actuels de haut niveau. J'utilise Kafka 0.8.2.1, avec no "offset.storage" défini dans le server.properties de Kafka - ce qui, je pense, signifie que les décalages sont stockés dans Kafka. (J'ai également vérifié qu'aucun décalage n'était stocké dans Zookeeper en vérifiant ce chemin dans le shell Zk: /consumers/consumer_group_name/offsets/topic_name/partition_number)

J'ai essayé d'écouter la rubrique __consumer_offsets pour voir quel consommateur sauvegardait quelle valeur des offsets, mais cela n'a pas fonctionné ... 

J'ai essayé ce qui suit:

a créé un fichier de configuration pour le consommateur de console comme suit:

=> more kafka_offset_consumer.config 

 exclude.internal.topics=false

et essayé deux versions des scripts consommateurs de la console:

#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

Ni a fonctionné - il reste juste là mais n'imprime rien, même si les consommateurs consomment/économisent activement des compensations.

Me manque-t-il d'autres configurations/propriétés?

merci!

Marina

16
Marina

Je suis tombé sur cette question en essayant de consommer également à partir du __consumer_offsets topic .

Pour Kafka 0.8.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.server.OffsetManager\$OffsetsMessageFormatter" \
--zookeeper localhost:2181 --topic __consumer_offsets --from-beginning

Pour Kafka 0.9.x.x et 0.10.0.0

#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.GroupMetadataManager\$OffsetsMessageFormatter" \
--zookeeper localhost:2181 --topic __consumer_offsets --from-beginning

Pour 0.11.0.0

#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" \
--zookeeper localhost:2181 --topic __consumer_offsets --from-beginning
35
Dayo

Ok, j'ai compris quel était le problème. Mon Kafka utilisait réellement Zookeeper comme stockage offset, pas Kafka ... La raison pour laquelle je n'ai pas détecté cela tout de suite, c'est parce que je vérifiais le contenu de ZK de manière incorrecte:

Je faisais

ls  /consumers/consumer_group_name/offsets/topic_name/partition_number

et ne rien voir là-bas. Au lieu de cela, je devais «obtenir» du contenu - ce qui indiquait des corrections correctes pour mes consommateurs, comme celle ci-dessous:

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

Si vous ajoutez --from-beginning, vous devriez probablement obtenir des résultats, du moins lorsque je l'ai essayé moi-même. Et si vous ne fournissez pas cet argument, mais que vous lisez davantage de messages (et que vous déclenchez des commits de décalage) pendant que le consommateur écoute, cela devrait également afficher les messages.

3
Guillaume Poirier

Depuis Kafka 0.11, le code source (Scala) peut être trouvé ici

Pour ceux qui ont besoin d’une traduction Java, quel que soit le processus consommateur, supposons que vous obtenez un ConsumerRecord<byte[], byte[]> consumerRecord, et que vous pouvez utiliser 

  1. Obtenez la clé, (vérifiez si la clé n'est pas null d'abord) et utilisez GroupMetadataManager.readMessageKey(consumerRecord.key). Cela peut retourner différents types, alors vérifiez if ( ... instanceof OffsetKey), puis lancez-le et vous pouvez obtenir différentes valeurs à partir de cela. 

  2. Pour obtenir la valeur d'enregistrement Kafka des décalages, vous pouvez utiliser String.valueOf(GroupMetadataManager.readOffsetMessageValue(consumerRecord.value))

Un exemple Java minimal traduit du code 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 
    }
}

Notez qu'il est également possible d'utiliser les API AdminClient pour décrire des groupes plutôt que de consommer ces messages bruts. 


Extrait de code source 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
  }
1
cricket_007