Getting communication between microservices right is problematic for many due in great part, I feel, to the fact that people gravitate toward a chosen technological approach without first considering the different types of communication they might want.
Microservices architecture replaces In-Process communication with Inter-Process communication, which provides loose coupling and greater flexibility. However, this comes at the cost of increased operational complexity and latency.
To reduce operational costs, many production environments choose to deploy multiple services on the same machine. However, developers may not account for the shared environment, so desgin system that services may communicate directly with each other using inefficient protocols such as TCP/IP, even though a more efficient solution is available.
Inter-Process Communication (IPC)
Process is an instance of Program that is executed and owns its memory address space. This enables each Program to isolate its data and prevent other programs from accessing it. However, this isolation can also make it challenging to establish an efficient communication channel between Processes.
Inter-Process communication (IPC) is a way for two Processes to communicate with each other. There are three main mechanism for IPC: shared file, through kernel, and shared memory.
Shared File
Shared file mechanism is a way for multiple Processes to communicate with each other by accessing the same File. This can be done by opening the File in shared mode, which allows multiple Processes to read and write to at the same time.
flowchart LR
A[Service A] <--> C[System Call Interface]
C <--> B[Service B]
subgraph Process
A
B
end
subgraph Kernel
C <--> E[File System]
end
Through Kernel
Communication through the Kernel is a mechanism that allows multiple Processes to communicate with each other by calling the Kernel. The Kernel then mediates the communication between the Processes. To make communication, Kernel usually create a File Description that Processes can read and write from it. Unlike shared file mechanism that File is identity, this mechanism requires some ways to manage identity such as Process identity or Connection identity. For example, Pipe operations require that the Processes involved in the communication be related to each other.
flowchart LR
A[Service A] <--> C[Kernel]
C <--> B[Service B]
subgraph Process
A
B
end
subgraph Kernel
C
end
Shared Memory
Shared memory is a mechanism that allows multiple Processes to communicate by accessing the same Memory region. This is the fastest way for Processes to communicate, but it comes with some drawbacks.
- Complexity: Developers need to be aware of the potential for data races and other synchronization issues.
- Security: Shared memory can make it easier for processes to access data that they should not have access to. This can be a security risk, especially if the processes are running with different levels of privileges.
flowchart LR
A[Service A] <--> C[Memory]
C <--> B[Service B]
subgraph Process
A
B
C
end
Sockets
Socket is a software structure that allows processes to communicate with each other. In Linux, sockets are implemented using the Berkeley sockets API. This API provides two main types of sockets: stream sockets and datagram sockets.
Stream Sockets | Datagram Sockets |
---|---|
Reliable | Unreliable |
Two-way connection | One-way connection |
Slower | Faster |
Socket is also categorized by domain, which defines how sockets are created, named, and used. There are two main socket domains in Linux: Internet domain (IDS) and Unix domain (UDS).
IDS | UDS |
---|---|
Slower | Faster |
Over the Internet | On the same machine |
Internet Domain Socket (IDS)
Internet domain socket (IDS) is a type of socket that is designed to communicate over the internet using the TCP/IP protocol. IDS creates a Socket File Description which is just a memory for read and write. When an IDS is created on the same host, it looks like Inter-Process communication through the kernel mechanism because the IDS depends on Kernel and uses the localhost address with port number as the identity method.
flowchart LR
subgraph User
A[Service A]
F[Service B]
end
subgraph Kernel
A -- 1 --> C[System Call Interface]
C -- 2 --> D[TCP/UDP]
D -- 3 --> E[IP]
E -- 4 --> D
D -- 5 --> C
C -- 6 --> F
end
Moreover, when commucate in the same host, IDS may experience overhead because it must implement the complex TCP/IP protocol, which includes many features that are only necessary for network communication.
Unix Domain Socket (UDS)
Unix Domain Sockets (UDS) are a type of IPC mechanism that allows Processes on the same Unix host to communicate with each other. UDS are implemented using the AF_UNIX
Socket family, which is also supported by the Windows 10. UDS uses shared file mechanism as communication method.
flowchart LR
subgraph Process
A[Service A]
F[Service B]
end
subgraph Kernel
A -- 1 --> C[System Call Interface]
C -- 2 --> D[File]
D -- 3 --> C
C -- 4 --> F
end
One advantage of using UDS is that they share the same interface as IDS. This means that developers can easily transition to using UDS without making significant changes to their code. Additionally, UDS can offer enhanced performance in certain situations due to the absence of an Internet Protocol.
Message Passing
Unlike sockets, which have a number of techniques and protocols to guarantee reliability, message passing is more focused on passing simple data structures. This means that message passing is typically faster than sockets in most cases.
Named pipe
A named pipe is a special file that allows processes to communicate with each other. It is a type of inter-process communication (IPC) mechanism. Named pipes are available on Unix-like operating systems, such as Linux and macOS.
Posix Message Queue
Posix message queues are a type of interprocess communication (IPC) that uses the kernel to send and receive messages between processes. Unlike other IPC mechanisms, such as sockets and pipes, POSIX message queues do not require the processes to be connected to each other. Instead, each process sends messages to a named queue, and any process that has access to the queue can receive the messages.
One of the advantages of POSIX message queues is that they are very efficient. Messages are not stored on the file system, so there is no need to read or write to the file system. This makes POSIX message queues much faster than other IPC mechanisms that use the file system, such as UDS.
Shared Memory
Conclusion
In the case of operations on the same host, there are numerous methods for Service Communication that focus on efficiency rather than relying solely on Network Protocols. Selecting the appropriate Inter-Process Communication (IPC) method for each specific problem can significantly enhance the performance and security of the system.
Resources
- W.Richard Stevens, Unix Network Programming Volume2: Interprocess Communications (2nd ed.), 1998, Prentice Hall
- W.Richard Stevens, Advanced Programming in the UNIX Environment (3rd ed.), 2013, Addison-Wesley
- Brian “Beej Jorgensen” Hall, Beej’s Guide to Interprocess Communication, 2023
- Communications Programming Concepts, Moscow State University Regatta community
- Sockets, IBM