使用Akka流无法获得适当的分块响应

时间:2017-05-02 15:11:52

标签: java akka-stream playframework-2.5 chunked

使用Play! Framework documentation中提供的示例,我创建了一个修改版本,发布了一些延迟事件,因此我可以观察到它们在客户端以相同的速率发生:

public Result playExampleDelayed() {
    Source<ByteString, ?> source = Source.<ByteString> actorRef(5, OverflowStrategy.dropNew())
            .mapMaterializedValue(sourceActor -> {
                for (int i = 0; i < 10; ++i) {
                    Thread.sleep(1000);
                    sourceActor.tell(ByteString.fromString("tick " + i), null);
                }
                sourceActor.tell(new Status.Success(NotUsed.getInstance()), null);
                return null;
            });
    return ok().chunked(source);
}

但是,使用curl,我们会在源完成后一步完成所有事件。

使用不同的源类型我可以获得预期的行为:

public Result tick() {
    Source<ByteString, ?> source = Source.<ByteString> tick(Duration.create(0, TimeUnit.SECONDS),
            Duration.create(1, TimeUnit.SECONDS), ByteString.fromString("tick"));
    return ok().chunked(source);
}

在这种情况下,我每秒钟会在控制台中获得一个块。

根据Akka文档,我希望第一个例子可以工作。我做错了什么?

1 个答案:

答案 0 :(得分:2)

您在View.ClickListener电话中使用了Thread.sleep。这是在您mapMaterializedValue您的信息流后立即发生的同步通话。在此处阻止(例如使用run())将阻止整个实现。因此,在循环执行的最后阶段,actor将拾取所有消息。

底线:使用Akka时总是避免使用Thread.sleep

相反,Thread.sleep使用调度程序(异步,非阻塞),因此是一种性能更高,更健壮,更优雅的解决方案。