如何使用Kafka(超过15MB)发送大型邮件?


118

我使用Java Producer API将字符串消息发送到Kafka V. 0.8。如果邮件大小约为15 MB,我会收到一个MessageSizeTooLargeException。我尝试将其设置message.max.bytes为40 MB,但仍然出现异常。小消息可以正常工作。

(例外出现在生产者中,我在此应用程序中没有消费者。)

我该怎么办才能摆脱这种例外情况?

我的示例生产者配置

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用于15MB左右的消息是个主意?1 MB是可以使用的最大邮件大小限制吗?我在Kafka文档中发现的邮件大小限制不多。
Sonson123,2014年

2
这与Kafka或任何其他消息处理系统完全无关。我的推论:如果您的15MB文件出了点​​问题,那么事后清理这些文件非常昂贵。这就是为什么我通常将大文件拆分为许多较小的作业(然后通常也可以并行执行)。
2014年

你有没有压缩?您能否分享更多详细信息,
仅凭

Answers:


181

您需要调整三个(或四个)属性:

  • 消费者方:fetch.message.max.bytes-这将确定消费者可以获取的消息的最大大小。
  • 代理方:replica.fetch.max.bytes-这将允许代理中的副本在群集内发送消息,并确保正确复制了消息。如果该值太小,则消息将永远不会被复制,因此,使用者将永远不会看到该消息,因为该消息将永远不会被提交(完全复制)。
  • 代理方:message.max.bytes-这是代理可以从生产者接收到的最大消息量。
  • 代理方(按主题):max.message.bytes-这是代理将允许附加到主题的最大消息大小。此大小在压缩前经过验证。(默认为经纪人的message.max.bytes。)

我发现第二种方法很困难-您不会从Kafka那里收到任何异常,消息或警告,因此在发送大型消息时请务必考虑这一点。


3
好的,您和user2720864是正确的。我只message.max.bytes在源代码中设置了。但是我必须在Kafka服务器的配置中设置这些值config/server.properties。现在,更大的消息也起作用:)。
2014年

3
将这些值设置得过高是否有任何已知的缺点?
伊万·巴拉索夫

7
是。在使用者方面,您fetch.message.max.bytes为每个分区分配内存。这意味着,如果fetch.message.max.bytes将大量分区与大量分区结合使用,则会消耗大量内存。实际上,由于代理之间的复制过程也是专门的使用者,因此这也会消耗代理上的内存。
laughing_man

3
请注意,每个主题max.message.bytes配置也可能低于代理的配置。message.max.bytes
彼得·戴维斯

1
根据官方文件,消费者方和经纪人之间复制的参数/.*fetch.*bytes/似乎不是硬性限制:“这不是绝对最大值,如果大于此值,记录批处理将仍退回以确保可以取得进展。”
Bluu

56

卡夫卡0.10新消费者所需的微小变化与aughing_man的回答相比:

  • 经纪人:无需更改,您仍然需要增加属性message.max.bytesreplica.fetch.max.bytesmessage.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
“ 复制副本最大字节数(默认值:1MB)–代理可以复制的最大数据大小。该大小必须大于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.bytesmessage.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)

  • 复制副本最大字节数
  • message.max.bytes

使用者配置($ KAFKA_HOME / config / consumer.properties)
此步骤对我不起作用。我将其添加到消费者应用程序中,并且运行良好

  • fetch.message.max.bytes

重新启动服务器。

请参阅此文档以获取更多信息:http : //kafka.apache.org/08/configuration.html


1
对于命令行使用者,我需要使用--fetch-size = <bytes>标志。似乎没有读取Consumer.properties文件(kafka 0.8.1)。我还建议您使用compression.codec选项从生产者端打开压缩。
Ziggy Eunicien 2014年

Ziggy的评论对我有用kafka 0.8.1.1。谢谢!
詹姆斯

能否在ConsumerConfig中将fetch.message.max.bytes替换为max.partition.fetch.bytes?
s_bei

12

这个想法是使消息从Kafka Producer发送到Kafka Broker然后由Kafka Consumer接收的消息大小相等。

卡夫卡生产者->卡夫卡经纪人->卡夫卡消费者

假设如果要求发送15MB的消息,则这三个生产者经纪人消费者都需要同步。

Kafka Producer发送15 MB- > Kafka Broker允许/存储15 MB- > Kafka Consumer接收15 MB

因此,设置应为:

a)经纪人:

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

b)对消费者:

fetch.message.max.bytes=15728640

2
能否在ConsumerConfig中将fetch.message.max.bytes替换为max.partition.fetch.bytes?
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'1

6

@laughing_man的答案非常准确。但是,我仍然想提出建议,这是我从Quora的Kafka专家Stephane Maarek那里学到的。

Kafka并非要处理大型邮件。

您的API应该使用云存储(Ex AWS S3),并且只需向Kafka或任何消息代理推送S3的引用即可。您必须找到某个地方来保存数据,也许是网络驱动器,也许是任何东西,但它不应该是消息代理。

现在,如果您不想采用上述解决方案

消息的最大大小为1MB(代理中的设置称为message.max.bytesApache Kafka。如果确实非常需要它,则可以增加该大小,并确保为生产者和消费者增加网络缓冲区。

而且,如果您真的很想拆分邮件,请确保每个邮件拆分都具有完全相同的密钥,以便将其推送到同一分区,并且邮件内容应报告“部件ID”,以便您的使用者可以完全重建邮件。

如果您的消息是基于文本的(gzip,snappy,lz4压缩),则还可以探索压缩,这可能会减小数据大小,但并非不可思议。

同样,您必须使用外部系统来存储该数据,然后将外部引用推送到Kafka。这是一种非常常见的体系结构,您应该使用并被广泛接受的体系结构。

请记住,仅当邮件数量巨大而不是大小时,Kafka才能发挥最佳作用。

资料来源:https : //www.quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka


4
您可能需要注意,“您的”建议几乎是StéphaneMaarek的Quora建议中逐字逐句的
Mike

Kafka处理大型邮件,绝对没有问题。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",
   ... .. }                                                                                                                                                                                                                                                      
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.