The original link
3. Database mode
A. One library per service
The problem
How do you define the database architecture for microservices? The following issues need to be addressed:
- Services must be loosely coupled and can be developed, deployed, and scaled independently.
- Business transactions produce invariants that span multiple services.
- Some business transactions need to query data owned by multiple services.
- Copying and sharding are sometimes necessary to scale a database.
- Different services have different data storage requirements.
The solution
To solve these problems, you must use a per-service library, which is private to that service. It can only be accessed through the API of the microservice and cannot be directly accessed by other services. For example, for associated databases, private-tables-per-service, schema-per-service, or database-server-per-service can be used. Each microservice should have a separate database ID to provide a barrier to independent access from using tables from other services.
B. Each service shares the database
The problem
The above stated that one database per service is ideal for microservices, but that is for applications that have not yet been developed and will be developed using the DDD pattern. For an existing integrated application, this is not easy. What is the appropriate architecture in this case?
The solution
Sharing a database per service is not ideal, but it is a useful solution for the scenario above. Most people think of this as an anti-pattern for microservices, but for an existing application, it’s a good start to breaking the application into smaller logical chunks. This should not be applied to undeveloped applications. In this pattern, a database corresponds to multiple services, but only two or three at most, otherwise scaling, autonomy, and independence are difficult to achieve.
C. Command query duty separation (CQRS)
The problem
Once you implement per-service libraries, you need to query, you need to syndicate queries from multiple services — that’s not possible. So how do you implement queries in microservices?
The solution
CQRS recommends splitting the application into two parts — a command part and a query part. The command section handles add, delete, and change requests. The request part uses materialized views to handle queries. Typically used with the event source pattern. Keep the materialized view updated by subscribing to the event stream.
D.S aga model
The problem
How do you ensure data consistency after each service has its own database and a business transaction that spans multiple services? For example, for an e-commerce application, the customer has a credit limit and how to ensure that new orders do not exceed the credit limit. Because the order is in a different database than the customer, the application cannot simply use local ACID transactions.
The solution
Saga stands for high-level business process and consists of multiple sub-requests, each updating data in a service. Each request has a compensation request when it fails. This can be done in two ways:
- Choreography – If there is no central coordinator, each service generates events and listens for events of other services to decide whether to take some action.
- Orchestration – The Orchestration coordinator is responsible for making saga decisions and corresponding business logic.
4. Observable mode
A. Log aggregation
The problem
Consider a situation where an application contains multiple service instances running on multiple machines. Requests typically span multiple service instances. Each service instance generates a log file in standard mode. How can logging be used to understand application behavior for a particular request?
The solution
We need a centralized logging service that aggregates logs from each service instance. Users can search for and analyze logs. You can configure an alarm when certain information appears in logs. For example, PCF has a Loggeregator that collects logs from each component (routing, controller, Diego, and so on). AWS Cloud Watch has the same capabilities.
B. Performance indicators
The problem
As the set of microservices expands, it becomes critical to listen for transactions and alert when problems occur. How do we use metrics to monitor application performance?
The solution
A measurement service is required to collect statistics for individual operations. You need to aggregate application indicators and provide reports and alarms. There are two ways to aggregate metrics:
- Push — Services Push metrics to metrics services such as NewRelic, AppDynamics.
- Pull — Metric service gets metrics from a service, such as Prometheus.
C. Distributed tracking
The problem in microservices architectures, requests often span multiple services. Each service handles requests by performing multiple operations across services. So, how do you track down a request and troubleshoot a problem?
The solution
You need a service that can:
- Assign a unique external request ID to each external request.
- Pass the external request ID to all services.
- Include the external request ID in the log information.
- When a request is processed by the central service, the request information (such as start time, end time) is logged.
Spring Cloud Slueth and Zipkin servers are common implementations.
D. Health diagnosis
The problem
Once microservices are implemented, services may be online but cannot process transactions. How do I ensure that requests are not routed to these failed instances? Use a load balancing implementation.
The solution
Each service needs to have an endpoint that can be used to check the health of the application, such as /health. The API needs to check host status, connections to other services, and other specified logic.
Spring Boot Actuator implements a/Health endpoint and can also be customized.
5. Crosscutting focus pattern
A. External configuration
The problem
A service also calls other services and databases. There may be differences for each environment such as development, QA, UAT, production, endpoint URLS, or some configuration attributes. Any configuration changes may require regeneration and deployment. How do I avoid modifying code when configuration changes?
The solution
Externalize all configuration, including endpoint urls and certificates. Applications should load them at startup or run time.
The Spring Cloud configuration server provides the ability to externalize properties to GitHub and load environment properties from there. These can be accessed at application startup and updated without the need to restart the server.
B. Service discovery mode
The problem
- With container technology, IP addresses are dynamically assigned to service instances. Once the address is changed, the consumer needs to disconnect and manually change it.
- Consumers need to remember service urls and become tightly coupled.
The solution
A service registry is required so that metadata for producer services can be recorded. The registry needs to be registered when the service is started and unregistered when the service is shut down. The consumer or router should query the registry to find the location of the service. The registry also does health diagnostics of producer services to ensure that only working instances are available to consumers. There are two types of service discovery: client side and server side. Netflix Eureka is client-side discovery, AWS ALB is server-side discovery.
C. Fuse mode
The problem
A service usually invokes other services to fetch data. In this case, there are two problems: First, requests continue downstream, consuming network resources and reducing performance. Second, the user experience is poor. How do you gracefully handle cascading errors?
The solution
The consumer needs to invoke the service through a proxy that acts as a circuit breaker. When the number of consecutive failures exceeds a threshold, a circuit breaker is triggered and all attempts to invoke the service fail at once for a period of time. After some time, the breaker allows a portion of the test requests to pass. If these requests are successful, the breaker is restored to normal. Otherwise, the timeout period is recalculated.
D. The blue-green deployment mode
The problem
In a microservice architecture, an application has multiple microservices. If we stopped all the services and deployed a new version, the downtime would be long and would affect the business. Of course, a rollback would also be a nightmare. How can you reduce downtime at deployment time?
Solution Blue-green deployment strategies reduce downtime. It is implemented by running two identical build environments, blue and green. Assume that green is an existing system and blue is a new version of the application. Only one environment is online at any one time, and the online environment serves all production businesses. All cloud platforms offer blue-green deployment capabilities. See this article for more details.
There are many other patterns of microservice architecture, Sidecar, Chained Microservice, Branch Microservice, Event Sourcing Pattern, Continuous Delivery Patterns, etc. This list will continue to grow as microservices evolve. I want to hear what microservices models you’re using.
Microservices Design Patterns (PART 1)