我有一个玩具Flink作业,它读取3个kafka主题,然后将所有这3个流合并在一起。仅此而已,无需其他工作。
如果在我的Flink工作中使用并行机制1,一切似乎都很好,因为当我更改并行机制> 1时,它失败了:
java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:693)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:241)
at sun.nio.ch.IOUtil.read(IOUtil.java:195)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at org.apache.kafka.common.network.PlaintextTransportLayer.read(PlaintextTransportLayer.java:110)
at org.apache.kafka.common.network.NetworkReceive.readFromReadableChannel(NetworkReceive.java:97)
at org.apache.kafka.common.network.NetworkReceive.readFrom(NetworkReceive.java:71)
at org.apache.kafka.common.network.KafkaChannel.receive(KafkaChannel.java:169)
at org.apache.kafka.common.network.KafkaChannel.read(KafkaChannel.java:150)
at org.apache.kafka.common.network.Selector.pollSelectionKeys(Selector.java:355)
at org.apache.kafka.common.network.Selector.poll(Selector.java:303)
at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:349)
at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:226)
at org.apache.kafka.clients.consumer.KafkaConsumer.pollOnce(KafkaConsumer.java:1047)
at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:995)
at org.apache.flink.streaming.connectors.kafka.internal.KafkaConsumerThread.run(KafkaConsumerThread.java:257)
它如何与并行性1一起工作,但不适用于并行性> 1?
这与kafka服务器的侧面设置有关吗?还是与我的Java代码中的用户设置有关(我的代码中尚无特殊配置)?
我知道这里提供的信息可能还不够,但是我无法接触kafka集群。我只是希望一些大师之前可能碰到同样的错误,并可以与我分享一些建议。
我正在使用kafka 0.10,flink 1.5。
非常感谢。
答案 0 :(得分:1)
正如您在错误日志中看到的那样,该错误来自您的Kafka集群。当Kafka Broker的直接缓冲内存超过分配给JVM的堆大小时,会发生此问题。根据应用程序的需要,直接缓冲内存是从JVM的堆中分配的。当您使用并行度> 1时,多个Flink任务 min(Flink插槽数,Kafka分区数)将同时消耗Kafka的数据,从而导致更多使用Kafka代理的堆大小为比较并行度等于1时发生的错误。标准解决方案是通过将 KAFKA_HEAP_OPTS 变量添加到 Kafka env文件或作为 OS环境变量来增加可用于Kafka代理的堆大小。 。例如,添加以下行以将堆大小设置为2 GB:
export KAFKA_HEAP_OPTS="-Xms2G -Xmx2G"
但是在您无法访问Kafka代理的情况下(根据您的问题),您可以减少对poll()的单次调用中返回的记录数,因此将需要在代理中使用堆内存减少了。 (这不是标准解决方案,我建议您只是为了消除错误)。
来自this answer:
Kafka Consumers通过以下两种方式处理数据积压 参数,
最大投票间隔.ms
两次调用poll()之间的最大延迟 使用消费者组管理时。这为 消费者在获取更多信息之前可以空闲的时间 记录。如果在此超时时间之前未调用poll(), 则认为该消费者失败了,该小组将重新平衡 为了将分区重新分配给另一个成员。默认值为 300000。最大投票记录
一次返回的最大记录数 调用poll()。默认值为500。根据需要忽略设置以上两个参数 可能导致轮询最大的数据,而消费者可能不会 能够处理可用资源,导致内存不足或 有时无法提供消费者补偿。因此,它总是 建议使用max.poll.records和max.poll.interval.ms 参数。
因此,要进行测试,请将 max.poll.records 的值减小到例如250,然后检查是否会发生错误。
Properties properties = new Properties();
properties.setProperty("bootstrap.servers", BOOTSTRAPSERVERS);
properties.setProperty("group.id", ID);
properties.setProperty("key.deserializer", Serializer);
properties.setProperty("value.deserializer", Deserializer);
properties.setProperty("max.poll.records", "250");
FlinkKafkaConsumer08<String> myConsumer =
new FlinkKafkaConsumer08<>("topic", new SimpleStringSchema(), properties);