Smart endpoints and dumb pipes
As your engineering organization transitions from building monolithic architectures to building microservices architectures, it will need to understand how to enable communications between microservices. In a monolith, the various components are all in the same process. In a microservices environment, components are separated by hard boundaries. At scale, a microservices environment will often have the various components distributed across a cluster of servers so that they are not even necessarily collocated on the same server.
This means there are two primary forms of communication between services:
-
Request/Response – One service explicitly invokes another service by making a request to either store data in it or retrieve data from it. For example, when a new user creates an account, the user service makes a request to the billing service to pass off the billing address from the user’s profile so that that billing service can store it.
-
Publish/Subscribe – Event-based architecture where one service implicitly invokes another service that was watching for an event. For example, when a new user creates an account, the user service publishes this new user signup event and the email service that was watching for it is triggered to email the user asking them to verify their email.
One architectural pitfall that generally leads to issues later on is attempting to solve communication
requirements by building your own complex enterprise service bus for routing messages between microservices.
It is much better to use a message broker such as Amazon Managed Streaming for Apache Kafka
Network communication often plays a central role in distributed systems. Service
meshes
Ambient Mesh
Amazon ECS Service Connect is another new addition to simplify service-to-service communication, service discovery, and traffic observability for Amazon ECS. Service Connect helps you build applications faster by letting you focus on the application code and not on your networking infrastructure.
Managing sidecar-based service meshes can be engaging and requires prior VPC networking experience; Amazon VPC Lattice simplifies this and provides a consistent way to connect, secure, and monitor communication between your services. You can define policies for network traffic management, access, and monitoring to connect compute services in a simplified and consistent way across instances, containers, and serverless applications. VPC Lattice manages all of your service-to-service connectivity, security, and monitoring needs so that you can focus on your application logic and deliver applications faster.
Sidecars can also be used to build monitoring solutions. When you are running microservices using Kubernetes, there are multiple observability strategies, one of them is using sidecars. Due to the modular nature of the sidecars, you can use it for your logging and monitoring needs. For example, you can setup FluentBit
The core benefit of building smart endpoints and dumb pipes is the ability to decentralize the architecture, particularly when it comes to how endpoints are maintained, updated, and extended. One goal of microservices is to enable parallel work on different edges of the architecture that will not conflict with each other. Building dumb pipes enables each microservice to encapsulate its own logic for formatting its outgoing responses or supplementing its incoming requests.
The following are the key factors from the twelve-factor app pattern methodology that play a role in building smart endpoints and dumb pipes:
-
Port Binding – Services bind to a port to watch for incoming requests and send requests to the port of another service. The pipe in between is just a dumb network protocol such as HTTP.
-
Backing services – Dumb pipes allow a background microservice to be attached to another microservice in the same way that you attach a database.
-
Concurrency – A properly designed communication pipeline between microservices allows multiple microservices to work concurrently. For example, several observer microservices may respond and begin work in parallel in response to a single event produced by another microservice.