A Preliminary Study of Microservices
What is a microservice
First of all, there is no official definition of microservices. It is difficult to describe microservices directly. We can understand what microservices are by comparing traditional WEB applications.
The core of traditional WEB application is divided into business logic, adapter and API or WEB interface accessed through UI. Business logic defines business processes, business rules, and domain entities. The adapter includes database access components, message components, and access interfaces. The architecture diagram of a taxi-hailing software is as follows:
Although they also follow modular development, they will eventually be packaged and deployed as a monolithic application. For example, Java applications will be packaged into WAR and deployed on Tomcat or Jetty.
This kind of single application is more suitable for small projects, the advantages are:
1. Development is simple and direct, centralized management
2. Basically no repeated development
3. The functions are all local, there is no distributed management overhead and call overhead
Of course its shortcomings are also very obvious, especially for Internet companies:
1. Low development efficiency: all development changes code in one project, submitting the code and waiting for each other, code conflicts continue
2. Code maintenance is difficult: code functions are coupled together, newcomers do not know where to start
3. The deployment is not flexible: the construction time is long, any small modification must rebuild the entire project, this process is often very long
4. Low stability: a trivial problem that can cause the entire application to hang
5. Insufficient scalability: unable to meet the business needs of high concurrency
Therefore, the current mainstream design generally adopts a microservice architecture. The idea is not to develop a huge monolithic application, but to decompose the application into small, interconnected microservices. A microservice completes a specific function, such as passenger management and order management. Each microservice has its own business logic and adapter. Some microservices also provide API interfaces for other microservices and application clients.
For example, the system described above can be decomposed into:
Each business logic is decomposed into a microservice, and the microservices communicate through REST API. Some microservices will also develop API interfaces for end users or clients. But under normal circumstances, these clients cannot directly access the back-end microservices, but pass requests through the API Gateway. API Gateway is generally responsible for tasks such as service routing, load balancing, caching, access control, and authentication.
Advantages of microservice architecture
The microservice architecture has many important advantages. 1. it solves the complexity problem. It decomposes a single application into a set of services. Although the total amount of functionality remains the same, the application has been broken down into manageable modules or services. These services define clear RPC or message-driven API boundaries. The microservice architecture strengthens the level of application modularity, which is difficult to achieve through a monolithic code base. Therefore, the development of microservices is much faster and easier to understand and maintain.
2. this architecture allows each service to be independently developed by a team dedicated to this service. As long as it conforms to the service API contract, developers can freely choose the development technology. This means that developers can use new technologies to write or refactor services. Since the services are relatively small, this will not have much impact on the overall application.
3. the microservice architecture allows each microservice to be deployed independently. Developers do not need to coordinate the deployment of service upgrades or changes. These changes can be deployed as soon as the test passes. Therefore, the microservice architecture also makes CI/CD possible.
Finally, the microservice architecture allows each service to be scaled independently. We only need to define the configuration, capacity, number of instances and other constraints that meet the service deployment requirements. For example, we can deploy CPU-intensive services on EC2 computing optimized instances, and deploy in-memory database services on EC2 memory optimized instances.
Disadvantages and challenges of microservice architecture
In fact, there are no silver bullets, and the microservice architecture will also bring us new problems and challenges. One of them is similar to its name. Microservices emphasize service size, but in fact there is no uniform standard. According to what rules business logic should be divided into microservices, this is an empirical project in itself. Some developers argue that 10-100 lines of code should be used to build a microservice. Although the establishment of small services is advocated by the microservice architecture, remember that microservices are a means to an end, not a goal. The goal of microservices is to fully decompose applications to promote agile development and continuous integration deployment.
Another major disadvantage of microservices is the complexity brought about by the distributed nature of microservices. Developers need to implement calls and communication between microservices based on RPC or messages, which makes the discovery between services, the tracking of service call chains, and quality issues very difficult.
Another challenge of microservices is the partitioned database system and distributed transactions. Business transactions that update multiple business entities are quite common. These types of transactions are very simple to implement in monolithic applications, because monolithic applications often only have one database. But under the microservice architecture, different services may have different databases. The constraints of the CAP principle make us have to abandon the traditional strong consistency and instead pursue ultimate consistency. This is a challenge for developers.
Microservice architecture also brings great challenges to testing. The traditional monolithic WEB application only needs to test a single REST API, and to test a microservice, it needs to start all other services it depends on. This complexity cannot be underestimated.
Another big challenge for microservices is changes across multiple services. For example, in a traditional monolithic application, if there are three services A, B, and C that need to be changed, A depends on B, and B depends on C. We only need to change the corresponding modules and deploy them all at once. But in the microservice architecture, we need to carefully plan and coordinate the change deployment of each service. We need to update C first, then update B, and finally update A.
Deploying applications based on microservices is also much more complicated. Monolithic applications can be simply deployed on the same set of servers, and then load balancing can be used on the front end. Each application has the same basic service address, such as database and message queue. Microservices are composed of a large number of different services. Each service may have its own configuration, number of application instances, and basic service address. Different configuration, deployment, expansion, and monitoring components are needed here. In addition, we also need a service discovery mechanism so that a service can discover the addresses of other services with which it communicates. Therefore, the successful deployment of microservice applications requires developers to have a better deployment strategy and a high degree of automation.
The above problems and challenges can be broadly summarized as follows:
- API Gateway
- Inter-service call
- Service discovery
- Service fault tolerance
- Service deployment
- Data call
Fortunately, there are many microservice frameworks that can solve the above problems.
The first generation of microservice framework
Spring Cloud provides developers with tools to quickly build general models of distributed systems (including configuration management, service discovery, fuses, intelligent routing, micro-agents, control buses, one-time tokens, global locks, leadership elections, distributed Sessions, cluster status, etc.). The main items include:
- spring cloud config: Centralized external configuration management supported by git repository. Configuration resources are directly mapped to the Spring Environment, but can be used by non-Spring applications if needed.
- spring cloud netflix: Integrate with various Netflix OSS components (Eureka, Hystrix, Zuul, Archaius, etc.).
- spring cloud bus: An event bus used to connect services and service instances with distributed messaging. Used to propagate state changes in the cluster (for example, configuration change events)
- spring cloud for cloud foundry: Integrate your application with Pivotal Cloudfoundry. Provide service discovery implementation, you can also easily realize the protection of resources through SSO and OAuth2, and you can also create a Cloudfoundry service proxy.
- spring cloud cloud foundry service broker: Provides a starting point for building and managing a service broker for services in Cloud Foundry.
- spring cloud cluster: Leader election and general state model (based on abstraction and implementation of zookeeper, redis, hazelcast, and Consul)
- spring cloud consul: service discovery and configuration management combined with Hashicorp Consul
- spring cloud security: Provide support for load-balanced OAuth2 dormant client and authentication header relay in Zuul proxy.
- spring cloud sleuth: Distributed tracing for Spring Cloud applications, compatible with Zipkin, HTrace and log-based (such as ELK) tracing.
- spring cloud data flow: Cloud native orchestration service for composable microservice applications in modern runtimes. The easy-to-use DSL, drag-and-drop GUI and REST-API together simplify the overall orchestration of data pipelines based on microservices.
- spring cloud stream: A lightweight event-driven microservice framework that can quickly build applications that can be connected to external systems. A simple declarative model for sending and receiving messages between Spring Boot applications using Apache Kafka or RabbitMQ.
- spring cloud stream app starters: Spring Cloud task application starters are Spring Boot applications, which may be any process, including Spring Batch jobs that will not run forever, and they end/stop after a limited time of data processing.
- spring cloud zookeeper: Zookeeper service discovery and configuration management
- spring cloud for amazon web services: easily integrate hosted Amazon Web Services services. It uses spring's idioms and APIs to easily integrate AWS services, such as caching or messaging APIs. Developers can build applications around managed services without worrying about the infrastructure.
- spring cloud connectors: enable PaaS applications to easily connect to back-end services on various platforms, such as databases and message brokers (previously known as "Spring Cloud" projects)
- spring cloud starters: As a startup project based on spring boot, reduce dependency management (after Angel.SR2, it is no longer an independent project)
- spring cloud cli: The plug-in supports the rapid creation of spring cloud component applications based on Groovy predictions
Dubbo is a distributed service framework open sourced by Alibaba, dedicated to providing high-performance and transparent RPC remote service invocation solutions and SOA service governance solutions. Its core parts include:
- Remote communication: Provides abstract encapsulation of a variety of NIO frameworks based on persistent connections, including multiple threading models, serialization, and information exchange methods in the "request-response" mode.
- Cluster fault tolerance: Provides transparent remote procedure calls based on interface methods, including multi-protocol support, and cluster support such as soft load balancing, failure tolerance, address routing, and dynamic configuration.
- Automatic discovery: Based on the registration center directory service, the service consumer can dynamically find the service provider, make the address transparent, and enable the service provider to smoothly add or reduce machines.
But it is obvious that both Dubbo and Spring Cloud are only suitable for specific application scenarios and development environments, and they are not designed to support versatility and multilingualism. And they are only the framework of the Dev layer, lacking the overall solution of DevOps (this is exactly what the microservice architecture needs to pay attention to). What followed was the rise of Service Mesh.
The next generation of microservices: Service Mesh?
Service Mesh is also translated as "service grid", as the infrastructure layer of communication between services. If you use one sentence to explain what Service Mesh is, you can compare it to TCP/IP between applications or microservices, responsible for network calls, current limiting, fusing, and monitoring between services. For writing applications, there is generally no need to care about the TCP/IP layer (such as RESTful applications through the HTTP protocol), and the same use of Service Mesh also eliminates the need for things between services that were originally implemented through applications or other frameworks. For example, Spring Cloud and OSS, now only need to be handed over to Service Mesh.
Service Mesh has the following characteristics:
- The middle layer of communication between applications
- Lightweight web proxy
- Application unaware
- Decoupling application retry/timeout, monitoring, tracking and service discovery
The architecture of Service Mesh is shown in the figure below:
Service Mesh runs as a Sidebar and is transparent to applications. All traffic between applications will pass through it, so the control of application traffic can be implemented in Service Mesh.
Currently popular Service Mesh open source software includes Linkerd, Envoy and Istio, and recently Buoyant (the company that open source Linkerd) has released the Kubernetes-based Service Mesh open source project Conduit.
Linkerd is an open source network agent, designed to be deployed as a service grid: a dedicated layer for management, control and monitoring of services within an application and communication between services.
Linkerd aims to solve the problems found when companies such as Twitter, Yahoo, Google, and Microsoft operate large-scale production systems. According to experience, the source of the most complex, surprising and urgent behavior is usually not the service itself, but the communication between services. Linkerd solves these problems, not just controlling the communication mechanism, but providing an abstraction layer on top of it.
Its main features are:
- Load balancing: Linkerd provides a variety of load balancing algorithms that use real-time performance indicators to distribute load and reduce the tail delay of the entire application.
- Fuse: Linkerd includes automatic fuse, which will stop sending traffic to instances that are considered unhealthy, so that they have a chance to recover and avoid cascading failures.
- Service discovery: linkerd integrates with various service discovery backends, and helps you reduce the complexity of your code by deleting specific (ad-hoc) service discovery implementations.
- Dynamic request routing: linkerd enables dynamic request routing and rerouting, allowing you to set up staging service, canaries, blue-green deploy, and cross-DC failures with the least amount of configuration Switching and dark traffic.
- Number of retries and deadline: linkerd can automatically retry the request when certain failures occur, and can time out the request after a specified period of time.
- TLS: linkerd can be configured to use TLS to send and receive requests, and you can use it to encrypt communications across host boundaries without modifying the existing application code.
- HTTP proxy integration: linkerd can be used as an HTTP proxy, and almost all modern HTTP clients are widely supported, making it easy to integrate into existing applications.
- Transparent proxy: You can use iptables rules on the host to set a transparent proxy through linkerd
- gRPC: linkerd supports HTTP/2 and TLS, allows it to route gRPC requests, and supports advanced RPC mechanisms such as two-way flow, flow control, and structured data load.
- Distributed tracing: linkerd supports distributed tracing and measurement instruments, which can provide uniform observability across all services.
- Instrumentation: Linkerd supports distributed tracking and measurement instruments, which can provide uniform observability across all services.
Envoy is designed for a service-oriented architecture L7 proxy and communication bus. This project was born out of the following goals:
For applications, the network should be transparent. When network and application failures occur, the root cause of the problem can be easily located.
Envoy can provide the following features:
- External process architecture: can work with applications developed in any language; can be quickly upgraded
- Based on the new C++11 coding: able to provide efficient performance
- L3/L4 filter: The core is an L3/L4 network proxy, which can be used as a programmable filter to implement different TCP proxy tasks and inserted into the main service. Support various tasks by writing filters, such as original TCP proxy, HTTP proxy, TLS client certificate authentication, etc.
- HTTP L7 filter: Supports an additional HTTP L7 filter layer. As a plug-in, the HTTP filter is inserted into the HTTP link management subsystem to perform different tasks, such as buffering, rate limiting, routing/forwarding, sniffing Amazon's DynamoDB, and so on.
- Support HTTP/2: In HTTP mode, it supports HTTP/1.1, HTTP/2, and supports HTTP/1.1, HTTP/2 two-way proxy. This means that HTTP/1.1 and HTTP/2 can be bridged in any combination of client and target server
- HTTP L7 routing: When running in HTTP mode, it supports path-based routing and redirection according to content type, runtime values, etc. Front-end/edge agent available for service
- Support gRPC: gRPC is an RPC framework from Google that uses HTTP/2 as the underlying multiplexing. The gRPC request and response carried by HTTP/2 can use Envoy's routing and LB capabilities
- Support MongoDB L7: Support for obtaining statistics and connection records and other information
- Support DynamoDB L7: Support for obtaining statistics and connection information
- Service discovery: supports multiple service discovery methods, including asynchronous DNS resolution and service discovery via REST request
- Health check: Contains a health check subsystem, which can perform active health check on upstream service clusters. Also supports passive health checks.
- Advanced LB: Including automatic retry, circuit breaker, global speed limit, blocking request, anomaly detection. In the future, it is also planned to support request rate control
- Front-end proxy: can be used as a front-end proxy, including TLS, HTTP/1.1, HTTP/2, and HTTP L7 routing
- Excellent observability: Provides reliable statistical capabilities for all subsystems. Currently supports statsd and compatible statistical libraries. You can also view statistical information through the management port, and support third-party distributed tracking mechanisms
- Dynamic configuration: provide hierarchical dynamic configuration API, users can use these APIs to build complex centralized management deployment
Istio is an open platform for connecting, managing and protecting microservices. Istio provides a simple way to build a deployed service network, with functions such as load balancing, inter-service authentication, and monitoring, without the need to change any service code. To add support for Istio to the service, you only need to deploy a special sidecar in the environment, use the Istio control panel function to configure and manage the agent, and intercept all network communications between microservices.
Istio currently only supports service deployment on Kubernetes, but other environments will be supported in future versions.
Istio provides a complete solution to meet the diverse needs of microservice applications by providing behavioral insight and operational control for the entire service grid. It provides many key functions uniformly in the service network:
- Traffic management: Control the flow of traffic and API calls between services, make calls more reliable, and make the network more robust in harsh conditions
- Observability: understand the dependencies between services, as well as the nature and flow of traffic between them, so as to provide the ability to quickly identify problems
- Strategy execution: Apply organizational strategy to the interaction between services to ensure that the access strategy is executed and resources are well distributed among consumers. The policy change is through configuring the grid instead of modifying the application code
- Service identity and security: Provide verifiable identities for services in the grid, and provide the ability to protect service traffic, so that it can be transferred on networks with different credibility
The Istio service grid is logically divided into a data panel and a control panel:
- The data panel consists of a set of intelligent agents (Envoy), which are deployed as sidecars to mediate and control all network communications between microservices
- The control panel is responsible for managing and configuring proxies to route traffic and enforce policies at runtime
The following figure shows the different components that make up each panel:
Conduit is an ultra-light service grid service designed for Kubernetes. It can transparently manage the runtime communication of services running on Kubernetes, making them more secure and reliable. Conduit provides visibility, reliability, and security features without changing the code.
Conduit service mesh is also composed of data panel and control panel. The data panel carries the actual network traffic of the application. The control panel drives the data panel and provides a northbound interface to the outside.
Linkerd and Envoy are similar. They are both a service-oriented communication network proxy, which can implement functions such as service discovery, request routing, and load balancing. Their design goal is to solve the communication problem between services and make the application unaware of service communication. This is also the core concept of Service Mesh. Linkerd and Envoy are like distributed Sidebars, and multiple proxies like Linkerd and Envoy are connected to each other to form a service mesh.
Istio is from a higher perspective, dividing Service Mesh into Data Plane and Control Plane. Data Plane is responsible for all network communications between microservices, and Control Plane is responsible for managing Data Plane Proxy:
And Istio naturally supports Kubernetes, which also bridges the gap between the application scheduling framework and Service Mesh.
There is less information about Conduit. From the official introduction, its positioning and functions are similar to Istio.
Kubernetes + Service Mesh
Kubernets has become the de facto standard for container scheduling and orchestration, and containers can be used as the smallest unit of work for microservices, thus giving play to the greatest advantages of the microservice architecture. So I think the future microservice architecture will revolve around Kubernetes. Service Meshes such as Istio and Conduit are designed for Kubernetes. Their appearance complements Kubernetes' shortcomings in service communication between microservices. Although Dubbo, Spring Cloud, etc. are all mature microservice frameworks, they are more or less bound to specific languages or application scenarios, and only solve the problems of the microservice Dev level. If you want to solve the Ops problem, they need to be combined with resource scheduling frameworks such as Cloud Foundry, Mesos, Docker Swarm or Kubernetes:
However, due to the initial design and ecology of this combination, there are many applicability issues that need to be resolved.
Kubernetes is different. It itself is a general-purpose container management platform that has nothing to do with the development language. It can support running cloud native and traditional containerized applications. And it covers the Dev and Ops stages of microservices, combined with Service Mesh, it can provide users with a complete end-to-end microservice experience.
So I think that the future microservice architecture and technology stack may be in the following form:
The multi-cloud platform provides microservices with resource capabilities (computing, storage, network, etc.). The container is the smallest unit of work that is scheduled and orchestrated by Kubernetes. Service Mesh manages the service communication of the microservice, and finally exposes the business interface of the microservice through the API Gateway. .
I believe that in the future, with the prevalence of microservice frameworks based on Kubernetes and Service Mesh, it will greatly reduce the cost of microservice implementation, and ultimately provide a solid foundation and guarantee for the implementation and large-scale use of microservices.
Original release time: 2018-07-24
author: Java architecture Meditations
"article from community partners Yunqi Java architecture Meditations " for information may concern " Java architecture Meditations "