我正在尝试在Akka Streams javadsl中使用RestartFlow
来重新启动我的流程阶段之一,如果在该阶段发生任何故障,但是它似乎并没有在重启流程,而是丢弃了该消息
我已经看到以下内容:RestartFlow in Akka Streams not working as expected,但是我的版本是2.5.19,因此应该对其进行修复?
我已经尝试过RestartFlow.onFailuresWithBackoff
和RestartFlow.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
如果有人可以帮助我指出正确的方向,
答案 0 :(得分:0)
它的工作方式有些不同。长话短说-如果发生错误,则会丢弃该消息,但是将仅重新启动源/流,而不会杀死整个流。在RestartFlow.onFailuresWithBackoff documentation中进行了描述:
重新启动过程本质上是有损失的,因为取消和消息发送之间没有协调。来自包装流的任一端的终止信号将导致另一端终止,并且任何传输中的消息都将丢失。在回退期间,此流将回压。