Synchronous vs. Asynchronous Communications |
COMP 310 Java Resources Eclipse Resources |
When communicating between two separated entities, e.g. between machines across a network, there are often two choices on how that communication can be accomplished:
void
return (RMI does this). Thus any response from the receiver is
occurring on the same communications channel as the sender used.void
return.
Any response from the receiver must be done through a separate return
communications channel.
Pros |
Cons |
|
Synchronous: |
|
|
Asynchronous: |
|
|
The choice of communications technique depends on the needs of the system. For example:
Typically characterized by: | Common communications solution choice: | |
Small systems |
|
Synchronous |
Large systems |
|
Asynchronous |
A very common misconception is to confuse an asynchronous messaging architecture with a multi-threaded "asynchronous" response handling of a request.
For instance, many libraries for HTTP request processing, e.g. JavaScript, enable the handling of the response to an HTTP request (e.g. GET, POST, etc) using a lambda function or similar that runs on a separate thread from the request itself. This technique is very useful for preventing the locking of the calling thread waiting for the response from a remote system. Because the "asynchronous" descriptor is typically applied to this technique, people often confuse it with real asynchronous messaging architecture when it is actually quite different.
Async response handling:
A request-response processing coding technique where the response to a request runs on a "different" thread (conceptually in JavaScript since it is single threaded).
- Is still a synchronous architecture because the request is tied to a response.
- No response without a request!
- Commits resources to the response processing before the response is received.
- Cannot accommodate push notifications
- Requires continual polling for notifications.
Asynchronous messaging:
A communications architecture where data is transmitted and received independently from requests.
- Requests are just that, requests (not "demands") with NO assumptions about responses.
- Requests for data are just messages, same as those that are not requesting data to be sent.
- Receivers of requests are not technically required to honor the request.
- Requests do NOT allocate resources for response processing.
- Resources for received messages are allocated separately from transmitted messages.
- Data can be sent at ANY time.
- "Responses" are just data transmissions, whether as a result of a received request OR NOT.
- Message receivers should be able to gracefully handle ANY type of message received at ANY time.
- The accepted message types thus depends on the state of the receiver -- easily achieved with a good architecture, e.g. using a State Design Pattern or similar.
- Push notifications are inherently handled as they are no different than any other type of received message.
- No special or additional code needed!
Unfortunately, a very common reason for not using an asynchronous architecture is simply misconceptions about the difficulties of creating such a system.
The biggest hurdle for most people is changing the way in which they see how information is passed in the system.
In particular, the key notion is to realize that the processes of requesting data (the code to make the function call to retrieve the data) is fundamentally decoupled from the processing the received data (the code that processes the returned result).
Also, in any system where the response time of a synchronous call is potentially signficant, the synchronous operation must be structured using some sort of asynchronous callback (e.g. a JavaScript
async
construct or a callback lambda) so as not to lock the calling threads and to reduce the impact on system resources. For these reasons, most libraries for handling synchronous network calls such as REST endpoints are fundamentally set up this way. That is,in properly constructed synchronous operations, the processing is ALREADY configured as an asynchronous architecture!
In the end, the major difference between synchronous and asynchronous architectures is WHERE the calling and receiving code is located. In an asynchronous system, the calling code ("requests") is simply physically separated from the receiving code.
The physical separation of the requests for data and the processing of received data has the added benefit of clarifying the multi-threaded (possibly multi-process) nature of the operations. The same issues are present in synchronous systems but the tighter coupling makes it much easier for developers to ignore or forget to properly deal with critical shared-data issues.
Asynchronous processing has a host of advantages and benefits for larger systems or systems that intend to grow. Switching from synchronous to asynchronous processing in an established system can be difficult and costly due to tight coupling that synchronous architectures naturally incur. But designing the system from the get go for asynchronous processing is not at all difficult and well worth any efforts needed to change the way one sees how information is being processed.
Don't fear the async!
© 2024 by Stephen Wong