Petya Petrova - Fotolia
Software architects and developers must understand the differences between synchronous vs. asynchronous communications and how they apply to program execution and systems design.
Let's start by exploring some scenarios that illustrate how these two communication approaches work. Then, we'll explore the details of synchronous and asynchronous communications, including their behavior in hardware, cloud and microservices.
What are synchronous and asynchronous communication?
In synchronous communications, multiple parties continually listen for and act upon replies from each other. One way to visualize the concept of synchronous communications is to imagine a real-time online chat system designed for a retailer's customer support. The support specialist quickly exchanges messages with the customer to help track an order, report a missing delivery or inquire about a certain product.
In this scenario, both the sender and receiver establish a communications session. Once the session is established, the two-way conversation takes place with no restrictions on who inputs information when. As one party types and sends a chat message, the party at the other end is present and actively waiting to receive and respond to a message. This is what defines synchronous communications.
In asynchronous communication, parties do not actively listen for messages. Building off the example above, imagine the customer uses an email support channel instead of the live chat. Asynchronous transmission occurs when the email is sent to the manufacturer's support department. The customer does not expect to receive a reply in real time. Rather, the email message arrives at the retailer and the staff choose when to read or reply to the message.
Asynchronous communications typically incur a delay between when the sender initiates the message and when the recipient responds. The length of this delay depends on the communication medium. A similar example based on physical mail would likely take even longer in transit. The two parties of an asynchronous exchange do not work together in real time. In fact, either receiving end may be completely unaware of who exactly they are interacting with.
These two forms of data transmission can be easy to understand in terms of human communications, but it's significantly more difficult for architects and developers to apply them in software design. And while the basic principles guide the execution of program code, the amount of time it takes for these software-based communications to transmit can often be measured in milliseconds.
How do synchronous and asynchronous communication work?
Applications generate messages in the form of calls to functions, services and APIs. The way an architect designs these communications affects the application's performance, resource consumption and ability to execute tasks.
When a software component communicates synchronously, it sits idle until it receives a call, response, value or other data transfer. For example, synchronous execution occurs during online shopping. A user decides to purchase a product, and the system generates a query to determine if inventory is available. The app waits for a response before starting the checkout process. This synchronous design prevents mismatches between inventory and sales.
Conversely, asynchronous communication allows code to continue to run after it has generated a call or response. Asynchronous communication is particularly valuable for reporting and alerts, such as a manufacturing application that monitors the temperature of an industrial furnace, continually transmits status updates and automatically sends alerts.
This type of application should never stop and wait for responses before it moves on to the next action. Instead, the communication alone should trigger either personnel or another application to take action. For instance, the application might send asynchronous temperature updates throughout the day but also set off a troubleshooting sequence whenever temperatures either exceed or drop below acceptable levels.
Pros and cons of synchronous vs. asynchronous communications
Synchronous vs. asynchronous methods each have potential benefits and drawbacks, but the method you choose depends on an application's purpose.
Synchronous communication is simpler in design but carries the risk of spreading failures across services. To mitigate that risk, the architect must implement sophisticated service discovery and application load balancing among microservices.
On the other hand, asynchronous communication trades architectural simplicity and data consistency for resilience and scalability. Asynchronous designs often provide better control over failures than synchronous setups. Consider starting with a synchronous system to optimize for speed of evolution and switching to asynchronous communications once your microservices architecture grows.
Best practices for synchronous and asynchronous communication
Coherence around inter-service communication is one of the challenges in a distributed architecture like microservices. There are a few approaches to deal with that challenge.
Communications between services in a microservices architecture can be:
- decentralized and synchronous;
- choreographed and asynchronous; or
- orchestrated and synchronous/asynchronous.
In a decentralized and synchronous communications pattern, each service receives flow control, makes subsequent synchronous calls to other services and passes control to the next service. In choreographed and asynchronous service communications, however, the service publishes events to a central message queue that distributes those events. In both approaches, there is no information about the system's overall behavior in one place. Business flow logic is either embedded inside the services or in the event bindings between the producers and consumers.
One approach, centralized orchestration, enables both synchronous and asynchronous communication. The orchestrator sequences the various service calls based on a defined workflow. That sequence is not embedded within the participating services. The business workflow knowledge resides in a centralized place, and the services focus solely on their individual responsibilities.
To enable both synchronous and asynchronous microservices communication, keep flow sequencing away from the individual services. Service-based flows are difficult to decouple. Instead, design an architecture that supports both asynchronous and synchronous communication. Then, allow your orchestrator to switch the communication pattern for the specific service (see the figure below).
This approach enables a simple, decoupled architecture that is easy to read. It also helps support interoperability between protocols and payload transformation between services.
Synchronous vs. asynchronous communication considerations
There are a number of issues that can arise with both synchronous and asynchronous communication processes -- all of which can have a significant impact on the performance of an application system. These challenges are almost always exaggerated when applied to distributed systems, particularly when it comes to concurrency, workflow and component tracking.
Clock skew is a situation where linked digital components receive time indications at different intervals, which significantly impacts a synchronous system's performance. This can particularly cause problems in densely designed systems that host large numbers of components.
Clock skew is even more damaging in asynchronous communication, and it is a challenge to ensure each module and constituent component's clock remains synchronized with the others. Read-and-write storage operations are likely to occur milliseconds apart. Without clock synchronization, I/O operations will occur in the wrong order.
Data storage and integrity
Cloud data storage, especially cloud backup for on-premises systems, can put primary and backup data in different locations. Remote synchronous replication dictates that read-and-write operations occur in time with the primary and backup data storage locations.
Another challenge is the need to correlate multiple data streams that encompass both synchronous and asynchronous collection methods. This issue is especially present in data mining and streaming analytics.
In most monolithic application architectures, statements about the system's behavior are relatively evident as part of the app design. However, when the underlying architecture is made up of distributed services, it is harder to track the flow of communication. A single task built on dispersed services likely involves multiple layers of communication.