Я провожу много тестов, используя Resilience4j и отслеживаю поведение потоков.
Я использую spring-boot 2.2.5, resilience4j 1.4.0. Гатлинг (инструмент загрузки), visualvm (анализ потока)
Я понял, что:
1 - когда я использую переборку типа = SEMAPHORE. Я понял, что при выполнении asyn c будет использоваться ExecutorService по умолчанию, в данном случае ForkJoinPool, и эта конфигурация будет работать:
maxConcurrentCalls, maxWaitDuration
Если вы используете тип переборки = 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 - мое приложение привязано к вводу-выводу, когда я sh когда Есть много запросов (40 / с), когда пул потоков, созданный resilience4j, достиг максимального значения MaxThreadPoolSize, но было создано только 3 потока (количество ядер процессора -1). Я видел, что они создают только:
переборка-MyService-1, налив head-MyService-2, переборка-MyService-3
В чем проблема?
2 - я сделал эту конфигурацию:
maxThreadPoolSize: 1
coreThreadPoolSize: 1
queueCapacity: 2
keepAliveDuration: 3
Я настроил slowService на 10 секунд, поэтому медленно. Я сделал 3 запроса за раз, система вела себя так:
- Процесс только 1 за раз, это нормально, потому что ядро и maxThread равны 1.
- Запрос был отправлен , это нормально, потому что queueCapacity равен 2.
Но я надеюсь, что запрос, ожидающий в очереди, будет ждать только 3 мс, потому что это настроенное время.
Как я могу ограничить максимальное время ожидания потока в очереди?
[Редактировать] [обновить] Я провел больше тестов и понял, что:
Пока поток занят, другие поступающие запросы будут запускать новую задачу до достижения coreThread, если все coreThread заняты.
Если пул достигает coreThread, каждый новый запрос будет помещен в очередь после очереди заполнен, новые запросы будут создавать новые потоки, пока не будет перечитан maxPoolThread.
О keepAliveDuration, потоки будут прерываться после простоя в течение заданного времени. CoreThreadSize будет простаивать, будет прервана только лишняя нить.
Все мои сомнения были даны ответом на мои тесты.
Пока я хотел бы просто узнать о Различное поведение между THREADPOOL и SEMAPHORE?