当并行度> 1

时间:2019-03-07 14:15:30

标签: apache-kafka apache-flink

我有一个玩具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。

非常感谢。

1 个答案:

答案 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);