Java 反应器中的自动速率调节 TL;博士

Java 反应器中的自动速率调节 TL;博士,java,apache-kafka,reactive-programming,project-reactor,circuit-breaker,Java,Apache Kafka,Reactive Programming,Project Reactor,Circuit Breaker,是否有一种方法可以根据下游健康状况自动调整项目反应堆中各元件之间的延迟 更多详细信息 我有一个应用程序,它从卡夫卡主题中读取记录,为每个记录发送一个HTTP请求,并将结果写入另一个卡夫卡主题。从/到Kafka的读写既快速又简单,但是第三方HTTP服务很容易被淹没,因此我使用属性文件中的值使用delayElements(),这意味着该值在应用程序运行时不会更改。下面是一个代码示例: kafkaReceiver.receiveAutoAck() .concatMap(iden

是否有一种方法可以根据下游健康状况自动调整项目反应堆中各元件之间的延迟

更多详细信息 我有一个应用程序,它从卡夫卡主题中读取记录,为每个记录发送一个HTTP请求,并将结果写入另一个卡夫卡主题。从/到Kafka的读写既快速又简单,但是第三方HTTP服务很容易被淹没,因此我使用属性文件中的值使用
delayElements()
,这意味着该值在应用程序运行时不会更改。下面是一个代码示例:

kafkaReceiver.receiveAutoAck()
            .concatMap(identity())
            .delayElements(ofMillis(delayElement))
            .flatMap(message -> recordProcessingFunction.process(message.value()), messageRate)
            .onErrorContinue(handleError())
            .map(this::getSenderRecord)
            .flatMap(kafkaSender::send)
但是,第三方服务可能会在加班时执行不同的操作,我希望能够相应地调整此延迟。比方说,如果我看到超过5%的请求在10秒内失败,我会增加延迟。如果它在10秒以上低于5%,那么我会再次减少延迟


反应堆中是否存在这样的机制?我可以从我这边想到一些创造性的解决方案,但我想知道他们(或其他人)是否已经实现了这一点。

我认为任何HTTP客户端(包括netty)都不会提供反压力。一种选择是切换到RSocket,但如果您正在呼叫第三方服务,我想这可能不是一种选择。您可以调整一个在一天中大部分时间都有效的速率,并使用doOnError或类似工具将出错的消息发送到另一个主题。另一个接收者可以以更高的延迟处理这些消息,如果消息再次出错,则将消息放回同一主题,并进行重试计数,以便您最终可以停止处理它们。

如果您正在查找延迟元素,则取决于元素处理速度,您可以使用


您可以使用指数退避添加重试。像这样的事情:

influx()
.flatMap(x -> Mono.just(x)
    .map(data -> apiCall(data))
    .retryWhen(
            Retry.backoff(Integet.MAX_VALUE, Duration.ofSeconds(30))
                .filter(err -> err instanceof RuntimeException)
                .doBeforeRetry(
                    s -> log.warn("Retrying for err {}", s.failure().getMessage()))
                .onRetryExhaustedThrow((spec, sig) -> new RuntimeException("ex")))
                .onErrorResume(err -> Mono.empty()),
        concurrency_val,
        prefetch_val)
这将重试失败的请求Integet.MAX_VALUE次,每次重试之间的最短时间为30秒。随后的重试实际上由一个可配置的抖动因子(默认值=0.5)偏移,导致连续重试之间的持续时间增加

Retry.backoff
上的文档说明:

为具有抖动的指数退避策略预先配置的RetryBackoffSpec,给定最大重试次数和退避的最小持续时间

此外,由于整个操作都映射在
flatMap
中,因此您可以更改它的默认
并发性
预取
值,以说明在整个管道等待RetryBackOffSpec成功完成时,在任何给定时间可能失败的最大请求数


最糟糕的情况是,您的
并发性\u val
请求数失败,并等待30秒以上的时间重试。如果下游系统不能及时恢复,整个操作可能会停止(仍在等待下游的成功),这可能是不可取的。最好将回退限制从
Integer.MAX\u VALUE
替换为可管理的值,超过该值,它将只记录错误并继续下一个事件。

您是否有kafka和HTTP调用的反应驱动程序?这些问题应该通过HTTP客户机的背压(或整个背压)来解决,不耽误个人的时间elements@arap你能提供一个这样的驱动程序的例子吗?看看这一个Kafka:和Spring Webclient forHTTP@arap这正是我正在使用的库,但是如果我将它们发送到另一个主题或使用内置的重试机制,初始客户端将继续以相同的速率发送请求,导致性能进一步下降这并不是我想要的。如果我开始接收5XX错误,我需要能够以较慢的速度将元素发送到下游HTTP服务,如果错误停止,我需要以较快的速度恢复
influx()
.flatMap(x -> Mono.just(x)
    .map(data -> apiCall(data))
    .retryWhen(
            Retry.backoff(Integet.MAX_VALUE, Duration.ofSeconds(30))
                .filter(err -> err instanceof RuntimeException)
                .doBeforeRetry(
                    s -> log.warn("Retrying for err {}", s.failure().getMessage()))
                .onRetryExhaustedThrow((spec, sig) -> new RuntimeException("ex")))
                .onErrorResume(err -> Mono.empty()),
        concurrency_val,
        prefetch_val)