Kafka ile (15MB üzeri) büyük mesajları nasıl gönderebilirim?


120

Java Producer API ile Kafka V. 0.8'e dizgi mesajları gönderiyorum. Mesaj boyutu yaklaşık 15 MB ise, bir MessageSizeTooLargeException. message.max.bytes40 MB olarak ayarlamayı denedim , ancak yine de istisna alıyorum. Küçük mesajlar sorunsuz çalıştı.

(İstisna yapımcıda görünüyor, bu uygulamada tüketicim yok.)

Bu istisnadan kurtulmak için ne yapabilirim?

Örnek yapımcı yapılandırmam

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

Hata-Log:

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
İlk içgüdülerim, sizden bu büyük mesajı birkaç küçük mesaja bölmenizi istemektir: - / Tahminimce bu, bazı nedenlerden dolayı mümkün değildir, ancak yine de yeniden gözden geçirmek isteyebilirsiniz: Büyük mesajlar genellikle bir tasarım kusuru olduğu anlamına gelir gerçekten düzeltilmesi gereken bir yer.
Aaron Digulla

1
Teşekkürler, ama mantığımı çok daha karmaşık hale getirir. Kafka'yı 15MB civarındaki mesajlar için kullanmak neden kötü bir fikir? Kullanılabilen maksimum mesaj boyutu sınırı 1 MB mı? Kafka belgelerinde mesaj boyutu sınırı hakkında pek bir şey bulamadım.
Sonson123

2
Bu, Kafka veya başka herhangi bir mesaj işleme sistemiyle tamamen ilgisizdir. Benim gerekçem: 15MB dosyanızla ilgili bir şeyler ters giderse, karışıklığı daha sonra temizlemek çok pahalıdır. Bu yüzden genellikle büyük dosyaları birçok küçük işe bölerim (bu daha sonra genellikle paralel olarak da yürütülebilir).
Aaron Digulla

herhangi bir sıkıştırma kullandın mı? lütfen biraz daha ayrıntı paylaşır mısın, tek bir kelimeden bir şeyi tahmin etmek biraz zor
user2720864

Yanıtlar:


182

Üç (veya dört) özelliği ayarlamanız gerekir:

  • Tüketici tarafı: fetch.message.max.bytes- bu, tüketici tarafından alınabilecek en büyük mesaj boyutunu belirleyecektir.
  • Aracı tarafı: replica.fetch.max.bytes- bu, aracılardaki eşlemelerin küme içinde ileti göndermesine ve iletilerin doğru şekilde çoğaltıldığından emin olmasına olanak tanır. Bu çok küçükse, mesaj asla kopyalanmayacaktır ve bu nedenle, tüketici mesajı asla görmeyecektir çünkü mesaj asla teslim edilmeyecektir (tamamen kopyalanacaktır).
  • Broker tarafı: message.max.bytes- bu, komisyoncu tarafından bir üreticiden alınabilecek en büyük mesaj boyutudur.
  • Broker tarafı (konu başına): max.message.bytes- bu, aracının konuya eklenmesine izin vereceği mesajın en büyük boyutudur. Bu boyut, ön sıkıştırma ile doğrulanmıştır. (Brokerın varsayılanlarıdır message.max.bytes.)

2 numara hakkında zor yoldan öğrendim - Kafka'dan HERHANGİ bir istisna, mesaj veya uyarı alamazsınız, bu yüzden büyük mesajlar gönderirken bunu dikkate aldığınızdan emin olun.


3
Tamam, sen ve user2720864 haklıydınız. Ben sadece message.max.byteskaynak kodunda ayarlamıştım . Ama bu değerleri Kafka sunucusunun konfigürasyonunda ayarlamam gerekiyor config/server.properties. Artık daha büyük mesajlar da işe yarıyor :).
Sonson123

3
Bu değerleri çok yükseğe ayarlamanın bilinen herhangi bir dezavantajı var mı?
Ivan Balashov

7
Evet. Tüketici tarafında, fetch.message.max.bytesHER bölüm için bellek ayırırsınız. Bu, fetch.message.max.bytesçok sayıda bölümle birleştirmek için çok sayıda kullanırsanız, çok fazla bellek tüketeceği anlamına gelir . Aslında, aracılar arasındaki çoğaltma işlemi aynı zamanda uzmanlaşmış bir tüketici olduğundan, bu aynı zamanda aracılar üzerindeki belleği de tüketecektir.
laughing_man

3
Ayrıca , aracınınkinden daha düşük olabilecek her konu için bir max.message.bytesyapılandırma olduğunu unutmayın . message.max.bytes
Peter Davis

1
Resmi belgeye göre, tüketici tarafındaki parametreler ve aracılar arasındaki kopyalamayla ilgili olanlar /.*fetch.*bytes/kesin sınırlar gibi görünmüyor: "Bu mutlak bir maksimum değil, eğer [...] bu değerden büyükse, kayıt grubu ilerleme kaydedilebilmesi için yine de iade edilebilir. "
Bluu

56

Laugh_man'ın cevabına kıyasla Kafka 0.10 ve yeni tüketici için gerekli küçük değişiklikler :

  • Broker: Değişiklik yok, yine de özellikleri artırmanız gerekiyor message.max.bytesve replica.fetch.max.bytes. message.max.byteseşit veya daha küçük (*) olmalıdır replica.fetch.max.bytes.
  • Yapımcı: Daha max.request.sizebüyük mesajı göndermek için artırın .
  • Tüketici: Daha max.partition.fetch.bytesbüyük mesajlar almak için artırın .

(*) message.max.bytes<= Hakkında daha fazla bilgi edinmek için yorumları okuyunreplica.fetch.max.bytes


2
Neden message.max.bytesdaha küçük olması gerektiğini biliyor musunuz replica.fetch.max.bytes?
Kostas

2
" replica.fetch.max.bytes (varsayılan: 1MB) - Bir aracının kopyalayabileceği maksimum veri boyutu. Bu, message.max.bytes'ten daha büyük olmalıdır , aksi takdirde bir komisyoncu iletileri kabul edip çoğaltamaz. potansiyel veri kaybı. " Kaynak: handling-large-messages-kafka
Sascha Vetter

2
Bana bir bağlantıyla geri döndüğünüz için teşekkür ederim. Bu, Cloudera rehberinin önerdiği şeyi yansıtıyor gibi görünüyor . Ancak bunların her ikisi de yanlış - neden replica.fetch.max.bytes kesinlikle daha büyük olması gerektiğine dair herhangi bir teknik neden sunmadıklarına dikkat edin message.max.bytes. Bir Confluent çalışan bugün erken saatlerde şüphelendiğim şeyi doğruladı : iki miktar aslında eşit olabilir.
Kostas

2
İlgili herhangi bir güncelleme olup message.max.bytes<replica.fetch.max.bytesveya message.max.bytes=replica.fetch.max.bytes@Kostas?
Sascha Vetter

2
Evet, eşit olabilirler: mail-archive.com/users@kafka.apache.org/msg25494.html (Ismael Confluent için çalışıyor)
Kostas

13

Aşağıdaki özellikleri geçersiz kılmanız gerekir:

Broker Yapılandırmaları ($ KAFKA_HOME / config / server.properties)

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

Tüketici Yapılandırmaları ($ KAFKA_HOME / config / tüketici.properties)
Bu adım benim için işe yaramadı. Tüketici uygulamasına ekledim ve sorunsuz çalışıyordu

  • fetch.message.max.bytes

Sunucuyu yeniden başlatın.

Daha fazla bilgi için bu belgelere bakın: http://kafka.apache.org/08/configuration.html


1
komut satırı tüketicisi için --fetch-size = <bytes> bayrağını kullanmam gerekiyor. Consumer.properties dosyasını (kafka 0.8.1) okumuyor gibi görünüyor. Ayrıca sıkıştırma.codec seçeneğini kullanarak üretici tarafından sıkıştırmayı açmanızı tavsiye ederim.
Ziggy Eunicien

Ziggy'nin yorumu benim için çalıştı kafka 0.8.1.1. Teşekkür ederim!
James

ConsumerConfig'de fetch.message.max.bytes yerine max.partition.fetch.bytes olabilir mi?
s_bei

12

Fikir, Kafka Producer'dan Kafka Broker'a gönderilen ve ardından Kafka Consumer tarafından alınan eşit boyutta mesaja sahip olmaktır.

Kafka yapımcısı -> Kafka Broker -> Kafka Tüketici

Diyelim ki, gereksinim 15MB'lık bir mesaj göndermekse, Üretici , Komisyoncu ve Tüketicinin üçünün de senkronize olması gerekir.

Kafka Producer 15 MB gönderir -> Kafka Broker 15 MB İzin Verir / Saklar -> Kafka Tüketici 15 MB alır

Bu nedenle ayar şöyle olmalıdır:

a) Broker'da:

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

b) Tüketici üzerinde:

fetch.message.max.bytes=15728640

2
ConsumerConfig'de fetch.message.max.bytes yerine max.partition.fetch.bytes olabilir mi?
s_bei

7

Bir önemli şey hatırlamak message.max.bytesözellik olmalıdır senkronize tüketicinin ile fetch.message.max.bytesmülkiyet. getirme boyutu en az maksimum mesaj boyutu kadar büyük olmalıdır, aksi takdirde üreticilerin tüketicinin tüketebileceğinden / getirebileceğinden daha büyük mesajlar gönderebileceği bir durum olabilir. Bir bakmaya değer olabilir.
Kafka'nın hangi sürümünü kullanıyorsunuz? Ayrıca aldığınız iz hakkında daha fazla ayrıntı sağlayın. payload size of xxxx larger than 1000000Günlükte ... gibi bir şey var mı?


1
Sorumu daha fazla bilgiyle güncelledim: Kafka Sürüm 2.8.0-0.8.0; şimdi sadece yapımcıya ihtiyacım var.
Sonson123

7

@Laughing_man'ın cevabı oldukça doğru. Ama yine de Quora'dan Kafka uzmanı Stephane Maarek'ten öğrendiğim bir tavsiye vermek istedim .

Kafka, büyük mesajlarla başa çıkmak zorunda değildir.

API'niz bulut depolamayı (Ex AWS S3) kullanmalı ve Kafka'ya veya herhangi bir mesaj aracısına bir S3 referansı göndermelidir. Verilerinizi kalıcı hale getirecek bir yer bulmalısınız, belki bir ağ sürücüsü, belki de her neyse, ama mesaj simsarı olmamalı.

Şimdi, yukarıdaki çözümle gitmek istemiyorsanız

Mesaj maksimum boyutu 1MB'dir (aracılarınızdaki ayar Apache Kafka olarak adlandırılır message.max.bytes) . Gerçekten çok ihtiyacınız varsa, bu boyutu artırabilir ve üreticileriniz ve tüketicileriniz için ağ tamponlarını artırdığınızdan emin olabilirsiniz.

Ve mesajınızı bölmeyi gerçekten önemsiyorsanız, her mesaj bölümünün aynı anahtara sahip olduğundan emin olun, böylece aynı bölüme itilir ve mesaj içeriğiniz, tüketicinizin mesajı tamamen yeniden oluşturabilmesi için bir "parça kimliği" bildirmelidir. .

Ayrıca mesajınız metin tabanlıysa (gzip, hızlı, lz4 sıkıştırma) veri boyutunu küçültebilir, ancak sihirli bir şekilde değil, sıkıştırmayı da keşfedebilirsiniz.

Yine, bu verileri depolamak için harici bir sistem kullanmanız ve sadece Kafka'ya harici bir referans göndermeniz gerekir. Bu çok yaygın bir mimari ve gitmeniz gereken ve geniş kabul gören bir mimari.

Kafka'nın yalnızca mesajların miktarı çok büyükse ancak boyut olarak değilse en iyi sonucu verdiğini unutmayın.

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



Kafka büyük mesajlarla çalışıyor, kesinlikle sorun yok. Hatta Kafka ana sayfasındaki giriş sayfası onu bir depolama sistemi olarak referans alıyor.
calloc_org

3

Landoop kafka kullanan kişiler için: Yapılandırma değerlerini ortam değişkenlerinde aşağıdaki gibi iletebilirsiniz:

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 `

Ve rdkafka'yı kullanırsanız, yapımcı yapılandırmasındaki message.max.bytes'i şu şekilde iletin:

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

Benzer şekilde tüketici için

  const kafkaConf = {
   "group.id": "librd-test",
   "fetch.message.max.bytes":"15728640",
   ... .. }                                                                                                                                                                                                                                                      
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.