在我们的应用程序中,我们使用kafka组件以手动提交方式使用来自kafka主题的消息。如果我们在后续过程中遇到异常(外部服务调用失败-抛出RetryableException),我们已在ThrottlingExceptionRoutePolicy中进行连线以打开电路并基于HalfOpenHandler重试电路关闭,则遇到RetryableException。
ThrottlingExceptionRoutePolicy { 油门异常-RetryableException, failureThreshold-1, failureWindow = 1分钟 halfOpenAfter-x分钟 keepOpen =假 }
from(“ kafka:topicName”)。routePolicy(exceptionPolicy).to(anotherProcess);
当我们在每个吊舱中运行单个使用者时,电路的打开/关闭将按预期工作。但是在有多个使用者的情况下,电路断开,但未尝试闭合。
查看ThrottlingExceptionRoutePolicy代码:
第一和第二使用者线程都在等待获取锁。
线程T1获取锁定,线程T2正在等待。
消费者已停止,STATE为OPEN,policy.openedAt-t1,halfOpenTask(h1)计划在x(阈值)毫秒后运行,policy.halfOpenTimer => h1
锁已释放
线程T2获取锁定。
消费者已经停止,STATE仍为OPEN,policy.openedAt = t2(t2> t1),halfOpenTask(h2-新实例)计划在x ms之后运行。 policy.halfOpenTimer => h2。
所有这些时间h1计时器都在递减计数。计时器完成后,HalfOpen任务将排队并开始。
在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的任何骆驼路线上。
有人遇到类似的问题吗?
答案 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,否则不会设置失败。这是一个错误。