Resilience4j: Thread-pool-bulkhead and Bulkhead

Created on 29 Jan 2020  路  4Comments  路  Source: resilience4j/resilience4j

Thanks for raising a Resilience4j issue.
Please provide a brief description of your problem along with the versions you are using.
If possible, please also consider putting together a complete JUnit test that reproduces the issue.

Resilience4j version:
1.2.0
Java version:
1.8
Problem description:
I am unable to find an example with clarity or documentation with clarity as what is ThreadPoolBuilkhead, BulkHead and Semaphore Bulkhead are the same?. I am using annotation based BulkHead pattern. I have the following configuration.

resilience4j.bulkhead:
configs:
default:
registerHealthIndicator: true
maxConcurrentCalls: 5

resilience4j.thread-pool-bulkhead:
configs:
default:
registerHealthIndicator: true
maxThreadPoolSize: 1
coreThreadPoolSize: 1
queueCapacity: 1

I have lost bit clarity on what are the key differences between the two builkhead implementations when it comes to usecases. The documentation doesn't give info regarding the same. So I need help interns of documentation or a simple clarification would help me a lot in using this library with more understanding.

Thanks
Krishna

question

Most helpful comment

Yes that's correct. The ThreadPoolBulkhead runs tasks in a thread pool and returns a CompletionStage (CompletableFuture). The method鈥檚 return type must be CompletableFuture<BarcodeResponse> instead of BarcodeResponse, a requirement for any asynchronous service. Your code must do return CompletableFuture.completedFuture(response);
It can't return a ResponseEntity<BarcodeResponse>.

It's comparable to Spring's @Async annotation. Please see: https://spring.io/guides/gs/async-method/

All 4 comments

Bulkhead -> Semaphore-based Bulkhead
ThreadPoolBulkhead -> Threadpool-based Bulkhead

The Semaphore-based Bulkhead runs your code in the current Thread and controls the number of concurrent threads by a Semaphore.
The Threadpool-based Bulkhead runs your code in a Thread from a Thread Pool and controls the number of concurrent threads by a bounded queue and thread pool.

Thank you RobWin for the explanation, it was very helpful. I tried ThreadPool with @BulkHead annotation and I get the following error. is ThreadPoolBulkHead is supported in the current release?

My Code:

  @Bulkhead(name = "", fallbackMethod = "bulkHeadFallback", type = Bulkhead.Type.THREADPOOL) // if the name is empty, it takes default config values 
public ResponseEntity<BarcodeResponse> getBarcodeResponse(AnalyseIdentifier  analyseIdentifier,

{
// call to some remote servcie
}

Error:

ThreadPool bulkhead is only applicable for completable futures

    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
    at jp.co.toshibatec.ngp.conductor.aspect.LoggingAccess.time(LoggingAccess.java:160)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at jp.co.toshibatec.ngp.conductor.plugins.item_bundle.web.ItemController$$EnhancerBySpringCGLIB$$b74a21ee.itemOperation(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)

Your response would be highly appreciated

Yes that's correct. The ThreadPoolBulkhead runs tasks in a thread pool and returns a CompletionStage (CompletableFuture). The method鈥檚 return type must be CompletableFuture<BarcodeResponse> instead of BarcodeResponse, a requirement for any asynchronous service. Your code must do return CompletableFuture.completedFuture(response);
It can't return a ResponseEntity<BarcodeResponse>.

It's comparable to Spring's @Async annotation. Please see: https://spring.io/guides/gs/async-method/

Thanks RobWin. You are a champ

Was this page helpful?
0 / 5 - 0 ratings