Resilience4j 舱壁线程行为

jav*_*Try 5 spring-boot resilience4j

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

我使用的是 spring-boot 2.2.5,resilience4j 1.4.0。Ga特林(加载工具)、VisualVM(分析线程)

我意识到:

  1. 当我使用舱壁类型 = SEMAPHORE 时。

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

    maxConcurrentCalls, maxWaitDuration 
    
    Run Code Online (Sandbox Code Playgroud)

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

  2. 当我使用批量 THREADPOOL 时,这些配置将起作用:

    maxThreadPoolSize, coreThreadPoolSize, queueCapacity, keepAliveDuration
    
    Run Code Online (Sandbox Code Playgroud)

    这些配置将被忽略:

    maxConcurrentCalls, maxWaitDuration 
    
    Run Code Online (Sandbox Code Playgroud)

我的代码:

@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");
    }
}
Run Code Online (Sandbox Code Playgroud)

配置:

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
Run Code Online (Sandbox Code Playgroud)

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

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

问题是:

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

舱壁-MyService-1、舱壁-MyService-2、舱壁-MyService-3

问题是什么?

2 - 我做了这个配置:

    maxThreadPoolSize: 1
    coreThreadPoolSize: 1
    queueCapacity: 2
    keepAliveDuration: 3
Run Code Online (Sandbox Code Playgroud)

我配置slowService需要10s,太慢了。

我一次做了 3 个请求,系统的行为如下:

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

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

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

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

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

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

关于 keepAliveDuration,线程将在空闲达到配置的时间后终止。coreThreadSize将处于空闲状态,只有多余的线程才会被终止。

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

现在我只想知道 THREADPOOL 和 SEMAPHORE 之间的行为差​​异?