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

Java 如何使用卡夫卡(超过15MB)发送大型邮件?,java,apache-kafka,Java,Apache Kafka,我使用Java Producer API向Kafka V.0.8发送字符串消息。 如果消息大小约为15 MB,我会得到一个MessageSizeTooLargeException。 我已尝试将message.max.bytes设置为40 MB,但仍然出现异常。小消息工作没有问题 (例外情况出现在生产者中,我在此应用程序中没有消费者。) 我能做些什么来消除这个异常 我的示例producer config 错误日志: 需要记住的一点是,message.max.bytes属性必须与使用者的fetch.

我使用Java Producer API向Kafka V.0.8发送字符串消息。 如果消息大小约为15 MB,我会得到一个
MessageSizeTooLargeException
。 我已尝试将
message.max.bytes
设置为40 MB,但仍然出现异常。小消息工作没有问题

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

我能做些什么来消除这个异常

我的示例producer config 错误日志:
需要记住的一点是,
message.max.bytes
属性必须与使用者的
fetch.message.max.bytes
属性同步。获取大小必须至少与最大消息大小一样大,否则可能会出现生产者发送的消息大于消费者消费/获取的情况。也许值得一看
您使用的是哪个版本的卡夫卡?还提供一些您正在获得的详细信息。有没有像<代码>大于xxxx的有效负载大小 日志中出现的超过1000000个属性?

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

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

我发现了第2条的难处——你没有从卡夫卡那里得到任何异常、消息或警告,所以在发送大消息时一定要考虑这一点。

你需要重写以下属性:

代理配置($KAFKA\u HOME/config/server.properties)

  • replica.fetch.max.bytes
  • message.max.bytes
消费者配置($KAFKA\u HOME/config/Consumer.properties)
这一步对我不起作用。我将其添加到消费者应用程序中,效果良好

  • fetch.message.max.bytes
重新启动服务器

有关更多信息,请参阅本文档:

这个想法是让卡夫卡制作人向卡夫卡经纪人发送相同大小的消息,然后卡夫卡消费者接收,即

卡夫卡制作人-->卡夫卡经纪人-->卡夫卡消费者

假设如果要求发送15MB的消息,那么生产者、代理和消费者三者都需要同步

卡夫卡制作人发送15 MB-->卡夫卡经纪人允许/存储15 MB-->卡夫卡消费者接收15 MB

因此,设置应为:

a) 关于经纪人:

message.max.bytes=15728640 
replica.fetch.max.bytes=15728640
b) 关于消费者:

fetch.message.max.bytes=15728640

卡夫卡0.10所需的微小更改,与以下内容相比:

  • 代理:没有更改,您仍然需要增加属性
    message.max.bytes
    replica.fetch.max.bytes
    message.max.bytes
    必须等于或小于
    replica.fetch.max.bytes
  • 生产者:增加
    max.request.size
    以发送更大的消息
  • 使用者:增加
    max.partition.fetch.bytes
    以接收更大的消息

(*)阅读评论以了解更多有关
消息的信息。max.bytes
来自@laugh\u man的答案非常准确。不过,我还是想提出一个建议,这是我从卡夫卡专家那里学到的。我们积极地将此解决方案应用到我们的实时系统中

卡夫卡不适合处理大型邮件。

您的API应该使用云存储(例如AWS S3),只需将S3的引用推送到Kafka或任何消息代理即可。您必须找到保存数据的地方,可能是网络驱动器,可能是其他什么,但不应该是消息代理

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

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

如果您真的关心拆分消息,请确保每个消息拆分都具有完全相同的键,以便将其推送到同一分区,并且您的消息内容应该报告一个“部分id”,以便您的消费者可以完全重建消息

如果您的消息是基于文本的(gzip、snappy、lz4压缩),您还可以探索压缩,这可能会减少数据大小,但不是神奇的

同样,您必须使用一个外部系统来存储该数据,只需将外部引用推送到卡夫卡即可。这是一个非常常见的体系结构,您应该使用它,并被广泛接受

记住,卡夫卡只有在信息数量巨大但大小不一的情况下才能发挥最佳效果。


来源:

对于使用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,则在producer配置中传递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",
   ... .. }                                                                                                                                                                                                                                                      

我认为,这里的大多数答案都有些过时或不完全完整

要参考(带有卡夫卡0.10的更新),我
  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",
   ... .. }