3

我正在使用 Resilience4j 进行大量测试并监控线程的行为。

我正在使用 spring-boot 2.2.5,resilience4j 1.4.0。Gatling(加载工具),visualvm(分析线程)

我意识到:

  1. 当我使用隔板类型 = SEMAPHORE.

    我意识到异步执行将使用默认的 ExecutorService,在这种情况下,ForkJoinPool 和此配置将起作用:

    maxConcurrentCalls, maxWaitDuration 
    

    如果您使用的是bulkhead type = THREADPOOL,上述配置将被忽略。

  2. 当我使用散装的 THREADPOOL 时,这些配置将起作用:

    maxThreadPoolSize, coreThreadPoolSize, queueCapacity, keepAliveDuration
    

    这些配置将被忽略:

    maxConcurrentCalls, maxWaitDuration 
    

我的代码:

@CircuitBreaker(name = MyServiceCommand.BEAN_NAME, fallbackMethod = "fallback")
@TimeLimiter(name = MyServiceCommand.BEAN_NAME)
@Bulkhead(name = MyServiceCommand.BEAN_NAME, type = Bulkhead.Type.THREADPOOL)
@Component
@AllArgsConstructor
@Slf4j
public class MyServiceCommand extends ResilienceAbstractCommand {

    protected static final String BEAN_NAME = "MyService";

    private SlowService slowService;

    public CompletableFuture<String> perform() {

        return CompletableFuture.completedFuture(slowService.get());
    }

    private CompletableFuture<String> fallback() {
        return CompletableFuture.completedFuture("fallback");
    }
}

配置:

resilience4j.circuitbreaker:
    configs:
        default:
            failureRateThreshold: 40
            waitDurationInOpenState: 20s
            minimumNumberOfCalls: 5
            slowCallRateThreshold: 30
            slowCallDurationThreshold: 300s
    instances:
        MyService:
            baseConfig: default
            ignoreExceptions:
                - com.hotmart.display.commons.exception.BusinessException

resilience4j.bulkhead:
    configs:
        default:
            maxConcurrentCalls: 800
            maxWaitDuration: 15000
    instances:
        MyService:
            baseConfig: default

resilience4j.thread-pool-bulkhead:
    configs:
        default:
            maxThreadPoolSize: 10
            queueCapacity: 500
    instances:
        MyService:
            baseConfig: default

resilience4j.timelimiter:
    configs:
        default:
            timeoutDuration: 300s
            cancelRunningFuture: true
    instances:
        MyService:
            baseConfig: default

SlowService 对另一个应用程序进行慢速网络调用

我配置这些值只是为了测试,在生产中这些值会有所不同。

问题是:

1 - 我的应用程序是 I/O Bound,我希望当有很多请求(40/s)时,resilience4j 创建的线程池达到 maxThreadPoolSize 数量,但只创建了 3 个线程(cpu 核心数量 -1)我看到了仅创建:

隔板-MyService-1、隔板-MyService-2、隔板-MyService-3

问题是什么?

2 - 我做了这个配置:

    maxThreadPoolSize: 1
    coreThreadPoolSize: 1
    queueCapacity: 2
    keepAliveDuration: 3

我将 slowService 配置为 10 秒,太慢了。

我一次做了 3 个请求,系统的行为是这样的:

  • 一次只处理1个,没关系,因为core和maxThread都是1。
  • 请求被查询了,没问题,因为queueCapacity是2。

但是,我希望在队列中等待的请求只等待 3ms,因为是配置的时间。

如何限制线程在队列中等待的最长时间?

[编辑][更新] 我做了更多的测试并意识到:

当一个线程忙时,如果所有 coreThread 都忙,另一个到达的请求将启动一个新任务,直到到达 coreThread。

如果池到达 coreThread,每个新请求都会被放入队列,队列满后,新请求会创建新线程,直到达到 maxPoolThread。

关于 keepAliveDuration,线程将在空闲一段时间后终止。coreThreadSize 将处于空闲状态,只会终止多余的线程。

我所有的疑问都通过我的测试得到了解答。

现在我只想知道 THREADPOOL 和 SEMAPHORE 之间的不同行为?

4

0 回答 0