The company is currently using Spring Cloud, and I feel that I don’t have a systematic understanding of Spring Cloud, so I plan to systematically sort out my understanding of Spring Cloud. While learning and practicing, I made a case of Spring Cloud by myself. Considering the slow access to GitHub, I put it on the code Cloud. The address is gitee.com/cxk6013/spr… Inside I have made a more detailed note, read might as well try to do it.

Introduction to microservices Architecture

When software in a slowly growing complex, development and operational costs are on the rise, this also is in the process of software development, one reason for the change or upgrade the structure, reduce the complexity of the software, and reduce the software complexity is a common way, will be split into several modules, a software that complexity were divvied up, good steel can also be used on the blade, What does that mean? Server, for example, the amount of the request all modules is not equal, some modules of traffic is bound to be very high, in electricity, for example, payment service or module in the usual traffic is relatively stable, but in a double tenth on this day, visitors can rapidly rising, companies often at this time will pay service expansion, to the payment service more resources, If these services are packaged as a whole, the resources I give cannot be enjoyed only by the payment service.

The reason why microservice architecture becomes the new normal is that it can well reduce the complexity of software, make full use of resources and improve the development speed. Separating the services sufficiently so that when the traffic of a service increases, I can expand the capacity of that service only, which is the full utilization of resources. In addition, I can achieve fast integration, when I reintegrate this service, it will not affect the other services, which is the decoupling. However, this does not mean that microservices are perfect. Managing and operating microservices has become a bit more complicated than in the past, which is why Docker and K8s are popular.

To sum up, the microservices discussed here refer to the microservice architecture. Roughly speaking, we can think of the microservice architecture as the separation of software modules according to the business, each module runs independently, and each module itself is a single unit.

Discuss distribution and clustering again

“A distributed system is a collection of independent computers that act as a single related system to the user.” Distributed system principle and Paradigm distributed system is a group of computers connected through the network to transmit messages and communication and coordinate their behavior of the system. Components interact with each other to achieve a common goal. Wikipedia

I’ve already discussed distribution and clustering in Software Architecture, but it’s not enough because technology continues to advance and resource utilization continues to increase. The distributed stress is a set of computer, yes, eggs can’t all in one basket, my idea is, if I have a computer resource is rich, use Docker to deploy, also calculate a distributed, and can’t calculate, because if the computer for some reason can not provide service? If you think of a process as an egg, the computer is the egg basket, and the basket breaks. I think the idea of distributed is to emphasize a group of computers and to emphasize this kind of disaster resilience, trying to minimize damage.

So how in the case of distributed system, a server can no longer provide services, our system can also provide services normally? As if the computer isn’t broken? That is clustering, where the same application is deployed several times on several servers. One’s broken. I’ve got another one. What if you break them all? I don’t think it’s that bad.

To sum up:

  • If several programs are deployed on several different computers, they cooperate with each other to complete a service through the network, then the system composed of these programs can be called a distributed system.
  • If it’s the same program that has been deployed on the machine multiple times, which is easy with Docker, it’s called centralized clustering.
  • If you have multiple deployments on different machines, you can call it a distributed cluster.

Compared with centralized cluster, distributed cluster has more disaster recovery capability, but also introduces new problems. This is the CAP theorem that we will discuss later.

The CAP theorem that you need to know

CAP principle, also known as CAP theorem, refers to Consistency, Availability and Partition tolerance in a distributed system. The CAP principle is that, at best, these three elements can achieve two, not all at once.

Let’s explain P first, because P looks high-end. The distributed system we discussed above emphasizes that different computers, different programs deployed on several different computers, collaborate with each other to complete a service through the network. We can think of the computers that make up a distributed system as a node.

Partition fault tolerance is to say that the communication between nodes may fail. When we only have a database, and one day a node of the distributed system cannot access the database because of network failure, then the partition is not fault tolerant.

Fault tolerance in order to ascend partition, we introduced a database again, this time this partition fault tolerance is further improved, but this time there is a new problem, namely how to keep the two database data consistency, to ensure the consistent, complete the necessary and sufficient conditions of the write operation is waiting for all nodes to success.

Each write operation waiting for all nodes to complete introduces reduced availability because writing data to all nodes may fail or take too long because you can’t guarantee that the network is absolutely reliable.

Conclusion: In order to improve the fault tolerance of partitions, we deploy the same services multiple times, and each service is the same. The more services are deployed, the higher the fault tolerance of partitions. Then data synchronization between these services becomes a new problem, namely consistency. If we insist on consistency, then usability will be reduced.

From the discussion above, we can conclude that CAP cannot have both. We have to choose the other option, CP and AP. But please note that it is not necessary to take AP and not C, we can relax the requirement for consistency.

In the above discussion, C is strong consistency, that is, the data of each node is the latest version. We can relax the requirement of consistency, that is, degradation, and there are different levels of consistency:

  • Weak consistency: Data on each node may not all be the latest version
  • Final consistency: Relax the time requirement, after a period of time, the data of each node is fully up to date.

For example, a write operation returns a response without waiting for all nodes to write, waiting some time to complete the synchronization of each node.

Availability requirements. For a system to meet availability requirements, every non-failing node must respond to every request. We generally measure the availability of a system by measuring downtime:

Reference blog post:

  • What does “P” mean in CAP theory?
  • Meaning of CAP theorem
  • CAP theory of distributed systems
  • The layman can understand SpringCloud, missed the blood loss!
  • The basic problem of distributed system: usability and consistency

Spring Cloud and Spring Boot

We mentioned the microservice architecture above. We split software modules according to business. We use Spring Boot to build services and Spring Cloud to govern services. What does this governance mean? Let’s think about the problems introduced when software is split into modules and each module runs independently:

  • How to resolve the intercall between services
  • If a service does not return a result for a long time due to network or other reasons, what should be done
  • How to manage the configuration of each module uniformly
  • How to block my real access path, that is, in my real access path wrapper layer, similar to the virtual mobile phone number

Spring Boot develops the Spring Cloud trilogy

Spring Boot positioning

Before, I found some information and added some groups, and some people would ask me how to learn the technology of Spring framework now. Some people would directly say, don’t learn Spring, Spring MVC, start from Spring Boot, saying that Spring Spring MVC is already behind. Spring Boot = Spring MVC = Spring Boot

Because we are in the development of Spring, SpringMVC configuration is more, have done SSM integration (SSM refers to Spring, SpringMVC, MyBatis) all know, to some extent we can think of these configuration is fixed, is who inject who and so on, So the general idea of Spring Boot is I’m going to do all of this for you and speed up your development. Besides, isn’t the versioning of some key dependencies a bit tricky? Spring Boot accelerates development further by bringing together some fixed dependencies, known as starters.

But the bottom layer of Spring Boot is still Spring, SpringMVC. There is no problem of who is more advanced than who, but the development of Spring Boot is faster, Spring Boot is a slightly larger topic, here limited space, not too much introduction, interested students can go down to check information.

Relationship between Spring Boot and Spring Cloud

Components in the Spring Cloud family are built using Spring Boot, so development is equally quick. But if something goes wrong, if you don’t know much about Spring Spring MVC, you’re at a loss.

Spring Boot is also a huge project, which includes a number of starter projects. Spring Cloud is a huge project, which includes various components. So we generally manage the versions of Spring Boot and Spring Cloud uniformly in the parent project.

General operations for Spring Boot development

  • To introduce dependencies, we usually use Maven
  • Writing configuration files
  • Annotate the startup class

This article introduces the Spring Cloud components

Here is the Spring Cloud Netflix family:

  • The Eureka registry oversees the discovery and interinvocation of services
  • Feign Remote caller
  • Ribbon Load balancer
  • Zuul gateway
  • Config Configuration Center
  • Hystrix fuse

Registry Eureka

If I have services A, B, and C, and I want to call service B, do I call service B directly from an explicit URL? Must not, in fact we can communication from the network to find the corresponding design idea, imagine the past the phone, assuming that A and B on the phone, is not A telephone cable from A home inside frame to B home, assume that A friend is more, A home phone line is not fit, this is just the two of the communication, suppose that we constantly introduce new users, This idea of connecting telephone lines directly from users who need to communicate with each other quickly makes our lines unmanageable, like this:

The cost of migration is too high. In fact, if we want to connect telephone lines and network cables, we will lead a network cable from our own house to access the network of telecom operators. There will be several middle layers in the middle to realize communication through these middle layers. Service A calls service B directly via an explicit URL(IP+ port + interface name: 192.168.3.1:8080 /buy/). When service B changes address, service A will follow suit. This is one of the uses of A registry:

This is where the Eureka registry comes in. The registry stores the service name. Registered services can use Eureka to get the service name of other services and make remote calls through the service name. Eureka is divided into servers and clients. The registry is a server, and clients need to provide services to the registry. Building microservices through Spring Cloud and Spring Boot is very simple and usually consists of three steps:

  • Importing dependencies (I assume you’ve already learned about Maven, but if you haven’t, check out this blog post: Maven Learning Notes)
  <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
Copy the code
  • Writing configuration files
server:
  port: 9991
eureka:
  client:
    service-url:
      defaultZone: http://localhost:${server.port}/eureka/
    register-with-eureka: false 
    fetch-registry: false
Copy the code

DefaultZone is the address of the registry, register-with-Eureka whether to let Eureka register itself. Fetch-registry Whether the Eureka obtains the addresses of other services itself.

  • Start the class with the corresponding annotation
EnableEurekaServer // This annotation identifies the service as a service registry.
SpringBootApplication
public class MicroEureka {
    public static void main(String[] args) { SpringApplication.run(MicroEureka.class,args); }}Copy the code

We get other uses for registries by thinking of them as telecommunications operators:

  • Service registration: Equivalent to an open number, the provider of a service, which is called by another service, registers itself in the registry by sending Rest requests, along with some of its metadata information (such as service name, port).

  • Renewal of service: equivalent to payment, the phone bill is running out, telecom operators will urge you to pay, if you do not pay will be cut off your phone. That is, after registering the service, the service provider maintains a heartbeat to keep the registry running at high speed, and I’m still alive.

  • Service offline: The pin number, which sends a Rest request to the Registry to tell the Eureka Server that the pin number is no longer needed when the service is about to shut down normally.

  • Getting services and invoking services: Equivalent to making a phone call, a service consumer can get a list of registered services through the registry and then make remote calls through Feign and the Ribbon using the service instance names from those lists.

  • Failure to eliminate: that is, downtime, you do not pay for a period of time, the telecommunications operator will continue to arrears will stop you. By default, services in the current list that have timed out (default: 90 seconds) and have not been renewed are excluded at regular intervals (default: 60 seconds).

  • Self-protection mechanism: Registry is so important that I can’t just deploy one registry. What if this one collapses, so we have to do a distributed cluster. But as we know, once it comes to distribution, we must choose. Eureka chooses AP, and fault tolerance of partition must exist, because you can never guarantee that the network is absolutely reliable. A is availability, that is to say, Eureka cannot guarantee strong consistency. Self-protection mode is a kind of security protection measure against abnormal network fluctuation. Using self-protection mode can make Eureka cluster more robust and stable operation.

  • The self-protection mechanism means that if more than 85% of the nodes have no normal heartbeat within 15 minutes, Eureka considers that there is a network fault between the nodes and the registry. At this time, Eureka enters the self-protection mechanism, and the following situations may occur:

    • Eureka Server will no longer remove services from the registry that should expire due to a long time without a heartbeat, waiting for the network to return to a stable state.
    • Eureka Server can still accept registration and query requests for new services, but will not be synchronized to other nodes to ensure that the current node is still available.
    • When the network is restored to a stable state, the new registration information is synchronized to other nodes.

Just like the telecom network, you can’t just connect to the telecom network. You also need communication tools, such as phones or computers, to communicate with others. The phones between services are Feign and the Ribbon

Eureka Registry reference Materials:

  • Spring Cloud Eureka self-protection mechanism
  • Spring Cloud Eureka self-protection mechanism official explanation
  • Eureka (Cluster mode)
  • The layman can understand SpringCloud, missed the blood loss!

Remotely call Feign and Ribbon

Feign completes calls between services

As usual with Spring Boot, we’ll first introduce dependencies:

	<dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
         </dependency>
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-openfeign</artifactId>
         </dependency>
            <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
Copy the code

Then write the corresponding configuration, as above:

Spring:
  application:
    name: cityclient
server:
  port: 8081
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9991/eureka/
Copy the code

Start class with the corresponding annotation:

SpringBootApplication
// This service is a Eureka client, only for Eureka
@EnableEurekaClient
There are many alternatives to registries, and this annotation fits seamlessly into other registries
@EnableDiscoveryClient
// Indicates that the service is to be invoked remotely
@EnableFeignClients
public class MicroEurekaClient {
    public static void main(String[] args) { SpringApplication.run(MicroEurekaClient.class,args); }}Copy the code

How do I call other services? In this example, I’m going to call the City service:

@FeignClient(value = "city") / / service name
public interface CityClient {
	// The corresponding URL
    @GetMapping("cityTest")
     String select(a);
}
Copy the code

Then inject into the corresponding control layer.

The Ribbon makes calls between services

The Ribbon calls services to each other through the RestTemplate, which we first load into the IOC container. Then call the corresponding controller:

   @Autowired
    private RestTemplate restTemplate;
    @GetMapping("testRibbon")
    public void  testRibbon(a){
        String result = restTemplate.getForObject("http://city/cityTest", String.class);
        System.out.println(result);
    }
Copy the code

Load Balancing Ribbon

In order to cope with the extra requests, we can form a cluster. That is to say, if I run another service for the same service, there will be two services for the same service. Then, which service should handle the request? These are load balancing algorithms and load balancers. There are two types of load balancing:

  • Client Load Balancing Ribbon Service List In Eureka, the ribbon receives a list from Eureka. When making a call, the Ribbon decides which service to call based on the load balancing algorithm.
  • Server load balancing (Nginx) There are two instances of the same service, and Nginx decides which service to accept the request.

Introduction to common load balancing algorithms:

  • Round Robin is the Round Robin method of allocating requests in turn, which you can simply say is queuing.
  • Random method A lucky service is selected at random to respond to the request.
  • Weighted polling assigns weight to each service and sets the service with the highest priority to respond to requests.

The Ribbon uses a polling algorithm by default. You can customize the Ribbon using the AbstractLoadBalancerRule class to override the Choose method.

Circuit breaker Hystrix

After we solve the invocation and load balancing of services, we will soon introduce a new problem. What if a service becomes unavailable for some reason or takes too long to respond to calls between services?

For example, in the Double Eleven, should users wait for the result of buying, or return an invalid if they fail to buy successfully within a period of time? People are tired of waiting, I believe you have the answer, is to return a failure results. This can improve the user experience. That’s what the fuse Hystrix does,

How does that fit with Feign? We usually do service calls with Feign,

// value specifies which service to call
// fallback specifies which class should return fast failure results
@FeignClient(value = "city", fallback = CityClientImpl.class) //
public interface CityClient {
	  // Address of the client
    @GetMapping("cityTest")
     String select(a);
}
Copy the code
@Component
public class CityClientImpl implements CityClient {
    @Override
    public String select(a) {
        return "Call failed"; }}Copy the code

Hystrix dashboard

The Hystrix dashboard, just like the dashboard of a car, displays the real-time performance of Hystrix. The Hystrix dashboard allows you to view Hystrix indicators and quickly identify problems in the system.

Page at startup:

Next page: )

Route gateway ZUul

So now we have a system structure that basically takes shape, and we have a structure like this,But our system also has the following problems:

  • The urls that the server exposes to the outside world are real, and the outside world uses these urls to launch attacks. In order to protect the security of the service, we can protect the security of the customer by making the phone call that the driver gets when receiving the order form virtual, and the URL that we expose to the outside can also be virtual.
  • Security check and login check redundancy: In order to ensure the system security, each module of microservice will do some verification, but the microservice is independent, we have to do a set of verification in each module of microservice. Obviously this is redundant.
  • Service instances and load balancers are heavily coupled: the outer load balancer, Nginx, needs to maintain all service listings, namely IP + port + service name. The day my IP and service partition change, I need to go to Nginx to change.

This leads to API gateway:, which solves the above problems. The gateway provides:

  • URL masking exposes the virtual URL to the outside, and the gateway maps the virtual URL to the real one
  • Unified verification reduces verification redundancy
  • Touching the coupling between service instances and load balancing is equivalent to adding an intermediate layer between service instances and Nginx, where Nginx does not directly access instances.

By the way, Zuul can also do load balancing. Will Nginx still use it? Gateways are also for clustering and load balancing, so Nginx can be used with Zuul.

With this layer, our architecture looks like this:

Configuration center Spring Cloud Config

So far we have architecture tend to perfect, but it is also not perfect place, the service will be our software architecture into one of the services, each service has a corresponding configuration file, when the service more, configuration file becomes difficult to manage, because it is dispersed in each service, and these profiles have in common, So we naturally have such a need, can unified management of microservices configuration files? This is where the configuration center comes in, and Spring Cloud provides us with the Config component, which is the configuration center.

The idea behind the configuration center of the Config component is this: Configuration files are centralized in the repository of code hosting websites such as Github and Gitee. The configuration center is directly connected to the repository. Each service indicates the configuration center and configuration file name in the configuration file, that is, requests resources from the configuration file, and then the configuration center pushes the corresponding file to the corresponding service.

conclusion

So far there has been a lot of competition between Spring Cloud components. There are Eureka and Nacos in the registry, and there are gateways as well. But the idea is still the same, split the modules, grasp the idea is good.

References:

  • SpringCloud 11: Hystrix Dashboard
  • Hystrix dashboard and Turbine cluster monitoring in Spring Cloud
  • Springboot2.0 hystrix Dashboard Unable to connect to Command Metric Stream solution
  • Springcloud-ribbon (Custom Load Balancing Algorithm)
  • The layman can understand SpringCloud, missed the blood loss!