DEV Community

Discussion on: Why a distributed system (highly concurrent) is mostly asynchronous?

Collapse
 
ananto30 profile image
Azizul Haque Ananto

Thanks for the answers. Can you please give examples of - Request which waits for response from the other part of the system is just stored in memory in some way (there are different approaches for this)
Is it mapping you are talking about? What are the other ways can we make asynchronous to synchronous?

If it's not about Kafka or MQ what other ways async systems can talk to each other? Shouldn't there be a message passing system?

Collapse
 
siy profile image
Sergiy Yevtushenko

No, message passing system is not necessary to create asynchronous processing system.

Whole explanation is somewhat larger than it is convenient to put into comment, but I'll try.

Behind most successful asynchronous processing libraries/frameworks (for example Node.js and Vert.x) you can find Reactor pattern. At high level the idea of reactor pattern is quite simple: there is a main thread which receives incoming events and then dispatches them for processing to other worker threads.

There are many articles dedicated to Reactor pattern, but this probably best one to understand how it works in Java at low level. The Netty is very similar but of course much more advanced and tuned to squeeze every single bit of performance.

So, what happens next and where asynchrony comes from?
The events coming from the OS to Reactor are quite low level, like "packet is received by socket XXX" or "packet is sent by socket YYY". These events are passed to chain of handlers which transform them higher level events, like "HTTP request is received" or "Requested data delivered from DB". Events of this level are passed to user code which is just another level of event handlers. The only requirement for the handler is that it does not block (i.e. it does not wait for finish of synchronous request). In most cases user handler can't, for example, generate response for HTTP request without calling some other services. Lets assume that these services are also asynchronous. In this case user code which handles incoming HTTP request invokes external service and immediately returns without completing HTTP request. Instead it passes some form of callback mechanism to invoked service. When invoked service finally receives necessary data, it calls provided callback and in callback we complete HTTP request and prepare response. While request is not completed it is stored in memory. Whole system has very small number of context switches. Another advantage is that such an approach can work on very low number of threads - usually number of threads is close to number of physical/logical CPU cores. Since every thread consumes sensible amount of memory and spends some resources on scheduling, reducing number of threads also significantly improves overall performance.

I really hope this very brief explanation is helpful. If it is not clear enough - let me know, I'll try to add necessary details.

Thread Thread
 
ananto30 profile image
Azizul Haque Ananto

Wow! Thanks! That's a very good explanation. I've been working with Webflux (Reactive Java based framework) for the last 6 months. It's an amazing concept but the performance boost is not up to the mark. Also, the code gets uglier day by day. (The common callback problem)
Lately, I've been working with Python's concurrency. The Asyncio event loop is the kind of reactor thing. But I've found it gets exhausted with a significant number of Futures. So I tried threads with multiprocessing and noticed there should be some message passing among the processes. I am working on a project on this concept with Zeromq. I will soon share the repo with you (hopefully, if I can finish).

Thread Thread
 
siy profile image
Sergiy Yevtushenko

I'm also working on the library which implements my views on how Java asynchronous processing should look like. I've taken Promise-based approach because Promises are composable and allow building complex processing pipelines without much efforts. Unlike Reactive streams (Webflux, Project Reactor, RxJava) Promises do not introduce any artificial concepts like "stream of one element" and whole processing looks very natural and similar to traditional synchronous code. I've also combined Promises with FP-style error and null values handling. Resulting combination is extremely powerful and expressive. You can take a look at code examples here and especially here.