resilience4j: JVM running out of threads when I use a Time Limiter (circuit breaker + thread pool bulkhead + time limiter)
Resilience4j version: 1.7
Java version: 8
I’m new to resilience4j (though I have moderate experience with Hystrix) and am trying to learn how to use it to optimize performance under load. Currently the code I’ve written uses: a circuit breaker, a thread pool bulkhead, and a TimeLimiter. I’ve observed that when I decorate the supplier using a Time Limiter, under medium load (around 90 requests per second) the JVM runs out of threads and throws the following exception.
! java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached
This effectively kills the service and causes every request to fail until the service is restarted. When I remove the Time Limiter, this issue goes away. Here is my code:
final CheckedFunction0<? extends HttpResponse> supplierWithCircuitBreaker = Decorators .ofCheckedSupplier(supplier).withCircuitBreaker(circuitBreaker).decorate();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
final CompletableFuture<? extends HttpResponse> async = Decorators.ofSupplier(() -> {
try {
return supplierWithCircuitBreaker.apply();
} catch (Throwable e) {
return handleException(e);
}
}).withThreadPoolBulkhead(threadPoolBulkhead).withTimeLimiter(timeLimiter, scheduler).get().toCompletableFuture();
async.thenAccept(result -> {
LOGGER.info(String.format("Returning value: %s", result.getHttpStatus()));
response.resume(Response.status(result.getHttpStatus()).entity(result).build());
}).exceptionally(e -> {
final StandardResponse errorResponse = handleException(e);
response.resume(Response.status(errorResponse.getHttpStatus()).entity(errorResponse).build());
// without this the compiler complains
return null;
});
Can anyone let me know what I’m doing wrong here?
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 1
- Comments: 15 (6 by maintainers)
@rurouniwallace I had a similar issue. My application was run for 30 min, and I had 8000 threads (with Hystrix I had 200-300 threads). After analysis of threads dumb, I found the root cause. The reason was in
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();. Each time when I decorate supplier by timeLimiter I created a newScheduledExecutorService. All executors were blocked and weren’t removed from application.I changed the implementation to use timeLimiter without scheduler (I use sync way) and after that application working as expected.
@RobWin Could you please suggest how to use the scheduler in timeLimiter? especially how to set size.