骆驼-RoutePolicy-ThrottlingExceptionRoutePolicy不适用于多个使用者

时间:2020-09-30 19:30:39

标签: apache-kafka apache-camel

在我们的应用程序中,我们使用kafka组件以手动提交方式使用来自kafka主题的消息。如果我们在后续过程中遇到异常(外部服务调用失败-抛出RetryableException),我们已在ThrottlingExceptionRoutePolicy中进行连线以打开电路并基于HalfOpenHandler重试电路关闭,则遇到RetryableException。

ThrottlingExceptionRoutePolicy { 油门异常-RetryableException, failureThreshold-1, failureWindow = 1分钟 halfOpenAfter-x分钟 keepOpen =假 }

from(“ kafka:topicName”)。routePolicy(exceptionPolicy).to(anotherProcess);

当我们在每个吊舱中运行单个使用者时,电路的打开/关闭将按预期工作。但是在有多个使用者的情况下,电路断开,但未尝试闭合。

查看ThrottlingExceptionRoutePolicy代码:

第一和第二使用者线程都在等待获取锁。

  1. 线程T1获取锁定,线程T2正在等待。

  2. 消费者已停止,STATE为OPEN,policy.openedAt-t1,halfOpenTask(h1)计划在x(阈值)毫秒后运行,policy.halfOpenTimer => h1

  3. 锁已释放

  4. 线程T2获取锁定。

  5. 消费者已经停止,STATE仍为OPEN,policy.openedAt = t2(t2> t1),halfOpenTask(h2-新实例)计划在x ms之后运行。 policy.halfOpenTimer => h2。

  6. 所有这些时间h1计时器都在递减计数。计时器完成后,HalfOpen任务将排队并开始。

  7. 在HalfOpen任务的运行方法中->
    7.取消策略.halfOpenTimer(h2) 7.b因此取消了h2半开计划任务 7.c调用this.calculateState()

            7.c.1  check the state is OPEN and if elapsedTime >= threshold X  , then call half-open handler
                   but the  elapsedTime is currentTs (t1+x) - openedAt(t2) so the condition is never 
                   true. So the half-open handler is never called. 
    

这可能发生在并发消费者大于1的任何骆驼路线上。

有人遇到类似的问题吗?

1 个答案:

答案 0 :(得分:0)

它也发生在一个 concurrentConsumers=1 的情况下 与 concurrencyLimit: 50 显然计时器永远不会关闭电路。这是记录的最后一条语句。 2021-08-04 15:56:59.473 DEBUG 99845 --- [askExecutor-104] o.a.c.t.ThrottlingExceptionRoutePolicy:开路...

此外,ThrottlingExceptionRoutePolicy.failures 只会在超过 failureWindow 的情况下继续递增。

    protected boolean isThresholdExceeded() {
    boolean output = false;
    this.logState();
    if (this.failures.get() >= this.failureThreshold && this.lastFailure >= System.currentTimeMillis() - this.failureWindow) {
        output = true;
    }

    return output;
}

只要 failures >= failureThreshold(将在某个时间点)并且 lastFailure 发生在 failureWindow 内,“输出”就会为真。 除非调用 closeCircuit,否则不会设置失败。这是一个错误。