"Buffer pool is destroyed" 当我使用 Flink SlidingEventTimeWindows
"Buffer pool is destroyed" when I use Flink SlidingEventTimeWindows
Flink 在我使用 "SlidingEventTimeWindows" 时抛出 "java.lang.IllegalStateException: Buffer pool is destroyed",但是当我更改为 "SlidingProcessingTimeWindows".
时一切正常
堆栈跟踪如下:
18:37:53,728 WARN org.apache.flink.streaming.api.operators.AbstractStreamOperator - Error while emitting latency marker.
java.lang.RuntimeException: Buffer pool is destroyed.
at org.apache.flink.streaming.runtime.io.RecordWriterOutput.emitLatencyMarker(RecordWriterOutput.java:147)
at org.apache.flink.streaming.api.operators.AbstractStreamOperator$CountingOutput.emitLatencyMarker(AbstractStreamOperator.java:683)
at org.apache.flink.streaming.api.operators.StreamSource$LatencyMarksEmitter.onProcessingTime(StreamSource.java:151)
at org.apache.flink.streaming.runtime.tasks.SystemProcessingTimeService$RepeatedTriggerTask.run(SystemProcessingTimeService.java:330)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Buffer pool is destroyed.
at org.apache.flink.runtime.io.network.buffer.LocalBufferPool.requestMemorySegment(LocalBufferPool.java:230)
at org.apache.flink.runtime.io.network.buffer.LocalBufferPool.requestBufferBuilderBlocking(LocalBufferPool.java:204)
at org.apache.flink.runtime.io.network.api.writer.RecordWriter.requestNewBufferBuilder(RecordWriter.java:213)
at org.apache.flink.runtime.io.network.api.writer.RecordWriter.sendToTarget(RecordWriter.java:144)
at org.apache.flink.runtime.io.network.api.writer.RecordWriter.randomEmit(RecordWriter.java:125)
at org.apache.flink.streaming.runtime.io.StreamRecordWriter.randomEmit(StreamRecordWriter.java:93)
at org.apache.flink.streaming.runtime.io.RecordWriterOutput.emitLatencyMarker(RecordWriterOutput.java:144)
... 10 more
我终于解决了下面的步骤。
首先,将My DataMockSource中的"collect"替换为"collectWithTimestamp",用于生成流data.After这样做,"Error while emitting latency marker"将在控制台中消失。
其次,将BoundedOutOfOrdernessTimestampExtractor替换为AscendingTimestampExtractor,用于EventTime processing.In我的DataMockSource,我生成数据并同时发出,所以AscendingTimestampExtractor是生成水印的正确方法。
我post这里的主要代码,以及github上的完整项目。希望对你有帮助。
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
env.enableCheckpointing(10000); //
DataStreamSource<MockData> mockDataDataStreamSource = env.addSource(new DataMockSource());
mockDataDataStreamSource.assignTimestampsAndWatermarks(
new AscendingTimestampExtractor<MockData>() {
@Override
public long extractAscendingTimestamp(MockData element) {
return element.getTimestamp();
}
});
SingleOutputStreamOperator<Tuple2<String, Long>> countStream = mockDataDataStreamSource
.keyBy("country").window(
SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(10)))
// .allowedLateness(Time.seconds(5))
.process(
new FlinkEventTimeCountFunction()).name("count elements");
countStream.addSink(new SinkFunction<Tuple2<String, Long>>() {
@Override
public void invoke(Tuple2<String, Long> value, Context context) throws Exception {
System.out.println(value);
}
});
env.execute("count test ");
我的 DataMockSource 在这里:
private volatile boolean running = true;
@Override
public void run(SourceContext sourceContext) throws Exception {
while (running){
MockData mockData = new MockData();
mockData.setAge(ThreadLocalRandom.current().nextInt(1,99));
mockData.setCountry("country "+ThreadLocalRandom.current().nextInt(2,5));
mockData.setId(ThreadLocalRandom.current().nextLong());
mockData.setTimestamp(Instant.now().toEpochMilli());
// emit record with timestamp
sourceContext.collectWithTimestamp(mockData,Instant.now().toEpochMilli());
// sourceContext.collect(mockData);
TimeUnit.SECONDS.sleep(3);
}
}
@Override
public void cancel() {
running = false;
}
在事件时间工作时,您需要在源中或使用 assignTimestampsAndWatermarks 安排时间戳提取和水印。看起来你没有这样做,这可以解释为什么你不会得到任何输出(事件时间 window 永远不会被触发)。
此外,您的来源应该有一个取消方法。像这样:
private volatile boolean running = true;
@Override
public void run(SourceContext ctx) throws Exception {
while (running) {
...
}
}
@Override
public void cancel() {
running = false;
}
我认为这可以解释您所看到的异常。也许源继续 运行 并在作业开始自行关闭后发送延迟标记。
Flink 在我使用 "SlidingEventTimeWindows" 时抛出 "java.lang.IllegalStateException: Buffer pool is destroyed",但是当我更改为 "SlidingProcessingTimeWindows".
时一切正常堆栈跟踪如下:
18:37:53,728 WARN org.apache.flink.streaming.api.operators.AbstractStreamOperator - Error while emitting latency marker.
java.lang.RuntimeException: Buffer pool is destroyed.
at org.apache.flink.streaming.runtime.io.RecordWriterOutput.emitLatencyMarker(RecordWriterOutput.java:147)
at org.apache.flink.streaming.api.operators.AbstractStreamOperator$CountingOutput.emitLatencyMarker(AbstractStreamOperator.java:683)
at org.apache.flink.streaming.api.operators.StreamSource$LatencyMarksEmitter.onProcessingTime(StreamSource.java:151)
at org.apache.flink.streaming.runtime.tasks.SystemProcessingTimeService$RepeatedTriggerTask.run(SystemProcessingTimeService.java:330)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Buffer pool is destroyed.
at org.apache.flink.runtime.io.network.buffer.LocalBufferPool.requestMemorySegment(LocalBufferPool.java:230)
at org.apache.flink.runtime.io.network.buffer.LocalBufferPool.requestBufferBuilderBlocking(LocalBufferPool.java:204)
at org.apache.flink.runtime.io.network.api.writer.RecordWriter.requestNewBufferBuilder(RecordWriter.java:213)
at org.apache.flink.runtime.io.network.api.writer.RecordWriter.sendToTarget(RecordWriter.java:144)
at org.apache.flink.runtime.io.network.api.writer.RecordWriter.randomEmit(RecordWriter.java:125)
at org.apache.flink.streaming.runtime.io.StreamRecordWriter.randomEmit(StreamRecordWriter.java:93)
at org.apache.flink.streaming.runtime.io.RecordWriterOutput.emitLatencyMarker(RecordWriterOutput.java:144)
... 10 more
我终于解决了下面的步骤。
首先,将My DataMockSource中的"collect"替换为"collectWithTimestamp",用于生成流data.After这样做,"Error while emitting latency marker"将在控制台中消失。
其次,将BoundedOutOfOrdernessTimestampExtractor替换为AscendingTimestampExtractor,用于EventTime processing.In我的DataMockSource,我生成数据并同时发出,所以AscendingTimestampExtractor是生成水印的正确方法。
我post这里的主要代码,以及github上的完整项目。希望对你有帮助。
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
env.enableCheckpointing(10000); //
DataStreamSource<MockData> mockDataDataStreamSource = env.addSource(new DataMockSource());
mockDataDataStreamSource.assignTimestampsAndWatermarks(
new AscendingTimestampExtractor<MockData>() {
@Override
public long extractAscendingTimestamp(MockData element) {
return element.getTimestamp();
}
});
SingleOutputStreamOperator<Tuple2<String, Long>> countStream = mockDataDataStreamSource
.keyBy("country").window(
SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(10)))
// .allowedLateness(Time.seconds(5))
.process(
new FlinkEventTimeCountFunction()).name("count elements");
countStream.addSink(new SinkFunction<Tuple2<String, Long>>() {
@Override
public void invoke(Tuple2<String, Long> value, Context context) throws Exception {
System.out.println(value);
}
});
env.execute("count test ");
我的 DataMockSource 在这里:
private volatile boolean running = true;
@Override
public void run(SourceContext sourceContext) throws Exception {
while (running){
MockData mockData = new MockData();
mockData.setAge(ThreadLocalRandom.current().nextInt(1,99));
mockData.setCountry("country "+ThreadLocalRandom.current().nextInt(2,5));
mockData.setId(ThreadLocalRandom.current().nextLong());
mockData.setTimestamp(Instant.now().toEpochMilli());
// emit record with timestamp
sourceContext.collectWithTimestamp(mockData,Instant.now().toEpochMilli());
// sourceContext.collect(mockData);
TimeUnit.SECONDS.sleep(3);
}
}
@Override
public void cancel() {
running = false;
}
在事件时间工作时,您需要在源中或使用 assignTimestampsAndWatermarks 安排时间戳提取和水印。看起来你没有这样做,这可以解释为什么你不会得到任何输出(事件时间 window 永远不会被触发)。
此外,您的来源应该有一个取消方法。像这样:
private volatile boolean running = true;
@Override
public void run(SourceContext ctx) throws Exception {
while (running) {
...
}
}
@Override
public void cancel() {
running = false;
}
我认为这可以解释您所看到的异常。也许源继续 运行 并在作业开始自行关闭后发送延迟标记。