Java + Resilience4J - Time limiter on my own handler? - java

Small question regarding Resilience4j please.
Currently, Resilience4J propose a very nice TimeLimiter pattern.
With it, one can very easily configure the time limit on an outbound http call. For instance, my service A is using an http client to call a service B. The time limit is to wait for service B for 1 second.
When properly configured, we can see when service B takes more than 1 second, to return a fallback instead, some kind of "no need to wait for service B anymore".
I was wondering, is it possible to configure similar, but for my own service/handler?
By that, I mean I would like to set a TimeLimiter on my own service A. Since I have an SLA defined by a contract of 5 seconds, instead of telling all my clients ("don't wait for me if I take more than 5 seconds") and to let them configure some kind of TimeLimiter on their end.
Very naive, I put the Resilience4J time limiter annotation on my own handler, and put very long computation in it, but not working. I think the Resilience4J time limiter is more for outbound calls.
Would it be possible to have the same mechanism on my own service A please?
Thank you

Yes, it also possible for your own service A.
But your service must return a CompletableFuture, Mono or Flux so that the TimeLimiter can throw an exception.

Related

Microservices async communication circuit breaker

I have 2 services running with spring boot and I have the following situation:
Service A (N instances) -> Queue (multiple instances) -> Service B (N instances)
Service A enqueue events async
Service B dequeue events
Traffic is increasing and we've noticed that events spend a lot of time in queue. We need to process events faster. Payload for each event is small and this solution has been working for some years now and a couple of years ago they thought that having a queue was a good idea but now I'm having this performance issue.
I thinking about creating an endpoint in service B and hit this endpoint from service A.
This call should be async and also implement a circuit breaker to avoid lossing messages if B goes down. If B goes down I could use the queue to keep messages and once B is running and up again pull messages from queue.
I have 2 questions:
Is it possible to implement circuit breaker or a failover mechanism for an async call?
do you think there is some other approach which could be better?
Thanks
for question
yes, it is possible, I am assuming you are using spring boot as you have mentioned java in tags, so there is a mechanism called RetryTemplate that you can use for async calls as well, you can find more details here -> https://www.openprogrammer.info/2019/09/03/using-spring-boot-async-with-retry/
There are better approaches I would say, what did you implement when you say queue here? like is it a LIFO or something like AWS SQS? if that is the case then you can try and look for topic-based queue mechanisms like apache kafka
If the bottleneck is in the queue, I don't think you should just remove it. You can just try to use a SQS or other cloud-based queue, which doesn't have that problem.
What happens if service A calls service B directly, and service B is down? The request will be lost. With a queue, the message will remain there until service B recovers.
Circuit breakers are used to avoid overwhelming a failed service with requests (in order to allow it to recover). So when it kicks in, there is a clear data loss there.

REST API request timeout for services which are always slow

I am working on a project where I have to call a third-party REST service. The problem with the current setup is that service does not return in at least 16 seconds. This response time may exceed more than that.
To avoid the threads waiting on the server, my service has a timeout value of 16 seconds. But that value is not helping. I searched on this and found that the Circuit breaker pattern will be useful. Reference:- spring-boot-rest-api-request-timeout . I believe this pattern is useful when the service has a slow response a few times. In my case, it is always a slow service.
How can I tackle this scenario?
If you want the response from the third party REST service, you have no choise but to wait, but if your request method have other thing to do. You should use Callable Thread to sent request to REST service and let Main Thread to complete the other work first then wait for the Callable to come back.
Maybe you can try to use some Cache like #Cacheable or Redis for this scenario. It may speed up some of the similar request.
Or, just let your request method sent the response back to client first. After that, use AJAX to access the third party REST service from the client side.

Reactive event processing with retrying in Java/Groovy

I would like to implement a microservice which after receive a request (via message queue) will try to execute it via REST/SOAP calls to the external services. On success the reply should be sent back via MQ, but on failure the request should be rescheduled for the execution later (using some custom algorithm like 10 seconds, 1 minute, 10 minutes, timeout - give up). After specified amount of time the failure message should be sent back to the requester.
It should run on Java 8 and/or Groovy. Event persistence is not required.
First I though about Executor and Runnable/Future together with ScheduledExecutorService.scheduleWithFixedDelay, but it looks to much low level for me. The second idea was actors with Akka and Scheduler (for rescheduling), but I'm sure there could be some other approaches.
Question. What technique would you use for reactive event processing with an ability to reschedule them on failure?
"Event" is quite fuzzy term, but most of definitions I met was talking about one of techniques of Inversion of Control. This one was characterized with fact, that you don't care WHEN and BY WHOM some piece of code will be called, but ON WHAT CONDITION. That means that you invert (or more precisely "lose") control over execution flow.
Now, you want event-driven processing (so you don't want to handle WHEN and BY WHOM), yet you want to specify TIMED (so strictly connected to WHEN) behaviour on failure. This is some kind of paradox to me.
I'd say you would do better, if you'd use callbacks for reactive programming, and on failure you'd just start new thread that will sleep for 10 seconds and re-run callback.
In the end I have found the library async-retry which was written just for this purpose. It allows to asynchronously retry the execution in a very customizable way. Internally it leverages ScheduledExecutorService and CompletableFuture (or ListenableScheduledFuture from Guava when Java 7 has to be used).
Sample usage (from the project web page):
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
RetryExecutor executor = new AsyncRetryExecutor(scheduler).
retryOn(SocketException.class).
withExponentialBackoff(500, 2). //500ms times 2 after each retry
withMaxDelay(10_000). //10 seconds
withUniformJitter(). //add between +/- 100 ms randomly
withMaxRetries(20);
final CompletableFuture<Socket> future = executor.getWithRetry(() ->
new Socket("localhost", 8080)
);
future.thenAccept(socket ->
System.out.println("Connected! " + socket)
);

How implements a retry feature on bad http code with AsyncHttpClient?

I need to call an url and it's possible that call return bad http code like 404, 500 etc. I want to implement a retry feature when I get those errors: a new call will be proceed every hour and ten times maximum.
I use the async-http-client library to do my POST call async.
Do you have any idea?
Thanks in advance for your help.
It's worth considering the Spring Retry functionality.
The API is constructed to be agnostic to what you want to retry, and concerns itself with retry policies, backoffs, limiting number of retries etc.
Another possibility if you're using Java 7/8 is the AsyncRetryExecutor. e.g.
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
RetryExecutor executor = new AsyncRetryExecutor(scheduler).
retryOn(SocketException.class).
withExponentialBackoff(500, 2). //500ms times 2 after each retry
withMaxDelay(10_000). //10 seconds
withUniformJitter(). //add between +/- 100 ms randomly
withMaxRetries(20);

What's the effect on a second request of calling Thread.currentThread().sleep(2000) in a Spring MVC request handler?

I need to wait for a condition in a Spring MVC request handler while I call a third party service to update some entities for a user.
The wait averages about 2 seconds.
I'm calling Thread.sleep to allow the remote call to complete and for the entities to be updated in the database:
Thread.currentThread().sleep(2000);
After this, I retrieve the updated models from the database and display the view.
However, what will be the effect on parallel requests that arrive for processing at this controller/request handler?
Will parallel requests also experience a wait?
Or will they be spawned off into separate threads and so not be affected by the delay experienced by the current request?
What are doing may work sometimes, but it is not a reliable solution.
The Java Future interface, along with a configured ExecutorService allows you to begin some operation and have one or more threads wait until the result is ready (or optionally until a certain amount of time has passed).
You can find documentation for it here:
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html

Categories

Resources