First we look at why we should consider using MicroServices.
Development of single-use applications
Assuming you are preparing to develop a taxi scheduling software that competes with Uber and Hailo, you may start this new project manually or using the rails, Spring Boot, play, or maven-based generators through preliminary meetings and requirements analysis, and its hexagonal architecture is modular, The architecture diagram is as follows:
The application core is the business logic, which is done by the module that defines the services, domain objects, and events. Around the core is the adapter that deals with the outside world. Adapters include database access components, message components that produce and process messages, and Web modules that provide API or UI access support.
Although it is also modular logic, it will eventually be packaged and deployed as a standalone application. The specific format depends on the application language and framework. For example, many Java applications are packaged in the war format, deployed on Tomcat or jetty, while others are packaged in a self-contained jar format, and rails and node. JS are packaged into a hierarchical directory.
This style of application development is common because Ides and other tools are good at developing a simple application that is easy to debug, and simply runs the application, with selenium linking the UI to complete end-to-end testing. Monolithic applications are also easy to deploy, simply by copying packaged applications to the server side, and by running multiple copies on the backend of the load balancer, you can easily implement application extensions. This kind of application works very well in the early days.
Lack of single-application
Unfortunately, this simple approach has a lot of limitations. A simple application will gradually become larger over time. In each sprint, the development team will face the new "story" and then develop many new code. A few years later, this small and simple application will become a huge monster. Here's an example, I recently discussed with a developer who is writing a tool to analyze the dependencies between their jar files in an app with millions of lines of code. I'm pretty sure this code is a monster that many developers have been working on for years.
Once your application becomes a big and complex monster, the development team must be miserable. The main problem with agile development and deployment is that the application is too complex to be understood by any single developer. Therefore, it is very difficult and time-consuming to fix bugs and add new features correctly. In addition, team morale will also decline. If the code is difficult to understand, it cannot be modified correctly. Will eventually go to a huge, incomprehensible quagmire.
Single-use applications can also reduce development speed. The larger the application, the longer the startup time. For example, a recent survey shows that sometimes the application starts more than 12 minutes in time. I also heard that some applications require a 40-minute boot time. If the developer needs to restart the application frequently, the majority of the time will be spent waiting, productivity is greatly affected.
In addition, complex and huge monolithic applications are not conducive to sustainable development. Today, the normal SaaS application is changed many times a day, which is very difficult for the monolithic application model. In addition, the impact of this change is not well understood, so we have to do a lot of manual testing. Then, the ongoing deployment can be tough.
Monolithic applications can be very difficult to extend when resource conflicts occur in different modules. For example, a module that completes a CPU-sensitive logic should be deployed in the AWS EC2 Compute Optimized instances, while another memory database module is more appropriate for EC2 memory-optimized instances. However, because these modules are deployed together, a compromise has to be made on the hardware selection.
Monomer application Another problem is reliability. Because all modules run in a process, a bug in any module, such as a memory leak, can overwhelm the entire process. In addition, because all application instances are unique, this bug will affect the reliability of the entire application.
Finally, monolithic applications make it very difficult to adopt new architectures and languages. For example, imagine that you have 2 million lines of code written in the XYZ framework. If you want to change to an ABC framework, both time and cost are very expensive, even if the ABC framework is better. Therefore, this is an insurmountable chasm. You have to bow before the first choice.
To summarize: At first you had a very successful business-critical application and became a huge, incomprehensible monster. The use of outdated, inefficient technologies makes it difficult to hire potential developers. Applications are not scalable, reliability is low, and ultimately, agile development and deployment are not complete.
So how to deal with it?
Micro-processing architecture-dealing with complex things
Many companies, such as Amazon, ebay, and Netflix, have addressed these issues by adopting a micro-processing architecture model. The idea is not to develop a huge monolithic application, but to break down the application into small, interconnected microservices.
A micro-service typically accomplishes a specific function, such as order management, customer management, and so on. Each micro-service is a miniature hexagon application with its own business logic and adapters. Some microservices also publish APIs for use by other microservices and application clients. Other microservices complete a web UI that, when run, may be a cloud VM or a Docker container.
For example, a previous description of the system may be decomposed as follows:
Each application ribbon is done using microservices, and Web applications are split into a series of simple Web applications (such as a pair of passengers, a taxi driver). Such splits are easier to deploy for different users, devices, and special application scenarios.
Each backend service opens up a rest API, and many of the services themselves use APIs provided by other services. For example, driver management uses a notification service that informs the driver of a potential need. The UI service activates other services to update the Web page. All services are asynchronous, message-based communication. The micro-service internals will be discussed in the subsequent series.
Some rest APIs are also open to mobile apps used by passengers and drivers. These applications do not directly access back-end services, but instead pass intermediate messages through API gateway. API Gateway is responsible for load balancing, caching, access control, API billing monitoring and other tasks, can be easily implemented by Nginx, and subsequent articles will be introduced to the API Gateway.
• The microservices architecture pattern corresponds to the y-axis representing the extensible scale cube, which is a three-dimensional extension model described in the Art of Scalability book. The other two extendable axes, the x-axis consists of multiple copies of the application running on the load Balancer backend, and the z-axis is the routing of requirements to related services.
The application can be represented by the above three dimensions, and the y-axis represents the decomposition of the application into a microservices service. At run time, the X-axis represents running multiple instances that are hidden behind the load balancer, providing throughput capabilities. Some applications may also partition the service with the z-axis. The following figure shows how the trip management service is deployed on Docker running on AWS EC2.
At run time, the trip Management service is comprised of multiple service instances. Each of the service instances is a Docker container. To ensure high availability, these containers are typically run on multiple cloud VMs. A service instance is a load balancer, such as Nginx, that is responsible for distributing requests between instances. The load balancer also handles other requests, such as caching, permission control, API statistics, and monitoring.
This microservices architecture model profoundly affects the relationship between the application and the database, unlike traditional multiple services that share a single database, and the microservices architecture has its own database for each service . In addition, this way of thinking also affects the enterprise-level data model. At the same time, this pattern implies multiple data, but if you want to get the benefits of microservices, it is necessary for each service to have a single database, because this architecture requires this loose coupling. The following figure shows the sample application database schema.
Each service has its own database, and each service can be used in a more appropriate database type, also known as a multi-language consistency architecture. For example, driver management (discovering which driver is closer to the passenger) must use a database that supports geo-information queries.
On the surface, microservices architecture patterns are a bit like SOA, and they all consist of multiple services. However, the problem can be seen from a different perspective, and the microservices architecture pattern is an SOA that does not contain Web services (ws-) and ESB services. MicroServices applications prefer simple, lightweight protocols, such as rest, rather than ws-, to avoid using ESBS and similar ESB functions within microservices. The MicroServices architecture model also rejects the use of SOA concepts such as the canonical schema.
Benefits of MicroServices Architecture
The MicroServices architecture model has many benefits. First, the complexity of multiple service methods is solved by decomposing huge monolithic applications. In the case of constant functionality, the application is decomposed into multiple manageable branches or services. Each service has a boundary defined with rpc-or a message-driven API. The MicroServices architecture model provides a modular solution for features that are difficult to achieve with single-piece encoding, so that individual services can be easily developed, understood, and maintained.
Second, this architecture enables each service to be developed by a dedicated development team. Developers are free to choose the development technology and provide API services. Of course, many companies try to avoid confusion and only offer certain technical options. This freedom, then, means that developers do not have to be forced to use the outdated technology used at the beginning of a project, and they can choose the current technology. Even because the service is relatively simple, it is not very difficult to rewrite the previous code with today's technology.
Thirdly, the microservices architecture pattern is a standalone deployment of each microservices. Developers no longer need to coordinate the impact of other service deployments on the service. This change can speed up deployment. The UI team can use the AB test to quickly deploy changes. The MicroServices architecture model makes continuous deployment possible.
Finally, the MicroServices architecture pattern allows each service to scale independently. You can deploy the scale to meet your needs based on the size of each service. You can even use hardware that is better suited to the needs of your service resources. For example, you can deploy a CPU-sensitive service on EC2 Compute Optimized instances and deploy a memory database on EC2 memory-optimized instances.
The inadequacy of the micro-service architecture
Fred Brooks wrote 30 years ago that "there is no silver bullets", like any other technology, has a shortage of micro-service architectures. One of them is similar to his name, "MicroServices" emphasizes the size of the service, and in fact some developers preach to build a slightly larger, 10-100 Loc service group. Although small services are more likely to be adopted, don't forget that this is a terminal choice rather than a final goal. The purpose of microservices is to effectively split applications, enabling agile development and deployment.
Another major disadvantage is that micro-service applications are distributed systems, which can lead to inherent complexity. Developers need to choose between RPC or messaging and complete interprocess communication mechanisms. More than that, they must write code to handle local failures such as slow or unavailable message delivery. Of course, this is not a difficult task, but compared to the single-use language level of the method or process calls, micro-service under the technology seems more complex.
Another challenge for MicroServices comes from partitioned database architectures. It is common for business transactions to update messages to multiple business entities at the same time. This transaction is easy for single-use applications because there is only one database. In a microservices architecture application, you need to update the different databases used by different services. Using distributed transactions is not necessarily a good choice, not only because of the CAP theory, but also because today's highly scalable NoSQL databases and messaging middleware do not support this requirement. Eventually you have to use a final consistency approach, which puts a higher demand and challenge on the developer.
Testing an application that is based on a microservices architecture is also a complex task. For example, using the popular Spring boot architecture, it is easy to test its rest API for a single Web application. In turn, the same service test needs to start all services related to it (at least the stubs of these services). Again, the complexities of using a microservices architecture cannot be underestimated.
Another challenge is that changes in the application of MicroServices architecture patterns will ripple across multiple services. For example, suppose you are completing a case where you need to modify services A, B, C, and a relies on b,b for C. In a monolithic application, you just need to change the relevant modules, integrate the changes, and deploy just fine. In contrast, the microservices architecture model needs to take into account the impact of related changes on different services. For example, you need to update service C, then B, and finally a, fortunately, many changes typically affect only one service, and few changes require a coordinated multi-service change.
Deploying a microservices application is also complex, and a distributed application simply needs to deploy its own server behind the complex equalizer. Each application instance needs to be configured with basic services such as databases and message middleware. In contrast, a microservices application is typically comprised of a large number of services. For example, according to Adrian Cockcroft,hailo there are 160 different services, Netflix has about 600 services. Each service has more than one instance. This creates a number of parts that need to be configured, deployed, extended, and monitored, in addition to completing a service discovery mechanism (published in subsequent articles) to discover the address (including server address and port) of the communication service with it. The traditional problem-solving approach cannot be used to solve such complex problems. In succession, a successful deployment of a microservices application requires the developer to have sufficient control of the deployment method and a high degree of automation.
An automated approach is to use PAAs services, such as Cloud Foundry. PAAs provides developers with a simple way to deploy and manage microservices, and it packs all of these issues into a built-in solution. At the same time, system and network experts who configure PAAs can use best practices and strategies to simplify these issues. Another way to automate the deployment of microservices applications is to develop the most basic PAAs system for you. A typical starting point is the use of a clustered scheme, such as using Mesos or kubernetes with Docker. Later series we'll look at how the software deployment approach, such as Nginx, provides a convenient way to provide caching, permissions control, API statistics, and monitoring at the micro-service level.
Summarize
It's really hard to build complex applications. The monolithic architecture is more suitable for lightweight, simple applications. If you use it to develop complex applications, it's really bad. The MicroServices architecture model can be used to build complex applications, and of course, this architectural model has its own shortcomings and challenges.
In a subsequent blog, I'll delve into the microservices architecture pattern and discuss strategies such as service discovery, service deployment choices, and how to break down a distributed application for multiple services.
Core technology: Maven,springmvc MyBatis Shiro, Druid, Restful, Dubbo, Zookeeper,redis,fastdfs, activemq,nginx
1. Project Core code structure
Project Module Dependencies
Special Reminder: Developers can service or Dubbo their business rest when developing
2. Project Dependency Introduction
2.1 Backend Management system, rest service system, Scheculer timing dispatch system depend on such as:
2.2 Dubbo Independent service projects depend on such as:
3. Project function section:
Zookeeper, Dubbo service startup
Dubbo Control Console
Rest Service Platform
The advantages and disadvantages of micro-service architecture