I'm attempting to implement a spring integration flow that requires a multithreaded call if an input variable in true. If this variable is true then the flow with execute a multithreaded call and the main thread will continue it's flow.
Then at the end it will be required to wait for both flows to finish before returning a response.
I've been successful at implementing a multithreaded spring integration flow using a splitter, but the splitter results in all of the messages going to the same channel, this is different since the multithreaded call requires calling a different channel than the main thread of execution.
Is there a way to set up a splitter to send to different channels based on if the parameter is true or not? Or how would I set up an executor channel to spawn a new thread if that value is true while continuing the main flow at the same time.
As for waiting for both of the flows to finish execution would a spring integration barrier or an aggregator be a better approach for this use case?
Consider to use a PublishSubscribeChannel with an Executor configuration to let the same message to be sent to different parallel flows. This way you really can continue your main flow with one subscriber and do something else with other subscribers. With an Executor all of them are going to be executed in parallel.
Docs: https://docs.spring.io/spring-integration/docs/current/reference/html/core.html#channel-implementations-publishsubscribechannel
If you still insist that main flow must be executed only on the same thread, then consider to use a RecipientListRouter, where one of the recipients could be an unconditional next direct channel in a main flow. The other recipient could be conditional on your boolean variable and it can be an ExecutorChannel to let its subscriber to be invoked in parallel.
Docs: https://docs.spring.io/spring-integration/docs/current/reference/html/message-routing.html#router-implementations-recipientlistrouter
For waiting for both flows it is up to you to decide - barrier, an aggregator or more sophisticated scatter-gather. All of them will work for your "wait-for-all" requirements. Or you may implement some custom solution based on a CountDownLatch in some header. So, every time your parallel flow is done, you count it down. And this way you even will be able to determine the number according your boolean value. So, if no parallel, then just 1 and only main flow is going to be executed and only this one is going to count down that latch you are waiting for on original request.
Related
I am new to this concept and want to have a great understanding of this topic.
To make my point clear I want to take an analogy.
Let's take a scenario of Node JS which is single-threaded and provide fast IO operation using an event loop. Now that makes sense since It is single-threaded and is not blocked for any task.
While studying reactive programming in Java using reactor. I came to a situation where the main thread is blocked when an object subscribes and some delay event took place.
Then I came to know the concept of subscribeOn.boundedElastic and many more pipelines like this.
I got it that they are trying to make it asynchronous by moving those subscribers to other threads.
But if it occurs like this then why is the asynchronous. Is it not thread-based programming?
If we are trying to achieve the async behaviour of Node JS then according to my view it should be in a single thread.
Summary of my question is:
So I don't get the fact of using or calling reactive programming as asynchronous or functional programming because of two reason
Main thread is blocked
We can manage the thread and can run it in another pool. Runnable service/ callable we can also define.
First of all you can't compare asynchronous with functional programming. Its like comparing a rock with a banana. Its two separate things.
Functional programming is compared to other types of programming, like object oriented programming or procedural programming etc. etc.
Reactor is a java library, and java is an object oriented programming language with functional features.
Asynchronous i will explain with what wikipedia says
Asynchrony, in computer programming, refers to the occurrence of events independent of the main program flow and ways to deal with such events.
So basically how to handle stuff "around" your application, that is not a part of the main flow of your program.
In comparison to Blocking, wikipedia again:
A process that is blocked is one that is waiting for some event, such as a resource becoming available or the completion of an I/O operation.
A traditional servlet application works by assigning one thread per request.
So every time a request comes in, a thread is spawned, and this thread follows along the request until the request returns. If there is something blocking during this request, for instance reading a file from the operating system, or making a request to another service. The assigned thread will block and wait until the reading of the file is completed, or the request has returned etc.
Reactive works with subscribers and producers and makes heavy use of the observer pattern. Which means that as soon as some thing blocks, reactor can take that thread and use it for something else. And then it is un-blocked any thread can pick up where it left off. This makes sure that every thread is always in use, and utilized at 100%.
All things processed in reactor is done by the event loop the event loop is a single threaded loop that just processes events as quick as possible. Schedulers schedule things to be processed on the event loop, and after they are processed a scheduler picks up the result and carries on.
If you just run reactor you get a default scheduler that will schedule things for you completely automatically.
But lets say you have something blocking. Well then you will stop the event loop. And everything needs to wait for that thing to finish.
When you run a fully reactive application you usually get one event loop per core during startup. Which means lets say you have 4 cores, you get 4 event loops and you block one, then during that period of blockages your application runs 25% slower.
25% slower is a lot!
Well sometimes you have something that is blocking that you can't avoid. For instance an old database that doesn't have a non-blocking driver. Or you need to read files from the operating system in a blocking manor. How do you do then?
Well the reactor team built in a fallback, so that if you use onSubscribe in combination with its own elastic thread pool, then you will get the old servlet behaviour back for that single subscriber to a specific say endpoint etc.
This makes sure that you can run fully reactive stuff side by side with old legacy blocking things. So that maybe some reaquests usese the old servlet behaviour, while other requests are fully non-blocking.
You question is not very clear so i am giving you a very unclear answer. I suggest you read the reactor documentation and try out all their examples, as most of this information comes from there.
Let's consider the following situation in producer-consumer pattern:
I cannot wait with a task to be performed. I want to produce task on demand (eg. with Supplier) when a consumer is ready to process it. In SynchronousQueue I need to have actual task when executing put() method. How to solve my problem?
I know that I could solve it by design - just make a set of workers and tell them to produceTask-consume-Task-repeat, but I'm looking for another way.
To be more specific:
Let's consider that I have remote http resource A. I can get a 'task' from it to process in my worker threads. Results are sent asynchronously. But the thing is that I should not get a task from A if I am not able to process it right now.
"I want to produce task on demand (eg. with Supplier) when a consumer is ready to process it."
One example of producing data on demand is Reactive Streams protocol, where Subscriber (consumer) requests Publisher (producer) to push next chunk of data with Subscription.request() method.
This protocol is implemented in RxJava and other libraries.
If I were You, in the case of "producer-consumer pattern" you should not use blocking queues, however You looking for a non-blocking asynchronous queue.
Then everybody notified just in time.
Or is there any other constraint with the actual tasks. Or somehow I misunderstand You? Which side of the producer-consumer goes hungry?
I'm trying to wrap my head around Hystrix and after reading their docs, still have a question about its usage patterns.
For one, I don't understand the use case for when to use their Asynchronous execution vs. their Reactive execution. The only difference I can see is that Asynchronous execution is always non-blocking, whereas Reactive can either be blocking or non-blocking. So I guess my real question is:
What's the difference between Synchronous and Blocking Reactive execution?; and
What's the difference between Asynchronous and Non-Blocking Reactive execution?
Let's assume you have wrapped two service calls A and B as a HystrixCommand. You now have three options:
use .execute(): pure synchronous call. You call the method and continue your program once the result has arrived. Your program's total execution time is the sum both calls. The main flow of your program is very linear.
use .queue(): receive a Future immediately for both commands. Both service calls are executed in parallel. Then use .get() to retrieve the results. These calls with block until the result is there. Your total execution time is faster than before: your execution time will be the length of the longest service call. Use this when you i.e. want to combine the results of the two services. The main flow of your program is still linear, although both calls are executed in parallel.
use .subscribe(): receive a Observable immediately for both commands. Both service calls are executed in parallel. Then use .subscribe() to register a call-back to act on the result once it is available. This is very useful if you don't want to combine the results and want to react independently on the results of service A and B once they arrive.
The main flow of your program is no linear, but reactive: the flow of the program will continue inside the callback for each command.
I hope it helps.
In netty, events that flow through a channel pipeline occur in order as each channel is effectively only assigned to one thread and each handler calls each other in turn. This makes sense and alleviates many syncronisation issues.
However if you use an IdleStateHandler, from my reading of the source, it appears that the channelIdle event will be 'processed' in the context of the Timers thread (the thread the HashedWheelTime is using for example).
Is this case or have I missed something? If it is the case, does this mean that it is possible for an idlestate event and an IO event (example a messageRecieved event) to be executing on the same channel at the same time?
Also, as I could save the ChannelHandler ctx and use it in a different thread to 'write' to a channel for example, thus also have an event going downstream in one thread and upstream in another thread at the same time on the same channel?
Finally which thread do ChannelFutures execute in?
All of these use cases are perfectly acceptable and not a criticism of Netty at all, I am actually very fond of the library and make use of it everywhere. Its just that as I try to do more and more complex things with it, I want to understand more about how it works under the hood so that I can ensure I am using the proper and just the right amount (no more, no less) of syncronisation (locking).
Yes the channelIdle event and downstream / upstream event could be fired at the same time. So if your handler does implement at least two of the three you need to add proper synchronization. I guess we should make it more clear in the javadocs..
Now the other questions..
You can call Channel.write(...) from every thread you want too.. So its possible to just store it somewhere and call write whenever you want. This also gives the "limitation" that you need have proper synchronization for "downstream" handlers.
ChannelFutures are executed from within the worker thread.
However if you use an IdleStateHandler, from my reading of the source, it appears that the channelIdle event will be 'processed' in the context of the Timers thread (the thread the HashedWheelTime is using for example).
Is this case or have I missed something? If it is the case, does this mean that it is possible for an idlestate event and an IO event (example a messageRecieved event) to be executing on the same channel at the same time?
Yes, you have missed the concept of ordered event execution available in the Netty, If you are not haveing ExecutionHandler with OrderedMemoryAwareThreadPoolExecutor in the pipeline, you can not have the ordered event execution, specially channel state events from IdleStateHandler.
Also, as I could save the ChannelHandler ctx and use it in a different thread to 'write' to a channel for example, thus also have an event going downstream in one thread and upstream in another thread at the same time on the same channel?
Yes its correct.
More over, If you want to have ordered event execution in the downstream, you have have an downstream execution handler impl with OrderedMemoryAwareThreadPoolExecutor.
Finally which thread do ChannelFutures execute in?
The are executed by Oio/Nio Worker threads,
But if your down stream handler is consuming some type of event and firing another type of event to below the downstream, then your downstream handler can optionally handle the future execution. this can be done by get the future form downstream event and calling
future.setSuccess()
A little help please.
I am designing a stateless server that will have the following functionality:
Client submits a job to the server.
Client is blocked while the server tries to perform the job.
The server will spawn one or multiple threads to perform the job.
The job either finishes, times out or fails.
The appropriate response (based on the outcome) is created, the client is unblocked and the response is handed off to the client.
Here is what I have thought of so far.
Client submits a job to the server.
The server assigns an ID to the job, places the job on a Queue and then places the Client on an another queue (where it will be blocked).
Have a thread pool that will execute the job, fetch the result and appropriately create the response.
Based on ID, pick the client out of the queue (thereby unblocking it), give it the response and send it off.
Steps 1,3,4 seems quite straight forward however any ideas about how to put the client in a queue and then block it. Also, any pointers that would help me design this puppy would be appreciated.
Cheers
Why do you need to block the client? Seems like it would be easier to return (almost) immediately (after performing initial validation, if any) and give client a unique ID for a given job. Client would then be able to either poll using said ID or, perhaps, provide a callback.
Blocking means you're holding on to a socket which obviously limits the upper number of clients you can serve simultaneously. If that's not a concern for your scenario and you absolutely need to block (perhaps you have no control over client code and can't make them poll?), there's little sense in spawning threads to perform the job unless you can actually separate it into parallel tasks. The only "queue" in that case would be the one held by common thread pool. The workflow would basically be:
Create a thread pool (such as ThreadPoolExecutor)
For each client request:
If you have any parts of the job that you can execute in parallel, delegate them to the pool.
And / or do them in the current thread.
Wait until pooled job parts complete (if applicable).
Return results to client.
Shutdown the thread pool.
No IDs are needed per se; though you may need to use some sort of latch for 2.1 / 2.3 above.
Timeouts may be a tad tricky. If you need them to be more or less precise you'll have to keep your main thread (the one that received client request) free from work and have it signal submitted job parts (by flipping a flag) when timeout is reached and return immediately. You'll have to check said flag periodically and terminate your execution once it's flipped; pool will then reclaim the thread.
How are you communicating to the client?
I recommend you create an object to represent each job which holds job parameters and the socket (or other communication mechanism) to reach the client. The thread pool will then send the response to unblock the client at the end of job processing.
The timeouts will be somewhat tricky, and will have hidden gotcha's but the basic design would seem to be to straightforward, write a class that takes a Socket in the constructor. on socket.accept we just do a new socket processing instantiation, with great foresight and planning on scalability or if this is a bench-test-experiment, then the socket processing class just goes to the data processing stuff and when it returns you have some sort of boolean or numeric for the state or something, handy place for null btw, and ether writes the success to the Output Stream from the socket or informs client of a timeout or whatever your business needs are
If you have to have a scalable, effective design for long-running heavy-haulers, go directly to nio ... hand coded one-off solutions like I describe probably won't scale well but would provide fundamental conceptualizing basis for an nio design of code-correct work.
( sorry folks, I think directly in code - design patterns are then applied to the code after it is working. What does not hold up gets reworked then, not before )