Spring cloud learning notes

Understanding microservices

Architectural features of microservices

-Single responsibility: Micro services have smaller granularity, and each service corresponds to a unique business capability to achieve a single responsibility

-Autonomy: team independence, technology independence, data independence, independent deployment and delivery

-Service oriented: services provide a unified standard interface, independent of language and technology

-Strong isolation: do a good job in isolation, fault tolerance and degradation of service calls to avoid cascading problems


-Monomer architecture: simple and convenient, highly coupled, poor scalability, suitable for small projects. For example: student management system

-Distributed architecture: loose coupling and good scalability, but the architecture is complex and difficult. Suitable for large Internet projects, such as Jingdong and Taobao

-Microservice: a good distributed architecture scheme

① Advantages: smaller splitting granularity, more independent services and lower coupling

② Disadvantages: the architecture is very complex, making it more difficult to operate, monitor and deploy

-Spring cloud is a one-stop solution for microservice architecture, integrating various excellent microservice functional components

Service splitting and remote invocation

Service splitting principle

-Different microservices should not develop the same business repeatedly

-The microservice data is independent. Do not access the databases of other microservices

-Microservices can expose their business as interfaces for other microservices to call

Service split example


Cloud Demo: parent project, management dependency

-Order service: order micro service, which is responsible for order related businesses

-User service: user micro service, responsible for user related business


-Both order microservices and user microservices must have their own databases and be independent of each other

-Both order service and user service expose Restful interfaces

-If the order service needs to query user information, it can only call the Restful interface of the user service, not the user database

Register RestTemplate

First, we register the RestTemplate instance in the OrderApplication startup class in the order service:


Implement remote call

Modify the queryOrderById method in the OrderService class under the cn.itcast.order.service package in the order service service:


Provider and consumer

In the service invocation relationship, there are two different roles:

Service provider: a service called by other micro services in a business. (provide interfaces to other microservices)

Service consumer: Service in one business calling other micro services. (call interfaces provided by other microservices)

A service can be either a service provider or a consumer.

Eureka registry

Question 1: how does the order service know the user service instance address?

The process of obtaining address information is as follows:

-After the user service instance is started, register its own information with Eureka server (Eureka server). This is called service registration

-Eureka server saves the mapping relationship between service name and service instance address list

-Order service pulls the instance address list according to the service name. This is called service discovery or service pull

Question 2: how does order service select a specific instance from multiple user service instances?

-Order service selects an instance address from the instance list using the load balancing algorithm

-Make a remote call to the instance address

Q3: how does the order service know whether a user service instance is still healthy and has been down?

-The user service will send a request to Eureka server at regular intervals (30 seconds by default) to report its status, which is called heartbeat

-When no heartbeat is sent after a certain period of time, Eureka server will consider the microservice instance as faulty and remove it from the service list

-When the order service pulls the service, the fault instance can be eliminated


Build Eureka server

Create Eureka server service

First of all, let's register the service side of the center: Eureka server, which must be an independent microservice

Introducing eureka dependency


Write startup class

package com.zxq.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

public class EurekaApplication {
    public static void main(String[] args){

Write configuration file

Write an application.yml file as follows:

  port: 10086
    name: eureka-server

Start service

Start the microservice and access it in the browser:

Service registration

Introduce dependency

In the pom file of user service, introduce the following Eureka client dependency:


configuration file

In user service, modify the application.yml file and add the service name and eureka address:

    name: userservice

Service pull and load balancing

Finally, we need to pull the instance list of user service from Eureka server and realize load balancing. Modify the queryOrderById method in the OrderService class under the cn.itcast.order.service package in the order service service. Modify the url path of access, and replace ip and port with service name:


In the OrderApplication of order service, add a @ LoadBalanced annotation to the RestTemplate Bean:


Ribbon load balancing





Custom load balancing policy

By defining IRule, you can modify load balancing rules in two ways:

1. Code method: define a new IRule in the OrderApplication class in order service:

2. Configuration file method: add a new configuration in the application.yml file of order service, or modify the rules:

userservice: # Configure load balancing rules for a microservice. Here is the userservice service
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # Load balancing rules


Starvation loading

By default, the Ribbon uses lazy loading, that is, the LoadBalanceClient will be created during the first access, and the request time will be very long.

Hungry loading will be created when the project is started to reduce the time-consuming of the first access. Hungry loading can be started through the following configuration:

    enabled: true
    clients: userservice


1.Ribbon load balancing rules

The rule interface is IRule

The default implementation is ZoneAvoidanceRule. Select the service list according to the zone, and then poll

2. Custom load balancing method

Code method: the configuration is flexible, but it needs to be repackaged and published when modifying

Configuration method: intuitive and convenient. There is no need to repackage and publish, but global configuration cannot be done

3. Starvation loading

Turn on hungry loading

Specifies the name of the loaded microservice

Nacos registry

The service is registered with nacos

Nacos is a component of spring cloud Alibaba, which also follows the service registration and service discovery specifications defined in spring cloud. Therefore, there is not much difference between using Nacos and using Eureka for microservices.

Introduce dependency

Introduce the dependency of SpringCloudAlibaba in ` < dependencymanagement > 'in the pom file of the cloud demo parent project:


Then introduce the Nacos discovery dependency into the pom files in user service and order service:


Configure nacos address

Add the nacos address in application.yml of user service and order service:

      server-addr: localhost:8848

Service hierarchical storage model


Configure cluster for user service

Modify the application.yml file of user service and add the cluster configuration:

      server-addr: localhost:8848
        cluster-name: HZ # Cluster name

We copy a user service startup configuration again and add the following attributes:

-Dserver.port=8083 -Dspring.cloud.nacos.discovery.cluster-name=SH



Load balancing with cluster priority

Modify the application.yml file of order service and add the cluster configuration:

      server-addr: localhost:8848
        cluster-name: HZ # Cluster name

Modify load balancing rules

Modify the application.yml file of order service and modify the load balancing rules:

    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # Load balancing rules 

Cross cluster access

Weight configuration

No access when weight is 0 (can be used for upgrade)

Environment isolation - namespace

Configure the namespace for the microservice



At this time, access the order service. Because the namespace is different, the userservice will not be found, and the console will report an error:


The difference between Nacos and Eureka

The service instances of Nacos are divided into two l types:

-Temporary instance: if the instance goes down for more than a certain period of time, it will be removed from the service list. The default type is.

-Non temporary instance: if an instance goes down, it will not be removed from the service list. It can also be called a permanent instance.


Not culled

Nacos configuration management

Unified configuration management

Add profile in nacos



Pull configuration from microservice

Introducing Nacos config dependency

First, in the user service service, the client dependency of Nacos config is introduced:

<!--nacos Configuration management dependency-->

Add bootstrap.yaml

Then, add a bootstrap.yaml file in user service, as follows:

    name: userservice # Service name
    active: dev #Development environment, this is dev 
      server-addr: localhost:8848 # Nacos address
        file-extension: yaml # File suffix

Configure hot update

Mode 1:

Mode 2:

Use the @ ConfigurationProperties annotation instead of the @ Value annotation.

In the user service service, add a class and read the pattern.dateformat attribute:


Use this class in UserController instead of @ Value:



Configure sharing

Add an environment sharing configuration

We add a userservice.yaml file in nacos:

In the user service, modify the PatternProperties class and read the newly added attributes:



In the user service, modify the UserController and add a method:


Run two userapplications with different profile s




Configure shared priorities


Feign remote call

Introduce dependency

We introduce feign dependency in pom file of order service service:


adding annotations

Add annotations to the startup class of order service to enable Feign


Write Feign's client

Create a new interface in order service, as follows




Custom configuration

Modifying the log level of feign based on the configuration file can be for a single service

      userservice: # Configuration for a micro service
        loggerLevel: FULL #  log level 

It can also be for all services

      default: # default here is the global configuration. If the service name is written, it is the configuration for a micro service
        loggerLevel: FULL #  log level 

There are four levels of logs:

-NONE: no log information is recorded, which is the default value.

-BASIC: only record the requested method, URL, response status code and execution time

-HEADERS: on the basis of BASIC, additional header information of request and response is recorded

-FULL: records the details of all requests and responses, including header information, request body and metadata.

You can also modify the log level based on Java code, first declare a class, and then declare an object of Logger.Level:

public class DefaultFeignConfiguration  {
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // The log level is BASIC

If you want to * * take effect globally * *, put it in the @ EnableFeignClients annotation of the startup class:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)


If it is * * partially effective * *, put it in the corresponding @ FeignClient annotation:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)


Feign usage optimization

Feign initiates http requests at the bottom, which depends on other frameworks. Its underlying client implementation includes:

• URLConnection: it is implemented by default and does not support connection pool

• Apache HttpClient: supports connection pooling

• OKHttp: support connection pool

Introduce dependency

<!--httpClient Dependence of -->

Configure connection pool

      default: # default global configuration
        loggerLevel: BASIC # At the log level, BASIC is the BASIC request and response information
    enabled: true # Enable feign's support for HttpClient
    max-connections: 200 # Maximum connections
    max-connections-per-route: 50 # Maximum connections per path

In conclusion, Feign's Optimization:

1. Try to use basic for log level

2. Use HttpClient or OKHttp instead of URLConnection

① Introduce feign httpclient dependency

② The configuration file enables the httpClient function and sets the connection pool parameters

Best practices

Inheritance mode

The same code can be shared through inheritance:

1) Define an API interface, define methods, and make declarations based on spring MVC annotations.

2) Feign client and Controller have integrated interface



-Code sharing is realized


-Tight coupling between service providers and service consumers

-The annotation mapping in the parameter list does not inherit, so the method, parameter list and annotation must be declared again in the Controller

Extraction mode

Extract Feign's Client as an independent module, and put the POJO related to the interface and the default Feign configuration into this module for all consumers to use.

Gateway service gateway

Core functions and features of gateway:

-Request routing

-Permission control

-Current limiting

gateway quick start

Next, we will demonstrate the basic routing function of the gateway. The basic steps are as follows:

1. Create the SpringBoot project gateway and introduce the gateway dependency

2. Write startup class

3. Write basic configuration and routing rules

4. Start the gateway service for testing

Create a gateway service and introduce dependencies

<!--nacos Service discovery dependency-->

Write startup class

public class GatewayApplication {

	public static void main(String[] args) {
		SpringApplication.run(GatewayApplication.class, args);

Write basic configuration and routing rules

  port: 10010 # Gateway port
    name: gateway # Service name
      server-addr: localhost:8848 # nacos address
      routes: # Gateway routing configuration
        - id: user-service # Routing id, user-defined, as long as it is unique
          # uri: the destination address of 8081 # route http is the fixed address
          uri: lb://The target address lb of userservice # route is load balancing, followed by the service name
          predicates: # Routing assertion is to judge whether the request meets the conditions of routing rules
            - Path=/user/** # This is matched according to the path. It meets the requirements as long as it starts with / user /

Assertion factory

The assertion rules we write in the configuration file are just strings. These strings will be read and processed by the predict factory and transformed into conditions for routing judgment

For example, Path=/user / * * matches according to the path. This rule is determined by

`org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory ` class

There are more than a dozen assertion factories like this in the spring cloud gateway:


Filter factory

Gateway filter is a filter provided in the gateway, which can process the requests entering the gateway and the responses returned by the microservice:

Spring provides 31 different routing filter factories. For example:

Default filter

If you want to be effective for all routes, you can write the filter factory to default. The format is as follows:


      - id: user-service 
        uri: lb://userservice 
        - Path=/user/**
      default-filters: # Default filter
      - AddRequestHeader=Truth, helloworld

Global filter

The global filter is also used to handle all requests and microservice responses entering the gateway, just like the gateway filter. The difference is that the gateway filter is defined by configuration, and the processing logic is fixed; The logic of GlobalFilter needs to be implemented by writing code.

Custom global filter

public class AuthorizeFilter implements GlobalFilter {
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. Get request parameters
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2. Get the authorization parameter
        String auth = params.getFirst("authorization");
        // 3. Calibration
        if ("admin".equals(auth)) {
            // Release
            return chain.filter(exchange);
        // 4. Interception
        // 4.1. Prohibit access and set the status code
        // 4.2. End processing
        return exchange.getResponse().setComplete();

Filter execution sequence

The request to enter the gateway will encounter three types of filters: the filter of the current route, DefaultFilter and GlobalFilter

After requesting a route, the current route filter, DefaultFilter and GlobalFilter will be merged into a filter chain (Collection), and each filter will be executed in turn after sorting

What are the sorting rules?

-Each filter must specify an order value of type int. the smaller the * * order value, the higher the priority and the higher the execution order * *.

-GlobalFilter specifies the order value by implementing the Ordered interface or adding the @ order annotation, which is specified by ourselves

-The order of routing filter and defaultFilter is specified by Spring. By default, it is incremented from 1 in the order of declaration.

-When the order value of the filter is the same, it will be executed in the order of defaultfilter > routing filter > globalfilter.

Cross domain problem

What is a cross domain problem

Cross domain: domain name inconsistency is cross domain, mainly including:

-Domain names are different: www.taobao.com and www.taobao.org and www.jd.com and miaosha.jd.com

-The domain name is the same, but the port is different: localhost:8080 and localhost8081

Cross domain problem: the browser prohibits cross domain ajax requests between the initiator of the request and the server, and the request is intercepted by the browser

Solve cross domain problems

In the application.yml file of the gateway service, add the following configuration

      # . . . 
      globalcors: # Global cross domain processing
        add-to-simple-url-handler-mapping: true # Solve the problem that the options request is intercepted
            allowedOrigins: # Which websites are allowed to make cross domain requests 
              - "http://localhost:8090"
            allowedMethods: # Allowed cross domain ajax request mode
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # Header information allowed to be carried in the request
            allowCredentials: true # Allow cookie s
            maxAge: 360000 # Validity of this cross domain detection

Tags: Spring Cloud Microservices

Posted on Sun, 31 Oct 2021 00:23:56 -0400 by anthylon