What is the difference between #Async annotated method and Reactor set to use thread pool of the same size. Is there any advantage to one of this methods and what it would be? For my use, I do not care to return any value with the asynced method.
The most obvious difference is that Reactor doesn't crosscut #Async annotated methods and implicitly submit events to a Reactor. If you're using the Reactor #Selector annotation on beans then you're getting the opposite of what you would with #Async: an event handler, not an event publisher.
With that said, there is some support in Reactor for #Async-style event publishing through the DynamicReactorFactory. It uses an interface instead of an annotation, but the concept is similar.
Regarding "advantages" to using one or the other: it really depends on what other things you're doing in your application and whether or not you're using Reactor in a more general sense. Reactor isn't designed to be a thread pool replacement. The ThreadPoolExecutorDispatcher in Reactor just uses a plain ThreadPoolExecutor underneath. The advantages to using Reactor in that scenario come from the optimized event publishing used in Reactor versus creating new Callables and Runnables all the time, as well as using Reactor's Stream and Promise API to handle asynchronous execution.
Looked at from the API prespective, there is a distinct and measurable advantage to using Reactor over a plain TaskExecutor for background jobs.
Related
I am using the Spring WebClient (org.springframework.web.reactive.function.client.WebClient) in order to implement some non-blocking behaviour.
Mono<ClientResponse> clientResponse =
webClient
.get(...).exchange();
clientResponse.subscribe((response) -> {
//--- unfortunately my tenant context is lost here !!! Someone knows the right solution?
});
However my tenant-context gets lost once the response arrives (of course, we are in a new thread).
Here is the documentation of how to implement common asynchronous tasks within the tenant-context: https://sap.github.io/cloud-sdk/docs/java/features/multi-tenancy/multi-tenancy-thread-context/
However, I couldn't find the recommended way how to remain the tenant-context using Spring webflux (using the WebClient).
Edit: The SAP Cloud SDK destroys a ThreadContext at the end of an operation. This is done to prevent it from leaking e.g. when the thread is re-used.
If:
the context is passed to an asynchronous operation
but the "parent" operation is done before the asynchronous operation starts
the ThreadContext will not be available in the asynchronous operation. That is what is happening when using the WebClient.
This is not true for custom properties, the SDK does not clear them. But that also means that you have to clear them yourself to ensure they don't leak when the thread is being re-used.
I'd recommend not to use the multi tenancy features of the SDK in such cases. Still, I'll leave my below answer in for context.
You can transfer the SAP Cloud SDK's ThreadContext to any new Thread if and only if you have control:
Before the new Thread is created
The operation that will be run asynchronously that requires the context
Edit: The parent thread (context) still exists
I am not too familiar with WebFlux, but I'll assume that:
clientResponse.subscribe runs in the parent Thread
And the lambda is executed in the asynchronous Thread
Given that, the following should transfer the ThreadContext to be present in the lambda:
ThreadContextExecutor executor = new ThreadContextExecutor();
clientResponse.subscribe((response) ->
executor.execute(() ->
{
// your code goes here, the ThreadContext should be available
}
)
);
You would have to do this at every point where an operation is running in a new Thread. As Artem pointed out, currently there is no feature in the SDK for this that would achieve the same automagically.
I think it is also possible to define a custom ExecutorService that Spring will use to create and run new Threads. In a custom executor you could encapsulate this wrapping logic once for all operations.
The SAP Cloud SDK APIs support Spring Boot and currently don't support Spring Webflux out of the box. You'll probably see all sorts of errors if using the SDK APIs with reactive Spring development. On the other hand, as Matthias showed workarounds might be possible for certain use-cases.
We consider adding Spring WebFlux support in the future. It probably won't happen this year (in 2021).
I'm wondering what is an "official" name for the design pattern where you have a single thread that actually handles some resource (database, file, communication interface, network connection, log, ...) and other threads that wish to do something with that resource have to pass a message to this thread and - optionally - wait for a notification about completion?
I've found some articles that refer to this method as "Central Controller", but googling doesn't give much about that particular phrase.
One the other hand this is not exactly a "message pump" or "event queue", because it's not related to GUI or the operating system passing some messages to the application.
It's also not "work queue" or "thread pool", as this single thread is dedicated only to this single activity (managing single resource), not meant to be used to do just about anything that is thrown at it.
For example assume that there's a special communication interface managed by one thread (for example let that be Modbus, but this really doesn't matter). This interface is completely hidden inside an object with it's thread and a message queue. This object has member functions that allow to "read" or "write" data using that communication interface, and these functions can be used by multiple threads without any special synchronization. That's because internally the code of these function converts the arguments to a message/request and passes that via the queue to the handler thread, which just serves these requests one at a time.
This design pattern may be used instead of explicit synchronization with a mutex protecting the shared resource, which would have to be locked/unlocked by each thread that wishes to interact with that resource.
The best pattern that fits here may be the Broker pattern:
The Broker architectural pattern can be used to structure distributed
software systems with decoupled components that interact by remote
service invocations. A broker component Is responsible for
coordinating communication, such as forwarding requests. as well as
for transmitting results and exceptions.
I would simply call it asynchronous IO, or more catchy: non-blocking IO.
As: does it really matter what that "single thread side" is doing in detail? Does it make a difference if you deal "async" with a data base; or some other remote server?
They key attribute is: your code is not waiting for answers; but expecting information to flow in "later".
Can somebody please explain the difference between synchronous and Asynchronous ways of event processing in hybris platform?
I was just going through event system provided by hybris service layer and got stuck at this concept as I couldn't proceed without knowing exactly what happens during events processing (synchronous or asynchronous )? In face what does the term "event processing" ?
Hybris's Event System is based on the Spring Event System, and provide an EventService and wrappers for Events and EventListeners (AbstractEvent and AbstractEventListener). So, under the hood, you deal with Spring's ApplicationEvent and ApplicationListener.
The goal of "event processing" is to provide a pass-through functionality between platform components, in the way, when "interested" components subscribe for an events, and receive notifications when certain event occured (published).
Hybris allow events to be published in a clustered environment, between cluster nodes, by implementing ClusterAwareEvent interface. These events are processed asynchronously. All other events processed synchronously, but it is possible to publish them asynchronously too, by overriding spring definition of PlatformClusterEventSender bean, with injection of thread pool.
I want to use akka in my application for multi processing.
So, the same block of code gets executed by each actor and the results will be aggregated by the listener.
so, my question is will there be any synchronisation problem in this case. If not how is it being handled by akka actors internally.
By default there should not be any synchronization problems - if you strictly respect the actor approach. This means that actors should only communicate using messages that contain immutable objects - and that you should never expose internal state of an actor to the outer world directly. Make the internal state mutable/readable solely by reacting to received messages.
Each actor is executed in its own ExecutionContext. This means that each actor has its own private state. Akka actors are designed in a way that accessing this internal state from the "outer world" is basically not possible (or made very hard) since after creating a new Actor, you only have an intermediary reference to an Actor (an ActorRef instance), not an reference to the actual Actor instance in the memory. It is intention of the Akka developers to do it that way: it is made hard for developers to get the the actual reference and access its properties directly - which would break the Actor approach.
If - on the other hand - you pass an shared mutable object to an actor, you will have all the hassle with locks and synchronization as you have for instance with using Threads.
When an EJB application receives several requests (work load) it can manage this work load just POOLING the EJBs, so when each EJB object is being used by a thread, the next threads will have to wait queued until some EJB ends up the work (avoiding overloading and efficiency degradation of the system).
Spring is using stateless singletons (not pooling at all) that are used by an "out of control" number of threads.
Is there a way to do something to control the way the work load is going to be delivered? (equivalent to the EJB instance pooling).
Thank you!
In the case of the web app, the servlet container has a pool of threads that determine how many incoming HTTP requests it can handle simultaneously. In the case of the message driven POJO the JMS configuration defines a similar thread pool handing incoming JMS messages. Each of these threads would then access the Spring beans.
Googling around for RMI threading it looks like there is no way to configure thread pooling for RMI. Each RMI client is allocated a thread. In this case you could use Spring's Task Executor framework to do the pooling. Using <task:executor id="executor" pool-size="10"/> in your context config will set up a executor with 10 threads. Then annotate the methods of your Spring bean that will be handling the work with #Async.
Using the Spring task executor you could leave the Servlet and JMS pool configuration alone and configure the pool for your specific work in one place.
To achieve a behaviour similar to the EJB pooling, you could define your own custom scope. Have a look at SimpleThreadScope and the example referenced from this class' javadoc.
The difference between Spring and EJB is, that Spring allows multiple threads on an single instance of an bean, while in EJB you have only one tread per bean (at one point in time).
So you do not need any pooling in Spring for this topic. But on the other hand you need take care that you implement your beans in a threadsave way.
From the comments:
Yes I need it if I want to limit the number of threads that can use my beans simultaneously
One (maybe not the best) way to handle this is to implement the application in normal spring style (no limits). And than have a "front-controller" that accept the client request. But instead of invoking the service directly, it invokes the service asyncron (#Async). May you use some kind of async proxy instead of making the service itselfe asyncron.
class Controller{...
Object doStuff() {return asyncProxy.doStuffAsync().get();}
}
class AsyncProxy{...
#Async Future<Object> duStuffAscny{return service.doStuff();
}
class Service{...
Object doStuff{return new Object();}
}
Then you only need to enable springs Async Support, and there you can configure the Pool used for the Threads.
In this case I would use some kind of front controller, that starts an new Async