Spring jaeger propagating span to an Async method - spring-boot

I have a simple Spring Boot 2.x RestController with an endpoint performing certain remote calls as well as controller is also calling an Async method that in turn makes several remote HTTP calls.
I'm having opentracing-spring-jaeger-web-starter in classpath with tracing enabled. If i invoke my REST endpoint, It creates a span for the endpoint call as well as remote calls that the controller is making synchronously.
However the remote calls made by Async method is getting reported in its own span. Is this by design or is there a way to propagate some context information to the Async method to better group/relate the spans ?

I solved it by using this library instead https://github.com/opentracing-contrib/java-spring-cloud
It seem to have an option to enable or disable different instrumentation feature. Read about opentracing.spring.cloud.async.enabled for more info.

Related

Thread model for Async API implementation using Spring

I am working on the micro-service developed using Spring Boot . I have implemented following layers:
Controller layer: Invoked when user sends API request
Service layer: Processes the request. Either sends request to third-part service or sends request to database
Repository layer: Used to interact with the
database
.
Methods in all of above layers returns the CompletableFuture. I have following questions related to this setup:
Is it good practice to return Completable future from all methods across all layers?
Is it always recommended to use #Async annotation when using CompletableFuture? what happens when I use default fork-join pool to process the requests?
How can I configure the threads for above methods? Will it be a good idea to configure the thread pool per layer? what are other configurations I can consider here?
Which metrics I should focus while optimizing performance for this micro-service?
If the work your application is doing can be done on the request thread without too much latency, I would recommend it. You can always move to an async model if you find that your web server is running out of worker threads.
The #Async annotation is basically helping with scheduling. If you can, use it - it can keep the code free of the references to the thread pool on which the work will be scheduled. As for what thread actually does your async work, that's really up to you. If you can, use your own pool. That will make sure you can add instrumentation and expose configuration options that you may need once your service is running.
Technically you will have two pools in play. One that Spring will use to consume the result of your future, and another that you will use to do the async work. If I recall correctly, Spring Boot will configure its pool if you don't already have one, and will log a warning if you didn't explicitly configure one. As for your worker threads, start simple. Consider using Spring's ThreadPoolTaskExecutor.
Regarding which metrics to monitor, start first by choosing how you will monitor. Using something like Spring Sleuth coupled with Spring Actuator will give you a lot of information out of the box. There are a lot of services that can collect all the metrics actuator generates into time-based databases that you can then use to analyze performance and get some ideas on what to tweak.
One final recommendation is that Spring's Web Flux is designed from the start to be async. It has a learning curve for sure since reactive code is very different from the usual MVC stuff. However, that framework is also thinking about all the questions you are asking so it might be better suited for your application, specially if you want to make everything async by default.

Connectivity issues when calling a controller endpoint, how can we deal with it? [Spring and Kotlin]

I have some service method used in my controller endpoint whose logic is not fully executed when connectivity issues arise (as you would expect). I am looking for a potential approach, rather than using a try and catch block within the service method. What is the recommended way to go? Is there any "rollback" functionality that can be injected in Spring whereby if something happens during the executing of the service logic then it rolls back?
Thank you

How to make Spring Boot REST controller asynchronous?

My application is simple 3-tier Spring Boot rest web-service with usual synchronous endpoints.
But since the period of getting response from downstream system where my service sends requests is quite long (kind of 60 seconds), I need to add support of asynchronous REST calls to my service to save upstream systems from a response awaiting. In other words, if a response to a downstream system is going to take more than 60 seconds (timeout), then the upstream system break the connection with my service and keeps its doing...
But when the response come, my service using "reply-to" header from the upstream system will send the response to the upstream system.
All the things above are kind of call back or webhook.
But I didn't find any examples of implementation.
How to implement this mechanism?
How can I find more information?
Does Spring Boot have something to implement it out-of-box?
Thank you for attention!
You can use the #Async annotation from Spring. You will also need to enable in your application this by setting #EnableAsync.
An important note is that your method with the #Async annotation should be on a different class from where it is being called. This will let the Spring proxy intercept the call and effectively do it asynchronous.
Please find here the official tutorial.

Transaction management of JPA and external API calls

I'm new to spring, started using spring boot for the project. We have an use case of implementing database changes and few external API calls as one transaction. Please suggest, is this possible with the spring #transactional?
Do the API calls need to be part of the transaction?
If the answer is no, I would advise to use TransactionTemplate.doInTransaction() leaving the API requests outside of the Tx.
If you need to make the API requests inside a Tx, I would advise against it, you would be locking DB resources for the duration of those requests.
You can also search and find out more about the eventual consistency model.
Using #Transactional for multiple database changes as one transaction is of course doable with the annotation but not so much for the external API calls. You would have to implement some custom logic for that - there would have to be endpoints to undo your last actions and you would have to implement calling them manually in try-catch block for example. For example, if the external API call creates an item there would also have to be an endpoint to delete an item and so on.
So to summarise - using #Transactional annotation for implementing database changes as one transaction is fine, but not enough for external API calls.

Handling long running processes in Spring MVC controllers

Using Spring MVC, I have a controller that makes an API request to an external service that may take a long time. I am doing this synchronously because I want to return the external request result to the user. Ideally, this doesn't block an entire thread during this time, sort of like an async/await C# style idiom, but I'm not sure how to do that easily with Spring (or something else).
You can use #Async annotation on some service method for asynchronous execution.
Spring MVC is built on top of a Servlet, this means that (by default) anything you do inside a Controller method will block the request thread provided by Tomcat (Tomcat is the default servlet container for Spring Boot these days).
If you are calling another HTTP based service, or Query a database inside your controller, you are probably making a blocking IO call. Blocking calls will always block the calling thread, the async/await in C# is just syntactical sugar, like Springs #Async it uses a hidden ThreadPool to do the actual work.
Unless you are able to call the upstream service using a NIO selector, you will need a thread to wait for the response, and in that case it makes most sense to just block on the Tomcat request thread, I believe the default number of request threads is 150, but you can set it higher if needed. If the upstream service can be called in a NIO manner, you only need one thread for all calls to that service, and you can can return a DeferedResult from your controller, and write the response to the client once the response from the upstream service has been produced.
It's simple. Do not call the long running api from your main controller method. Just return the view (JSP). Then you can fire an ajax request from your document.ready method in your view (Javascript). You can have a seperate #ResourceRequest annotated method in your controller to handle the ajax call. Return the api result (as JSON or something) to the ajax caller. Once the view receives the ajax response, update the UI as you want.

Resources