之前,我们在代码中使用了Bulkhead,CircuitBreaker和Retry,并且一切都按预期进行。 现在我们想使用TimeLimiter,并且我们修改了代码以同时使用ThreadPoolBulkhead,TimeLimiter,CircuitBreaker,Retry和Fallback。 以下是我们当前的配置:
配置文件:
resilience4j.thread-pool-bulkhead:
configs:
default:
maxThreadPoolSize: 50
coreThreadPoolSize: 10
queueCapacity: 100
keepAliveDuration: 5000
instances:
backendA:
baseConfig: default
resilience4j.timelimiter:
configs:
default:
timeoutDuration: 45000
instances:
backendA:
baseConfig: default
fallbackA:
timeoutDuration: 10000
...
Similar configurations for cicuitBreakers and Retry.
下面是我们在代码中的用法:
Decorators
.ofSupplier(() -> test.hello())
.withThreadPoolBulkhead(getThreadPoolBulkheadInstanceFromRegistry())
.withTimeLimiter(getTimeLimiterInstanceFromRegistry(),Executors.newSingleThreadScheduledExecutor())
.withCircuitBreaker(getcircuitBreakerFromRegistry())
.withRetry(getRetryInstanceFromRegistry(),Executors.newSingleThreadScheduledExecutor())
.withFallback(exception -> handleFallback(exception,transaction))
.get()
.toCompletableFuture()
.get();
后退机制与上述机制相同,唯一的不同是,它使用了时间限制器的fallbackA
实例,该实例被配置为在10秒后超时。
在测试系统时(20 tps持续5-10分钟),一切正常。但是,当我们以相同的20tps将负载持续时间增加到3-4小时时,我们注意到系统在40-45分钟内按预期工作,并且交易正在进行。但是之后所有事务开始失败。
如果没有TimeLimter和ThreadPoolBulkhead,同样的事情也会起作用。
上述配置是否有问题? 另外,当我们有线程池隔板时,为什么我们需要提供单独的Scheduled Executor服务?难道不应该使用分配给舱壁的线程吗?
此外,我们尝试在课程级别将Executors.newSingleThreadScheduledExecutor()
更改为Executors.newScheduledThreadPool(10)
。然后,一切都会按预期的方式在积极的情况下进行,但是当我们在hello()上延迟45秒,并且回退也有延迟(也应该从那里超时),并且负载保持不变,即20 tps。
我们注意到最初的2笔交易成功,其余交易失败。但是我们不确定为什么这2笔交易有效(大约花了1分钟40秒),它们也应该失败。