我使用Java Producer API向Kafka V. 0.8发送String-messages。
如果邮件大小约为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)
答案 0 :(得分:139)
您需要调整三个(或四个)属性:
fetch.message.max.bytes
- 这将确定消费者可以获取的消息的最大大小。replica.fetch.max.bytes
- 这将允许代理中的副本在群集内发送消息,并确保正确复制消息。如果这个太小,则永远不会复制该消息,因此,消费者永远不会看到该消息,因为该消息永远不会被提交(完全复制)。message.max.bytes
- 这是经纪人从制作人处收到的最大邮件大小。max.message.bytes
- 这是代理允许附加到主题的消息的最大大小。此大小经过预压缩验证。 (默认为经纪人的message.max.bytes
。)我发现了关于2号的困难方法 - 你没有从Kafka那里得到任何例外,消息或警告,所以在你发送大量消息时一定要考虑这个。
答案 1 :(得分:42)
Kafka 0.10 和new consumer与laughing_man's answer相比需要进行细微更改:
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 :(得分:11)
您需要覆盖以下属性:
经纪人配置($ KAFKA_HOME / config / server.properties)
消费者配置($ KAFKA_HOME / config / consumer.properties)
此步骤对我不起作用。我将它添加到消费者应用程序,它工作正常
重启服务器。
查看此文档以获取更多信息: http://kafka.apache.org/08/configuration.html
答案 3 :(得分:8)
我们的想法是将相同大小的信息从Kafka Producer发送给Kafka Broker,然后由Kafka Consumer收到,即
。Kafka制片人 - > Kafka Broker - >卡夫卡消费者
假设要求是发送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
答案 4 :(得分:6)
要记住,message.max.bytes
属性必须同步与消费者的fetch.message.max.bytes
属性有关。获取大小必须至少与最大消息大小一样大,否则可能存在生成器可以发送大于消费者可以使用/获取的消息的情况。值得一看的是它。
您使用的是哪个版本的Kafka?还提供了一些您将获得的更多详细信息跟踪。有没有像payload size of xxxx larger
than 1000000
出现在日志中的东西?
答案 5 :(得分:4)
@laughing_man的回答非常准确。但我仍然想提出建议,这是我从Quora的Kafka专家 Stephane Maarek 那里学到的。
Kafka并不是要处理大型邮件。
您的API应该使用云存储(Ex AWS S3),并且只需向Kafka或任何消息代理推送S3的引用即可。您必须找到某个地方来保存数据,也许是网络驱动器,也许是任何东西,但不应该是消息代理。
现在,如果您不想采用上述解决方案
消息的最大大小为1MB(您的代理中的设置称为message.max.bytes
)Apache Kafka。如果真的很需要它,则可以增加该大小,并确保为生产者和消费者增加网络缓冲区。
如果您真的很想拆分邮件,请确保每个邮件拆分都具有完全相同的密钥,以便将其推送到同一分区,并且邮件内容应报告“部件ID”,以便您的使用者可以完全重建消息。
如果您的消息是基于文本的(gzip,snappy,lz4压缩),则还可以探索压缩,这可能会减小数据大小,但并非不可思议。
同样,您必须使用外部系统来存储该数据,并且只需将外部引用推送到Kafka。这是一种非常常见的体系结构,您应该使用并被广泛接受的体系结构。
请记住,仅当邮件数量巨大但大小不够时,Kafka才能发挥最佳作用。
来源:https://www.quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka
答案 6 :(得分: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",
... .. }
答案 7 :(得分:2)
我认为,这里的大多数答案都有些过时或不完整。
要参考 answer of Sacha Vetter(带有 Kafka 0.10 的更新),我想提供一些额外的信息和官方文档的链接。
生产者配置:
max.request.size
(Link) 必须为大于 1 MB 的文件增加,否则它们将被拒绝代理/主题配置:
message.max.bytes
(Link) 可以设置,如果想在代理级别增加消息大小。但是,来自文档:“这可以使用主题级别 max.message.bytes 配置为每个主题设置。”max.message.bytes
(Link) 可能会增加,如果只有一个主题应该能够接受更大的文件。不得更改代理配置。我总是更喜欢主题限制配置,因为我可以自己将主题配置为 Kafka 集群的客户端(例如使用 admin client)。我可能对代理配置本身没有任何影响。
在上面的答案中,还提到了一些必要的配置:
来自文档:"这不是绝对最大值,如果fetch的第一个非空分区中的第一批记录批大于此值,仍会返回记录批以确保进度可以制作。”
来自文档:“记录是由消费者分批获取的。如果获取的第一个非空分区中的第一个记录批次大于此限制,则仍将返回该批次以确保消费者可以取得进步。”
fetch.max.bytes
(Link)(消费者配置;上面没有提到,但属于同一类别)来自文档:“记录是由消费者分批获取的,如果获取的第一个非空分区中的第一个记录批处理大于此值,则记录批处理仍将返回给确保消费者能够取得进步。”
结论:关于获取消息的配置不需要更改以处理消息,大于这些配置的默认值(在小型设置中测试过)。可能,消费者可能总是得到大小为 1 的批次。但是,必须设置第一个块中的两个配置,如之前的答案所述。
此说明不应说明任何有关性能的信息,也不应建议设置或不设置这些配置。必须根据具体的计划吞吐量和数据结构单独评估最佳值。
答案 8 :(得分:0)
以下是我使用 kafka-python==2.0.2
成功发送高达 100mb 的数据的方法:
经纪人:
consumer = KafkaConsumer(
...
max_partition_fetch_bytes=max_bytes,
fetch_max_bytes=max_bytes,
)
Producer(见文末最终解决方案):
producer = KafkaProducer(
...
max_request_size=KafkaSettings.MAX_BYTES,
)
那么:
producer.send(topic, value=data).get()
像这样发送数据后,出现如下异常:
MessageSizeTooLargeError: The message is n bytes when serialized which is larger than the total memory buffer you have configured with the buffer_memory configuration.
最后我增加了 buffer_memory
(默认 32mb)以在另一端接收消息。
producer = KafkaProducer(
...
max_request_size=KafkaSettings.MAX_BYTES,
buffer_memory=KafkaSettings.MAX_BYTES * 3,
)