we experience the following problem: We have got some service bean that does some handling and will iterate over a set and start an async thread for each entry, which will look like following:
#Service
public class ServiceBean {
#Autowired
private AsyncHandler asyncHandler;
public void doService(Set<?> theSet) {
for (Object obj : theSet) {
Future<?> future = asyncHandler.doHandle(obj);
// ...
}
// wait for all futures to complete
}
}
#Service
public class AsyncHandler {
#Async
public Future<?> doHandle(Object object) {
// dosth
return future;
}
}
Now we see that each thread will hold its own transaction and thereby database connection, which will cause the connection pool to run empty very fast.
What is the desired way to share the transaction accross all threads?
Thanks in advance!
What is the desired way to share the transaction accross all threads?
Don't do that. That makes it incredibly hard to understand what is going on. There's a reason why a transaction is attached to the thread that has created it. I guess your plan is to start all those asynchronous threads and then wait for them to complete to send the commit signal.
If you don't, who's going to complete the transaction? If a thread rollbacks the transaction, what happens in other threads that are still using it? You could pass the Connection around obviously but I'd expect things to be serialized anyway as most connection implementation are using synchronized in various places.
Related
I have such a controller and such a service class. Why am I getting this warning in IDEA - "Possibly blocking call in non-blocking context could lead to thread starvation" ?
#PostMapping(value = {"/create"})
public Mono<ResponseEntity<ResponseDto>> create(
#RequestBody RequestDto request) {
ResponseDto result = service.create(request);
return Mono.just(ResponseEntity.ok(result));
}
#Transactional
public ResponseDto create(RequestDto request) {
taskRepository.save(request);
return new ResponseDto("Ок");
}
This is apparently caused by the #Transactional annotation. When I remove it, the warning disappears. What is this problem and how can it be fixed?
p.s. this example is schematic. the real code is bigger.
The reactive process is contrary to the norm. You cannot use blocking elements here! With Tomcat, it creates a separate thread for each request so that the topic can be blocked. Reactive Netty will NOT create a new thread, just uses a fixed pool.
With the loose approach, you can think that if a process is waiting for a response, it gives the resource of that thread to another. If you block it, it won't be able to do that. Therefore, even with a single-threaded Netty, it can handle to serve multiple parallel requests.
Therefore, thread-based data storage also does not work properly, because another process can interfere or modify it. Therefore, reactive context is available instead.
There is a article to reactive transaction. I don't know it will be solution for you:
https://itnext.io/integrating-hibernate-reactive-with-spring-5427440607fe
I am writing a service where I want to expose an endpoint which will call another service and if the service call is successful then I want to send back the result to UI/ calling app.
In parallel before sending back the response, I want to execute/submit a task which should run in background and my call should not be dependent on success or failure of this task.
Before returning the response i want to do the-
executorService.execute(object);
This should not be a blocking call..
Any suggestion
Spring Async methods is the way to go here as was suggested in comments.
Some caveats:
Async methods can have different return types, its true that they can return CompletableFuture but this is in case if you called them from some background process and would like to wait/check for their execution status or perhaps, execute something else when the future is ready. In your case it seems that you want "fire-and-forget" behavior. So you should use void return type for your #Async annotated method.
Make sure that you place #EnableAsync. Under that hood it works in a way that it wraps the bean that has #Async methods with some sort of proxy, so the proxy is actually injected into your service. So #EnableAsync turns on this proxy generation mechanism. You can verify that this is the case usually in the debugger and checking the actual type of the injected reference object.
Consider customizing the the task executor to make sure that you're running the async methods with executor that matches your needs. For example, you won't probably want that every invocation of async method would spawn a new thread (and there is an executor that behaves like this). You can read about various executors here for example
Update
Code-wise you should do something like this:
public class MyAsyncHandler {
#Async
public void doAsyncJob(...) {
...
}
}
#Service
public class MyService {
#Autowired // or autowired constructor
private MyAsyncHandler asyncHandler;
public Result doMyMainJob(params) {
dao.saveInDB();
// do other synchronous stuff
Result res = prepareResult();
asyncHandler.doAsyncJob(); // this returns immediately
return res;
}
}
When using Spring webflux with Mono or Flux return type, the http connecting thread is parked/released while the connection waits for the response. Thus, the connection is not taking max-connections.
Question: how can I test/proof that the connection is really released while waiting for the response, and not blocking max-connections?
I already enabled DEBUG logging, but that did not show anything regarding this question.
#RestController
public class MyServlet {
#GetMapping("/")
public Mono<String>/Flux<String> test() {
return Mono.just(service.blocking());
}
}
#Service
public class SlowService {
public String blocking() {
TimeUnit.SECONDS.sleep(10);
return "OK";
}
}
Or is that incorrect at all, and I'd have to use:
Mono.fromCallable(() -> service.blocking()).subscribeOn(Schedulers.elastic());
But still, how can I see from the logs that the connection gets parked correctly?
To test, I'm using server.tomcat.max-threads=5. I'm trying to rewrite my blocking service so that those threads are not blocked during the sleep, and thus more than 5 connections can reach my service concurrently.
There are 2 thread pools, the forkjoin pool that will handle all the regular work. Then you have the Schedular pool that will handle scheduled tasks.
return Mono.just(service.blocking());
This will block one of the threads in the ForkJoinPool so less events can be handled by webflux hence slowing down your service.
Mono.fromCallable(() -> service.blocking()).subscribeOn(Schedulers.elastic());
This will assign the task and "offload" it to the scheduler pool of threads so another thread pool will handle this and not hog one of the ForkJoinPool threads.
How to test this? You need to load test your service, or as most people do, trust the framework to do what it is set out to do and trust that the spring team has tested their side of things.
I'm creating a REST service using Spring with Jersey and I have a use case where for every request I get, I need to make several calls (N) to an upstream API.
I get one request, it has n items, for each item, I create a thread to call my dependency (REST) and process the response. At the end I collect all the responses together, maintaining the order, and return them as a single response to the client.
I am using Java 8's CompletableFuture and wanted to know if I was using the ExecutorService framework correctly.
#Component // automatic singleton by Spring
class A {
private ExecutorService executorService = Executors.newCachedThreadPool();
private RawResponse getRawResponse(Item item) {
// make REST call
}
private Response processResponse(RawResponse rawResponse) {
// process response
}
public List<Response> handleRequest(Request request) {
List<CompletableFuture> futureResponses = new ArrayList<>();
for(Item item : request.getItems()) {
CompletableFuture<Response> futureResponse = CompletableFuture.supplyAsync(() -> getRawResponse(item), executorService)
.thenApply(rawResponse -> processResponse(rawResponse))
.handle((response, throwable) {
if(throwable != null) { // log and return default response
} else { return response;}});
futureResponses.add(futureResponse);
}
List<Response> result = new ArrayList<>();
for (CompletableFuture<Resource> futureResponse : futureResponses) {
try {
result.add(futureResponse.get());
} catch (Exception e) {
// log error
}
}
return result;
}
}
The question I have now is, should I move the creation of the executorService right above:
List<CompletableFuture> futureResponses = new ArrayList<>();
and call shutdown on it right above:
return result;
because at this time, I am not really calling shutdown anywhere since the app will always run in it's docker container.
Is it costly to keep creating and discarding the pool, or is the current way going to leak memory? And I think calling the pool static as a private field var is redundant since the class is a spring bean anyways (singleton).
Any advice will be appreciated, also should I be using a cachedThreadPool? I am not sure how to approximate the number of threads I need.
should I move the creation of the executorService right above?
No you don't, you have your ExecutorService the right place in your example code. Think it as a thread pool, you will not want to init a new thread pool and close it for each method call of handleRequest. Of course ExecutorService does more job than a thread pool, actually it'll manage a thread pool underneath, and provides life-circle management for async tasks.
I am not really calling shutdown anywhere since the app will always run in it's docker container.
In most of cases you init your ExecutorService when applications starts and shut it down when applications shuts down. So you can just leave it there, because it'll be closed when application exits, or you can add some kind of shutdown hooks if you need to do graceful shutdown.
Is it costly to keep creating and discarding the pool.
Kind of, we don't want to create and discard Thread very often, so we have thread pool, if you create/discard pool for each method call, what's the point to have a thread pool.
or is the current way going to leak memory?
No, as long as the task you submitted does not leak memory. The implementation of ExecutorService itself is good to use.
And I think calling the pool static as a private field var is redundant since the class is a spring bean anyways (singleton)
Yes, you're correct. You can also define ExecutorService as Spring Bean and inject it to service bean, if you want to do some customized init process.
should I be using a cachedThreadPool, I am not sure how to approximate the number of threads I need.
That's hard to say, you need to do some test to get the right number of threads for your application. But most of NIO or EventDriven framework has the twice number of available cores to be the number of threads by default.
As you are using Spring, you might want to let it handle the asynchronous execution instead.
Just put #EnableAsync in one of your #Configuration classes to enable the #Async annotation on methods.
You would then change your getRawResponse() to
#Async
private CompletableFuture<RawResponse> getRawResponse(Item item) {
// make REST call
return CompletableFuture.completedFuture(rawResponse);
}
(you might need to put this method in a separate service to allow proper proxying, depending on how AOP is configured in your project)
and change your loop to simply
for(Item item : request.getItems()) {
CompletableFuture<Response> futureResponse = getRawResponse(item)
.thenApply(rawResponse -> processResponse(rawResponse))
.handle((response, throwable) {
if(throwable != null) { // log and return default response
} else { return response;}
});
futureResponses.add(futureResponse);
}
As you can see, you do not need to care about the executor in your service anymore.
You can also customize your executor by declaring its Spring bean, for example:
#SpringBootApplication
#EnableAsync
public class Application extends AsyncConfigurerSupport {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("GithubLookup-");
executor.initialize();
return executor;
}
}
You can even configure several executors and select one by providing its name as parameter to the #Async annotation.
See also Getting Started: Creating Async Methods and The #Async annotation.
I have a pojo producer which produces MyResourceManager.
#TraderResouceManager #RequestScoped public MyResourceManager(){ ... ... }
MyResourceManger is injected into SLSB
#inject #TraderDB private MyResourceManager rm;
The disposer is a follows
public void close(#Disposes #TraderResouceManager MyResourceManager rm) {
rm.close();
}
Question
When does the close() execute ?
Is it before closing transaction or after closing the transaction ?
EDIT : The question perhaps needs additional explanation. Lets take a database connection analogy.
I create a #producer with #RequestScoped, using a pojo which creates a new connection per request.
What I need is to dispose the connection at the end of request.
This connection is shared by other beans (for now SLSB). In a given request there may be many beans involved running inside a transaction.
Hence additionally I need to close the connection only after all the transactions are logically closed.
Question
Will I be able to achieve this behavior with above code when I use container managed transactions ?
Close() executes when the current request is terminated since your producer method is request-scoped. If you call your SLSB from a JSF request or a servlet, then the lifeclye of those requests determines when MyResourceManager will be disposed. If your SLSB is remote, it will be terminated as soon as the call returns.