Akka流onFailuresWithBackoff不会重新启动流

时间:2019-01-17 23:32:22

标签: java akka akka-stream akka-http

我正在尝试在Akka Streams javadsl中使用RestartFlow来重新启动我的流程阶段之一,如果在该阶段发生任何故障,但是它似乎并没有在重启流程,而是丢弃了该消息

我已经看到以下内容:RestartFlow in Akka Streams not working as expected,但是我的版本是2.5.19,因此应该对其进行修复?

我已经尝试过RestartFlow.onFailuresWithBackoffRestartFlow.withBackoff,但都没有用。我也尝试过使用整个Actor系统主管策略,但这似乎只是拦截异常,这样它就不会从流程中抛出,而且似乎也没有提供我想要的退避和最大重试策略。

流:

public Consumer.DrainingControl<Done> stream() {
    return Consumer.committableSource(consumerSettings,
        Subscriptions.topics(config.getString(ConfigKeys.KAFKA_CONFIG_PREFIX +
            ConfigKeys.CONSUMER_TOPIC)))
        .via(RestartFlow.onFailuresWithBackoff(
                Duration.ofSeconds(1), // min backoff
                Duration.ofSeconds(2), // max backoff,
                0.2, // adds 20% "noise" to vary the intervals slightly
                10, // limits the amount of restarts to 10
                this::dispatchMessageFlow))
        .via(Committer.flow(CommitterSettings.create(system)))
        .toMat(Sink.ignore(), Keep.both())
        .mapMaterializedValue(Consumer::createDrainingControl)
        .run(mat);
}

然后是流程:

private Flow<ConsumerMessage.CommittableMessage<String, String>,
    ConsumerMessage.Committable, NotUsed> dispatchMessageFlow() {
    return Flow.<ConsumerMessage.CommittableMessage<String, String>>create()
            .mapAsyncUnordered(
                config.getInt(ConfigKeys.PARALLELISM),
                msg ->
                    streamProcessor.process(msg.record().value())
                        .whenComplete((done, e) -> {
                            if (e != null) {
                                throw new RuntimeException(e);
                            } else {
                                if (done.status().isSuccess()){
                                    streamingConsumerLogger.info("Successfully posted message, got response:\n{}",
                                        done.toString());
                                } else {
                                    throw new RuntimeException("HTTP Error!");
                                }
                            }
                        })
                        .thenApply(done -> msg.committableOffset()));
}

我见过一次异常,akka指出由于失败将重新启动图形,但此后没有其他事情。根据我的理解,我应该再看10次。消费者继续收听新消息,因此好像消息刚刚被丢弃。

java.util.concurrent.CompletionException: java.lang.RuntimeException: HTTP Error!
    at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
    at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
    at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:769)
    at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736)
    at java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:443)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.RuntimeException: HTTP Error!
    at com.company.app.messageforwarder.StreamingConsumerService.lambda$null$0(StreamingConsumerService.java:72)
    at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760)
    ... 6 more

如果有人可以帮助我指出正确的方向,

1 个答案:

答案 0 :(得分:0)

它的工作方式有些不同。长话短说-如果发生错误,则会丢弃该消息,但是将仅重新启动源/流,而不会杀死整个流。在RestartFlow.onFailuresWithBackoff documentation中进行了描述:

  

重新启动过程本质上是有损失的,因为取消和消息发送之间没有协调。来自包装流的任一端的终止信号将导致另一端终止,并且任何传输中的消息都将丢失。在回退期间,此流将回压。