在订购模式下使用AsyncFunc时,我似乎遇到了死锁。
我已经能够将此错误转载如下:
import org.apache.flink.streaming.api.datastream.AsyncDataStream;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.async.AsyncFunction;
import org.apache.flink.streaming.api.functions.async.collector.AsyncCollector;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class AsyncTest {
@Test
public void test() throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
DataStream<Integer> source = env.fromCollection(Arrays.asList(1,2,3,4,5,6,7));
AsyncDataStream.orderedWait(source,
new AsyncFunction<Integer, String>(){
@Override
public void asyncInvoke(Integer integer, AsyncCollector<String> asyncCollector) throws Exception {
AsyncTest.getFuture(integer).whenComplete((t,m) -> {
if (m==null){
asyncCollector.collect(Collections.singleton(t));
return;
}
asyncCollector.collect(m);
});
}
}, 20000, TimeUnit.MILLISECONDS,5)
.returns(String.class)
.print();
env.execute("unit-test");
}
static CompletableFuture<String> getFuture(Integer input) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
if (input == 7){
System.out.println("Returning");
return "ok";
}
System.out.println("Waking up");
throw new RuntimeException("test");
},new ScheduledThreadPoolExecutor(10));
}
}
我认为这种僵局可能来自于 OrderedStreamElementQueue 的基础 ArrayQueue 首先被不完整的未来填满。
当发射器试图从此队列中查看时,由于没有完成任何未来,发射器会暂停其执行。
当期货完成时,它们会异常完成,因此不会触发应该在 headIsCompleted 上调用signalAll的 onCompleteHandler 方法(并因此唤醒发射器线程)
同时,当队列已满时,对 orderedStreamElement 的 tryPut 的任何调用都会返回false,因此没有 StreamElementQueueEntry 可以通过调用 onCompleteHandler 进行链接。
所以,似乎Emitter线程无法被唤醒。
这只是我的猜测。也许我弄错了。但是当我在本地运行上面的代码时,执行永远不会结束。
除了增加队列的容量和/或作业的并行性之外,有没有办法克服这个问题?
答案 0 :(得分:1)
您的分析是正确的。问题是StreamElementQueueEntry
没有对其未来的特殊完成做出反应。因此,每当发生超时或其他异常时,StreamElementQueueEntry
未正确设置为已完成,并且Emitter
未收到有关新完成条目的通知。
FLINK-6435修复了问题,该问题已合并到Flink主页。