ฉันจะส่งข้อความขนาดใหญ่ด้วย Kafka (มากกว่า 15MB) ได้อย่างไร


120

ฉันส่งข้อความสตริงไปยัง Kafka V. 0.8 ด้วย Java Producer API หากขนาดข้อความประมาณ 15 MB ฉันจะได้รับไฟล์MessageSizeTooLargeException. ฉันพยายามตั้งค่าmessage.max.bytesเป็น 40 MB แต่ฉันยังคงได้รับข้อยกเว้น ข้อความขนาดเล็กทำงานได้โดยไม่มีปัญหา

(ข้อยกเว้นปรากฏในผู้ผลิตฉันไม่มีผู้บริโภคในแอปพลิเคชันนี้)

ฉันจะทำอย่างไรเพื่อกำจัดข้อยกเว้นนี้

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

บันทึกข้อผิดพลาด:

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
สัญชาตญาณแรกของฉันคือขอให้คุณแบ่งข้อความขนาดใหญ่นี้ออกเป็นข้อความขนาดเล็กหลาย ๆ ข้อความ: - / ฉันเดาว่านี่เป็นไปไม่ได้ด้วยเหตุผลบางประการ แต่คุณอาจต้องการพิจารณาใหม่อย่างไรก็ตามข้อความขนาดใหญ่มักจะหมายความว่ามีข้อบกพร่องในการออกแบบ ที่ที่ควรได้รับการแก้ไขจริงๆ
Aaron Digulla

1
ขอบคุณ แต่มันจะทำให้ตรรกะของฉันซับซ้อนขึ้นมาก เหตุใดจึงเป็นความคิดที่ดีที่จะใช้ Kafka สำหรับข้อความประมาณ 15MB 1 MB เป็นขีด จำกัด ขนาดข้อความสูงสุดที่ใช้ได้หรือไม่? ฉันพบข้อ จำกัด ขนาดข้อความในเอกสาร Kafka ไม่มากนัก
Sonson123

2
สิ่งนี้ไม่เกี่ยวข้องกับ Kafka หรือระบบประมวลผลข้อความอื่น ๆ เหตุผลของฉัน: หากมีสิ่งผิดปกติเกิดขึ้นกับไฟล์ 15MB ของคุณการล้างสิ่งที่ยุ่งเหยิงในภายหลังจะมีราคาแพงมาก นั่นเป็นเหตุผลที่ฉันมักจะแยกไฟล์ขนาดใหญ่ออกเป็นงานขนาดเล็กจำนวนมาก (ซึ่งโดยปกติแล้วสามารถดำเนินการควบคู่กันได้เช่นกัน)
Aaron Digulla

คุณเคยใช้การบีบอัดหรือไม่ คุณช่วย
เล่า

คำตอบ:


182

คุณต้องปรับคุณสมบัติสาม (หรือสี่):

  • ด้านผู้บริโภค: fetch.message.max.bytes- สิ่งนี้จะกำหนดขนาดใหญ่ที่สุดของข้อความที่ผู้บริโภคสามารถดึงมาได้
  • ฝั่งนายหน้า: replica.fetch.max.bytes- สิ่งนี้จะช่วยให้การจำลองในโบรกเกอร์สามารถส่งข้อความภายในคลัสเตอร์และตรวจสอบให้แน่ใจว่าข้อความถูกจำลองอย่างถูกต้อง หากมีขนาดเล็กเกินไปข้อความจะไม่ถูกจำลองซ้ำดังนั้นผู้บริโภคจะไม่เห็นข้อความเนื่องจากข้อความจะไม่ถูกผูกมัด (จำลองแบบทั้งหมด)
  • ด้านนายหน้า: message.max.bytes- เป็นขนาดใหญ่ที่สุดของข้อความที่นายหน้าสามารถรับได้จากผู้ผลิต
  • ฝั่งนายหน้า (ตามหัวข้อ): max.message.bytes- นี่คือขนาดข้อความที่ใหญ่ที่สุดที่นายหน้าอนุญาตให้ต่อท้ายหัวข้อ ขนาดนี้ได้รับการตรวจสอบความถูกต้องก่อนการบีบอัด (ค่าเริ่มต้นของนายหน้าmessage.max.bytes)

ฉันพบวิธีที่ยากลำบากเกี่ยวกับหมายเลข 2 - คุณไม่ได้รับข้อยกเว้นข้อความหรือคำเตือนใด ๆ จากคาฟคาดังนั้นโปรดพิจารณาสิ่งนี้เมื่อคุณส่งข้อความขนาดใหญ่


3
ตกลงคุณและ user2720864 ถูกต้อง ฉันได้ตั้งค่าmessage.max.bytesในซอร์สโค้ดเท่านั้น config/server.propertiesแต่ก็ต้องตั้งค่าเหล่านี้ในการกำหนดค่าของเซิร์ฟเวอร์ Kafka ตอนนี้ข้อความที่ใหญ่ขึ้นก็ใช้ได้เช่นกัน :)
Sonson123

3
มีข้อเสียที่ทราบแล้วว่าตั้งค่าเหล่านี้สูงเกินไปหรือไม่?
Ivan Balashov

7
ใช่. ในฝั่งผู้บริโภคคุณจัดสรรfetch.message.max.bytesหน่วยความจำสำหรับแต่ละพาร์ติชัน ซึ่งหมายความว่าหากคุณใช้จำนวนมากเพื่อfetch.message.max.bytesรวมกับพาร์ติชั่นจำนวนมากมันจะใช้หน่วยความจำมาก ในความเป็นจริงเนื่องจากกระบวนการจำลองแบบระหว่างโบรกเกอร์ยังเป็นผู้บริโภคที่เชี่ยวชาญสิ่งนี้จะใช้หน่วยความจำของโบรกเกอร์ด้วย
laughing_man

3
หมายเหตุนอกจากนี้ยังมีmax.message.bytesการกำหนดค่าต่อหัวข้อmessage.max.bytesซึ่งอาจจะต่ำกว่าของโบรกเกอร์
Peter Davis

1
ตามเอกสารอย่างเป็นทางการพารามิเตอร์ในฝั่งผู้บริโภคและพารามิเตอร์ที่เกี่ยวข้องกับการจำลองแบบระหว่างโบรกเกอร์/.*fetch.*bytes/ดูเหมือนจะไม่เป็นข้อ จำกัด ที่ยาก: "นี่ไม่ใช่ค่าสูงสุดสัมบูรณ์หาก [... ] มากกว่าค่านี้ชุดระเบียนจะ จะยังคงถูกส่งกลับเพื่อให้แน่ใจว่าสามารถดำเนินการได้ "
Bluu

56

การเปลี่ยนแปลงเล็กน้อยที่จำเป็นสำหรับKafka 0.10และผู้บริโภครายใหม่เมื่อเทียบกับคำตอบของaugh_man :

  • นายหน้า: ไม่มีการเปลี่ยนแปลงที่คุณยังคงต้องเพิ่มคุณสมบัติและmessage.max.bytes จะต้องมีความเท่าเทียมกันหรือเล็ก (*) กว่าreplica.fetch.max.bytesmessage.max.bytesreplica.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?
Kostas

2
" replica.fetch.max.bytes (ค่าเริ่มต้น: 1MB) - ขนาดสูงสุดของข้อมูลที่โบรกเกอร์สามารถจำลองได้ต้องมีขนาดใหญ่กว่าmessage.max.bytesมิฉะนั้นนายหน้าจะยอมรับข้อความและไม่สามารถทำซ้ำได้ซึ่งนำไปสู่ อาจทำให้ข้อมูลสูญหาย " ที่มา: management-large-messages-kafka
Sascha Vetter

2
ขอขอบคุณที่ติดต่อกลับมาพร้อมลิงก์ สิ่งนี้ดูเหมือนจะสะท้อนสิ่งที่คู่มือ Clouderaแนะนำเช่นกัน ทั้งสองคนนี้ แต่เป็นสิ่งที่ผิด - แจ้งให้ทราบว่าพวกเขาไม่ได้มีเหตุผลทางเทคนิคใด ๆ ที่เป็นเหตุผลที่ ควรจะเป็นอย่างเคร่งครัดขนาดใหญ่เพื่อreplica.fetch.max.bytes message.max.bytesพนักงาน Confluent ได้ยืนยันก่อนหน้านี้ในสิ่งที่ฉันสงสัยในวันนี้ว่าทั้งสองปริมาณสามารถเท่ากันได้
Kostas

2
มีการอัปเดตเกี่ยวกับmessage.max.bytes<replica.fetch.max.bytesหรือmessage.max.bytes=replica.fetch.max.bytes@Kostas หรือไม่?
Sascha Vetter

2
ใช่พวกเขาสามารถเท่าเทียมกัน: mail-archive.com/users@kafka.apache.org/msg25494.html (Ismael ทำงานให้กับ Confluent)
Kostas

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
สำหรับผู้ใช้ commandline ฉันต้องใช้แฟล็ก --fetch-size = <bytes> ดูเหมือนจะไม่อ่านไฟล์ consumer.properties (kafka 0.8.1) ฉันขอแนะนำให้เปิดการบีบอัดจากฝั่งผู้ผลิตโดยใช้ตัวเลือก compression.codec
Ziggy Eunicien

ความคิดเห็นของ Ziggy ใช้ได้ผลสำหรับฉัน kafka 0.8.1.1 ขอบคุณ!
James

เป็นไปได้ไหมที่ fetch.message.max.bytes ถูกแทนที่ด้วย max.partition.fetch.bytes ใน ConsumerConfig
s_bei

12

แนวคิดคือการมีขนาดเท่ากันของข้อความที่ส่งจาก Kafka Producer ไปยัง Kafka Broker จากนั้น Kafka Consumer จะได้รับ

ผู้ผลิต Kafka -> Kafka Broker -> Kafka Consumer

สมมติว่าถ้าต้องการคือการส่งข้อความ 15MB แล้วผลิตที่นายหน้าและผู้บริโภคทั้งสามความต้องการที่จะอยู่ในการซิงค์

Kafka Producerส่ง 15 MB -> Kafka Broker Allows / Stores 15 MB -> Kafka Consumerได้รับ 15 MB

ดังนั้นการตั้งค่าควรเป็น:

ก) ในโบรกเกอร์:

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

b) สำหรับผู้บริโภค:

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 เวอร์ชัน 2.8.0-0.8.0; ตอนนี้ฉันต้องการแค่โปรดิวเซอร์เท่านั้น
Sonson123

7

คำตอบจาก @laughing_man ค่อนข้างแม่นยำ แต่ถึงกระนั้นฉันก็อยากจะให้คำแนะนำซึ่งฉันได้เรียนรู้จากStephane Maarekผู้เชี่ยวชาญของ Kafka จาก Quora

Kafka ไม่ได้มีไว้เพื่อจัดการกับข้อความขนาดใหญ่

API ของคุณควรใช้ที่เก็บข้อมูลบนคลาวด์ (Ex AWS S3) และเพียงแค่กดไปที่ Kafka หรือนายหน้าข้อความใด ๆ ที่อ้างอิง S3 คุณต้องหาที่ไหนสักแห่งเพื่อเก็บรักษาข้อมูลของคุณอาจจะเป็นไดรฟ์เครือข่ายอาจเป็นอะไรก็ได้ แต่ไม่ควรเป็นนายหน้าข้อความ

ตอนนี้ถ้าคุณไม่ต้องการใช้วิธีแก้ปัญหาข้างต้น

ขนาดข้อความสูงสุดคือ 1MB (การตั้งค่าในโบรกเกอร์ของคุณเรียกว่าmessage.max.bytes) อาปาเช่คาฟคา หากคุณต้องการมันไม่ดีจริงๆคุณสามารถเพิ่มขนาดและตรวจสอบให้แน่ใจว่าได้เพิ่มบัฟเฟอร์เครือข่ายสำหรับผู้ผลิตและผู้บริโภคของคุณ

และถ้าคุณสนใจที่จะแยกข้อความของคุณจริงๆตรวจสอบให้แน่ใจว่าการแบ่งข้อความแต่ละส่วนมีคีย์เดียวกันทุกประการเพื่อให้ถูกส่งไปยังพาร์ติชันเดียวกันและเนื้อหาข้อความของคุณควรรายงาน "รหัสส่วน" เพื่อให้ผู้บริโภคของคุณสามารถสร้างข้อความใหม่ได้อย่างสมบูรณ์ .

นอกจากนี้คุณยังสามารถสำรวจการบีบอัดได้หากข้อความของคุณเป็นแบบข้อความ (การบีบอัด gzip, เร็ว, lz4) ซึ่งอาจลดขนาดข้อมูล แต่ไม่ใช่อย่างน่าอัศจรรย์

อีกครั้งคุณต้องใช้ระบบภายนอกเพื่อจัดเก็บข้อมูลนั้นและเพียงแค่ส่งการอ้างอิงภายนอกไปยัง Kafka นั่นเป็นสถาปัตยกรรมทั่วไปและเป็นสถาปัตยกรรมที่คุณควรใช้และเป็นที่ยอมรับอย่างกว้างขวาง

โปรดทราบว่าคาฟคาจะทำงานได้ดีที่สุดก็ต่อเมื่อข้อความมีจำนวนมาก แต่ไม่ได้มีขนาด

ที่มา: https://www.quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka


4
คุณอาจต้องการทราบว่าคำแนะนำ "ของคุณ" เป็นสำเนาคำแนะนำแบบ Quora ของStéphane Maarek ที่quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka
Mike

Kafka ทำงานกับข้อความขนาดใหญ่ได้อย่างไม่มีปัญหา หน้าบทนำในโฮมเพจ Kafka ยังอ้างถึงเป็นระบบจัดเก็บข้อมูล
calloc_org

3

สำหรับผู้ที่ใช้ landoop kafka: คุณสามารถส่งผ่านค่า config ในตัวแปรสภาพแวดล้อมเช่น:

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",
   ... .. }                                                                                                                                                                                                                                                      
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.