Як я можу надсилати великі повідомлення з Kafka (понад 15 МБ)?


118

Я надсилаю String-повідомлення на Kafka V. 0.8 за допомогою API Java Producer. Якщо розмір повідомлення становить близько 15 МБ, я отримую MessageSizeTooLargeException. Я намагався встановитиmessage.max.bytes 40 Мб, але все одно отримую виняток. Невеликі повідомлення працювали без проблем.

(Виняток з’являється у виробника; у цій програмі у мене немає споживача.)

Що я можу зробити, щоб позбутися цього винятку?

Мій приклад виробника конфігурації

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);
}

Журнал помилок:

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)

5
Першим моїм інстинктом було б попросити вас розділити це величезне повідомлення на кілька менших: - / Я здогадуюсь, що це неможливо з якихось причин, але ви можете все-таки переглянути його: Величезні повідомлення зазвичай означають, що існує недолік дизайну десь, що дійсно має бути виправлено.
Аарон Дігулла

1
Дякую, але це зробило б мою логіку набагато складнішою. Чому погано використовувати Kafka для повідомлень близько 15 Мб? Чи є 1 МБ максимально допустимий розмір повідомлення, який можна використовувати? Про обмеження розміру повідомлення я не знайшов у документації Kafka.
Sonson123

2
Це абсолютно не стосується Кафки чи будь-якої іншої системи обробки повідомлень. Мої міркування: Якщо з вашим файлом 15 МБ щось піде не так, то очищення безладу після цього дуже дорого. Ось чому я зазвичай розбиваю великі файли на багато менших завдань (які потім зазвичай можна виконувати також паралельно).
Аарон Дігулла

чи використовували ви стиснення? Ви можете, будь ласка, поділитися деталями, начебто важко здогадатися про щось із одного одного слова
user2720864

Відповіді:


181

Вам потрібно скорегувати три (або чотири) властивості:

  • Сторона споживача:fetch.message.max.bytes - це визначатиме найбільший розмір повідомлення, який може отримати споживач.
  • Сторона брокера: replica.fetch.max.bytes посередника - це дозволить реплікам у брокерах надсилати повідомлення в кластер і переконуватись, що повідомлення реплікуються правильно. Якщо це занадто мало, то повідомлення ніколи не буде повторюватися, а отже, споживач ніколи не побачить повідомлення, оскільки повідомлення ніколи не буде вчинене (повністю реплікуване).
  • Сторона брокера: message.max.bytes - це найбільший розмір повідомлення, який може отримати брокер від виробника.
  • Сторона max.message.bytesпосередника (за темою): - це найбільший розмір повідомлення, який брокер дозволить додати до теми. Цей розмір підтверджується допрессідацією. (За замовчуванням до брокера message.max.bytes.)

Я дізнався важкий шлях щодо числа 2 - ви не отримуєте жодних винятків, повідомлень чи попереджень від Kafka, тому обов'язково враховуйте це, коли ви надсилаєте великі повідомлення.


3
Гаразд, ви та користувач2720864 були правильні. Я тільки встановив message.max.bytesу вихідному коді. Але я повинен встановити ці значення в конфігурації сервера Kafka config/server.properties. Зараз також працюють більші повідомлення :).
Sonson123

3
Чи є відомі недоліки, які задають ці значення занадто високими?
Іван Балашов

7
Так. З боку споживача, ви виділяєте fetch.message.max.bytesпам'ять для розділу EACH. Це означає, що якщо ви використовуєте величезну кількість для fetch.message.max.bytesкомбінованої з великою кількістю розділів, це забирає багато пам'яті. Насправді, оскільки процес реплікації між брокерами також є спеціалізованим споживачем, це також буде споживати пам'ять брокерів.
laughing_man

3
Зауважте, існує також max.message.bytesконфігурація за темою, яка може бути нижчою, ніж у брокера message.max.bytes.
Пітер Девіс

1
Згідно з офіційним документом, параметри на стороні споживача та параметри щодо реплікації між брокерами /.*fetch.*bytes/не здаються жорсткими межами: "Це не абсолютний максимум, якщо [...] більше цього значення, пакет записів буде все ще повернутись, щоб забезпечити прогрес ".
Блу

56

Невеликі зміни, необхідні для Kafka 0.10 та нового споживача порівняно з відповіддю laughing_man :

  • Брокер: Жодних змін немає, вам потрібно збільшити властивості message.max.bytesта replica.fetch.max.bytes. message.max.bytesмає бути рівним або меншим (*), ніжreplica.fetch.max.bytes .
  • Виробник: Збільшити max.request.size щоб надіслати більше повідомлення.
  • Споживач: збільшуйте, max.partition.fetch.bytesщоб отримувати більші повідомлення.

(*) Прочитайте коментарі, щоб дізнатися більше про message.max.bytes<=replica.fetch.max.bytes


2
Чи знаєте ви, чому message.max.bytesпотрібно бути меншим, ніж replica.fetch.max.bytes?
Костас

2
" replica.fetch.max.bytes (за замовчуванням: 1 МБ) - Максимальний розмір даних, який брокер може копіювати. Цей розмір повинен бути більшим, ніж message.max.bytes , або брокер прийме повідомлення і не зможе їх повторити. потенційна втрата даних ". Джерело: handling-large-messages-kafka
Sascha Vetter

2
Дякую за те, що ти повернувся до мене за посиланням. Це, здається, перегукується з тим, що пропонує посібник Cloudera . Обидва вони, однак, помиляються - зауважте, що вони не пропонують жодних технічних причин того, чому replica.fetch.max.bytes слід бути суворішим message.max.bytes. Співробітник « Конфлюент» раніше сьогодні підтвердив те, що я підозрював: що ці дві величини можуть бути насправді рівними.
Костас

2
Чи є якісь оновлення щодо message.max.bytes<replica.fetch.max.bytesабо message.max.bytes=replica.fetch.max.bytes@Kostas?
Саша Веттер

2
Так, вони можуть бути рівними: mail-archive.com/users@kafka.apache.org/msg25494.html (Ісмаїл працює для злиття)
Костас

13

Вам потрібно змінити такі властивості:

Конфігурація посередника ($ KAFKA_HOME / config / server.properties)

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

Споживчі конфігурації ($ KAFKA_HOME / config / Consumer.properties)
Цей крок не працював для мене. Я додаю його до програми для споживачів, і він працював чудово

  • fetch.message.max.bytes

Перезавантажте сервер.

Перегляньте цю документацію для отримання додаткової інформації: http://kafka.apache.org/08/configuration.html


1
для споживача командного рядка мені потрібно використовувати прапор --fetch-size = <bytes>. Здається, він не читає файл Consumerproperties (kafka 0.8.1). Я також рекомендую включити стиснення з боку виробника за допомогою параметра compression.codec.
Ziggy Eunicien

Коментар Зіґґі працював для мене kafka 0.8.1.1. Дякую!
Джеймс

може бути, що fetch.message.max.bytes замінено max.partition.fetch.bytes у ConsumerConfig?
s_bei

12

Ідея полягає в тому, щоб повідомлення було рівним за розміром, яке надсилається від виробника Kafka до брокера Kafka, а потім отримується від Kafka Consumer, тобто

Кафський виробник -> Kafka Broker -> Kafka Consumer

Припустимо, якщо вимога полягає в надсиланні 15 Мб повідомлення, тоді виробник , брокер та споживач , усі три, повинні синхронізуватися.

Kafka Producer надсилає 15 Мб -> Брокер Kafka Дозволяє / Магазини 15 Мб -> Kafka Consumer отримує 15 МБ

Отже, цей параметр повинен бути:

а) на брокера:

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

б) щодо споживача:

fetch.message.max.bytes=15728640

2
може бути, що fetch.message.max.bytes замінено max.partition.fetch.bytes у ConsumerConfig?
s_bei

7

Одна ключова річ , щоб пам'ятати , що message.max.bytesатрибут повинен бути синхронізований з споживача fetch.message.max.bytesнерухомості. розмір вибору повинен бути принаймні таким же, як максимальний розмір повідомлення, інакше може виникнути ситуація, коли виробники можуть надсилати повідомлення, більші, ніж споживач може споживати / отримувати. Можливо, варто поглянути на це.
Яку версію Kafka ви використовуєте? Надайте ще кілька деталей, які ви отримуєте. чи є якась річ на кшталт ... payload size of xxxx larger than 1000000підійде до журналу?


1
Я оновив своє запитання додатковою інформацією: Kafka Version 2.8.0-0.8.0; зараз мені потрібен лише продюсер.
Sonson123

6

Відповідь від @laughing_man досить точна. Але все ж я хотів дати рекомендацію, яку я дізнався від експерта Kafka Стефана Маарека від Quora.

Кафка не призначена для обробки великих повідомлень.

Ваш API повинен використовувати хмарне сховище (Ex AWS S3), а просто натисніть на Kafka або будь-якого брокера повідомлень, що посилається на S3. Ви повинні знайти десь зберегти свої дані, можливо, це мережевий диск, можливо, це все що завгодно, але це не повинно бути посередником повідомлень.

Тепер, якщо ви не хочете піти з вищевказаним рішенням

Максимальний розмір повідомлення - 1 Мб (настройка у ваших брокерів називається message.max.bytes) Apache Kafka . Якщо вам це дуже потрібно, ви можете збільшити цей розмір і переконатися в збільшенні мережевих буферів для своїх виробників і споживачів.

Якщо ви дійсно переймаєтесь розділенням свого повідомлення, переконайтеся, що кожне розділене повідомлення має однакову клавішу, щоб його було натиснуто на один і той же розділ, а вміст вашого повідомлення повинен повідомити "ідентифікатор частини", щоб ваш споживач міг повністю відновити повідомлення. .

Ви також можете вивчити стиснення, якщо ваше повідомлення засноване на тексті (gzip, snappy, lz4 стиснення), що може зменшити розмір даних, але не магічно.

Знову ж таки, ви повинні використовувати зовнішню систему для зберігання цих даних і просто натиснути зовнішню посилання на Kafka. Це дуже поширена архітектура, і з якою ви повинні піти і широко прийняти.

Майте на увазі, що Кафка працює найкраще лише в тому випадку, якщо повідомлення мають величезну кількість, але не за розміром.

Джерело: https://www.quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka


4
Ви можете зауважити, що "Ваша" рекомендація - це майже дослівна копія рекомендації Quora Стефана Маарека на сайті quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka
Mike

Кафка працює з великими повідомленнями, абсолютно ніякого питання. Вступна сторінка на домашній сторінці Kafka навіть згадує її як систему зберігання.
calloc_org

3

Для людей, які використовують landoop kafka: Ви можете передавати значення конфігурацій у змінні середовища, наприклад:

docker run -d --rm -p 2181:2181 -p 3030:3030 -p 8081-8083:8081-8083  -p 9581-9585:9581-9585 -p 9092:9092
 -e KAFKA_TOPIC_MAX_MESSAGE_BYTES=15728640 -e KAFKA_REPLICA_FETCH_MAX_BYTES=15728640  landoop/fast-data-dev:latest `

І якщо ви використовуєте rdkafka, тоді передайте message.max.bytes у конфігурацію виробника, наприклад:

  const producer = new Kafka.Producer({
        'metadata.broker.list': 'localhost:9092',
        'message.max.bytes': '15728640',
        'dr_cb': true
    });

Аналогічно для споживача

  const kafkaConf = {
   "group.id": "librd-test",
   "fetch.message.max.bytes":"15728640",
   ... .. }                                                                                                                                                                                                                                                      
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.