web-dev-qa-db-fra.com

Comment envoyer des messages volumineux avec Kafka (plus de 15 Mo)?

J'envoie des messages String à Kafka V. 0.8 à l'aide de l'API Java Producer. Si la taille du message est d'environ 15 Mo, je reçois un MessageSizeTooLargeException. J'ai essayé de définir message.max.bytesà 40 Mo, mais j'obtiens toujours l'exception. De petits messages ont fonctionné sans problèmes.

(L'exception apparaît dans le producteur, je n'ai pas de consommateur dans cette application.)

Que puis-je faire pour se débarrasser de cette exception?

Mon exemple producteur config

private ProducerConfig kafkaConfig() {
    Properties props = new Properties();
    props.put("metadata.broker.list", BROKERS);
    props.put("serializer.class", "kafka.serializer.StringEncoder");
    props.put("request.required.acks", "1");
    props.put("message.max.bytes", "" + 1024 * 1024 * 40);
    return new ProducerConfig(props);
}

Journal d'erreur:

4709 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with correlation id 214 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
4869 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with    correlation id 217 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5035 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with   correlation id 220 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5198 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with correlation id 223 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5305 [main] ERROR kafka.producer.async.DefaultEventHandler  - Failed to send requests for topics datasift with correlation ids in [213,224]

kafka.common.FailedToSendMessageException: Failed to send messages after 3 tries.
at kafka.producer.async.DefaultEventHandler.handle(Unknown Source)
at kafka.producer.Producer.send(Unknown Source)
at kafka.javaapi.producer.Producer.send(Unknown Source)
90
Sonson123

Vous devez ajuster trois (ou quatre) propriétés:

  • Côté consommateur: fetch.message.max.bytes - ceci déterminera la plus grande taille d'un message pouvant être récupéré par le consommateur.
  • Côté courtier: replica.fetch.max.bytes - cela permettra aux réplicas des courtiers d'envoyer des messages dans le cluster et de s'assurer que les messages sont répliqués correctement. S'il est trop petit, le message ne sera jamais répliqué et le consommateur ne le verra jamais car le message ne sera jamais validé (entièrement répliqué).
  • Côté courtier: message.max.bytes - il s’agit de la taille la plus grande du message pouvant être reçu par le courtier par un producteur.
  • Côté courtier (par sujet): max.message.bytes - il s’agit de la plus grande taille du message que le courtier autorisera à être ajouté au sujet. Cette taille est validée en pré-compression. (La valeur par défaut est message.max.bytes. Du courtier.)

J'ai découvert la difficulté avec le numéro 2 - vous ne recevez AUCUNE exception, message ou avertissement de la part de Kafka. Veillez donc à en tenir compte lorsque vous envoyez des messages volumineux.

150
laughing_man

Changements mineurs requis pour Kafka 0.10 et le nouveau consommateur par rapport à réponse de laughing_man :

  • Courtier: aucune modification, vous devez toujours augmenter les propriétés message.max.bytes et replica.fetch.max.bytes. message.max.bytes doit être égal ou inférieur (*) à replica.fetch.max.bytes.
  • Producteur: augmentez max.request.size pour envoyer le message plus volumineux.
  • Consommateur: augmentez max.partition.fetch.bytes pour recevoir des messages plus volumineux.

(*) Lisez les commentaires pour en savoir plus sur message.max.bytes <= replica.fetch.max.bytes

43
Sascha Vetter

Vous devez remplacer les propriétés suivantes:

Configuration du courtier ($ KAFKA_HOME/config/server.properties)

  • replica.fetch.max.bytes
  • message.max.bytes

Configurations du consommateur ($ KAFKA_HOME/config/consumer.properties)
Cette étape n'a pas fonctionné pour moi. Je l'ai ajouté à l'application grand public et tout fonctionnait bien

  • fetch.message.max.bytes

Redémarrez le serveur.

regardez cette documentation pour plus d'infos: http://kafka.Apache.org/08/configuration.html

11
user2550587

L’idée est d’avoir le même message envoyé de Kafka Producer à Kafka Broker, puis de le recevoir par Kafka consommateur i.e.

Producteur Kafka -> Kafka Courtier -> Kafka Consommateur

Supposons que si l'exigence est d'envoyer 15 Mo de message, alors le Producteur, le Courtier et le Consommateur, les trois, doivent être synchronisés. .

Producteur Kafka envoie 15 Mo ->Courtier Kafka Permet/Stocke 15 Mo ->Kafka Consumer reçoit 15 Mo

Le réglage doit donc être:

a) sur courtier:

message.max.bytes=15728640 
replica.fetch.max.bytes=15728640

b) sur le consommateur:

fetch.message.max.bytes=15728640
9
Ravi

Une chose importante à retenir est que l'attribut message.max.bytes doit être synchronisé avec la propriété fetch.message.max.bytes du consommateur. la taille d'extraction doit être au moins égale à la taille maximale du message, sinon les producteurs pourraient envoyer des messages plus volumineux que ce que le consommateur peut consommer/extraire. Cela vaut peut-être la peine d'y jeter un coup d'œil.
Quelle version de Kafka vous utilisez? Fournissez également des informations supplémentaires sur la trace que vous obtenez. y a-t-il quelque chose comme ... payload size of xxxx larger than 1000000 à venir dans le journal?

7
user2720864

La réponse de @laughing_man est assez précise. Mais je voulais quand même donner une recommandation que j’ai apprise de Kafka expert , Stephane Maarek de Quora.

Kafka n’est pas conçu pour traiter des messages volumineux.

Votre API doit utiliser le stockage en nuage (Ex AWS S3) et simplement pousser vers Kafka ou tout courtier de messages avec une référence S3. Vous devez trouver un endroit pour conserver vos données, c’est peut-être un lecteur réseau, c’est peut-être n'importe quoi, mais ce ne devrait pas être un courtier de messages.

Maintenant, si vous ne voulez pas aller avec la solution ci-dessus

La taille maximale du message est de 1 Mo (le paramètre de vos courtiers s'appelle message.max.bytes) Apache Kafka . Si vous en aviez vraiment besoin, augmentez cette taille et augmentez la mémoire tampon du réseau pour vos producteurs et vos consommateurs.

Et si vous souhaitez vraiment diviser votre message, assurez-vous que chaque message a exactement la même clé, de sorte qu'il soit poussé sur la même partition, et que le contenu de votre message contienne un "identifiant de pièce" afin que votre consommateur puisse le reconstruire complètement. .

Vous pouvez également explorer la compression si votre message est basé sur du texte (compression gzip, snappy, lz4), ce qui peut réduire la taille des données, mais pas de façon magique.

Encore une fois, vous devez utiliser un système externe pour stocker ces données et envoyer simplement une référence externe à Kafka. C’est une architecture très courante, avec laquelle vous devriez aller et qui est largement acceptée.

N'oubliez pas que Kafka ne fonctionne mieux que si les messages sont énormes, mais pas de taille.

Source: https://www.quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka

5
Bhanu Hoysala