Microservice notes 01

Draft, need post-processing

01. Micro service architecture

What is micro service?

Microservice architecture is an architecture model. It advocates dividing a single application into a group of small services, which coordinate and cooperate with each other to provide final value for users. Each service runs in its own independent process, and lightweight communication mechanism is adopted between services to cooperate with each other (usually restful API based on HTTP protocol). Each service is built around the specific business and can be independently deployed to production environment, class production environment, etc. In addition, a centralized service management mechanism should be avoided, and the appropriate service should be built according to the context.

Subject words 01:95 post digital life - landing dimension

Keyword 02: distributed micro Service Architecture - landing dimension

02. Introduction to springcloud

What is it?

SpringCloud = a one-stop solution for distributed service architecture, which is a collection of landing technologies of various micro service architectures, commonly known as micro service architecture

JD.COM

Ali

Conform to the dimension of micro Service Technology

Part I: springboot 2 X and springcloud H

Version correspondence

03. Payment module

1. Environmental construction

Hide idea folder

  1. maven builds a parent project:
  • Import dependency

    • <!-- unified management  jar Package version -->
          <properties>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
              <maven.compiler.source>1.8</maven.compiler.source>
              <maven.compiler.target>1.8</maven.compiler.target>
              <junit.version>4.12</junit.version>
              <log4j.version>1.2.17</log4j.version>
              <lombok.version>1.18.12</lombok.version>
              <mysql.version>5.1.47</mysql.version>
              <druid.version>1.1.16</druid.version>
              <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
          </properties>
      
          <!-- After the sub module inherits, it provides the following functions: locking the version+son modlue Do not write groupId and version  -->
          <dependencyManagement>
              <dependencies>
                  <!--spring boot 2.2.2-->
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-dependencies</artifactId>
                      <version>2.2.2.RELEASE</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
                  <!--spring cloud Hoxton.SR1-->
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-dependencies</artifactId>
                      <version>Hoxton.SR1</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
                  <!--spring cloud alibaba 2.1.0.RELEASE-->
                  <dependency>
                      <groupId>com.alibaba.cloud</groupId>
                      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                      <version>2.1.0.RELEASE</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
                  <dependency>
                      <groupId>mysql</groupId>
                      <artifactId>mysql-connector-java</artifactId>
                      <version>${mysql.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>com.alibaba</groupId>
                      <artifactId>druid</artifactId>
                      <version>${druid.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>org.mybatis.spring.boot</groupId>
                      <artifactId>mybatis-spring-boot-starter</artifactId>
                      <version>${mybatis.spring.boot.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>junit</groupId>
                      <artifactId>junit</artifactId>
                      <version>${junit.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>log4j</groupId>
                      <artifactId>log4j</artifactId>
                      <version>${log4j.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>org.projectlombok</groupId>
                      <artifactId>lombok</artifactId>
                      <version>${lombok.version}</version>
                      <optional>true</optional>
                  </dependency>
              </dependencies>
          </dependencyManagement>
      
          <build>
              <plugins>
                  <plugin>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-maven-plugin</artifactId>
                      <configuration>
                          <fork>true</fork>
                          <addResources>true</addResources>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
      

The difference between dependency management and dependencies

Maven uses the dependencyManagement element to provide a way to manage dependent version numbers.

Usually you will see the dependencyManagement element in the parent POM at the top level of an organization or project.

Use POM The dependencyManagement element in XML allows all to reference a dependency in a subproject without displaying the listed version number.

Maven will go up the parent-child hierarchy until it finds a project with a dependency management element, and then it will use the version number specified in the dependency management element.

Therefore, after you use dependency management to wrap up the dependencies, you will find that there is no import of these dependencies in our dependencies. I think these are restrictive. You still need to import them in the subproject.

Benefits:

  • If multiple subprojects refer to the same dependency, you can avoid declaring a version number in each used subproject. In this way, when you want to upgrade or switch to another version, you only need to update in the top-level parent container without modifying one subproject; In addition, if a sub project needs another version, you only need to declare version.

How to skip unit tests in maven

After the parent project is created, execute mvn:install to publish the parent project to the warehouse to facilitate the inheritance of the child project

Steps to create a microservice module

  1. Create module

    • Um......
  2. Change POM

    • <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
               http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <parent>
              <artifactId>cloud2020</artifactId>
              <groupId>com.lin</groupId>
              <version>1.0-SNAPSHOT</version>
          </parent>
        
          <modelVersion>4.0.0</modelVersion>
        
          <artifactId>cloud-provider-payment8001</artifactId>
        
          <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-actuator</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.mybatis.spring.boot</groupId>
                  <artifactId>mybatis-spring-boot-starter</artifactId>
              </dependency>
              <dependency>
                  <groupId>com.alibaba</groupId>
                  <artifactId>druid-spring-boot-starter</artifactId>
                  <version>1.1.10</version>
              </dependency>
              <!--mysql-connector-java-->
              <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
              </dependency>
              <!--jdbc-->
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-jdbc</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-devtools</artifactId>
                  <scope>runtime</scope>
                  <optional>true</optional>
              </dependency>
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <optional>true</optional>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
              </dependency>
          </dependencies>
      </project>
      
  3. Write yml

    • server:
        port: 8001
           
      spring:
        application:
          name: cloud-payment-service
        datasource:
          type: com.alibaba.druid.pool.DruidDataSource            # Current data source operation type
          driver-class-name: org.gjt.mm.mysql.Driver              # MySQL driver package com mysql. jdbc. Driver
          url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
          username: root
          password: 429208
      
      
      mybatis:
        mapperLocations: classpath:mapper/*.xml
        type-aliases-package: com.atguigu.springcloud.entities    # Package of all Entity alias classes
          
      
  4. Main startup class

    • package com.atguigu.springcloud;
        
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
        
      /**
       * @auther zzyy
       * @create 2020-01-27 19:50
       */
      @SpringBootApplication
      public class PaymentMain8001 {
          public static void main(String[] args) {
              SpringApplication.run(PaymentMain8001.class,args);
          }
      }
      
  5. Business class

Explore springboot's Web actor

These two dependencies should appear together

Write business code

vue-controller-service-dao-mysql

We pushed forward from behind

Functions of implements Serializable

Why should the basic data type of pojo layer be wrapped well

For example, for a Student class, we set its score attribute to
private Integer socre;
Not set to
private int socre;
This is because some students will get 0 points in the exam, while some students are absent from the exam. In this way, there is no way to distinguish.
The biggest difference between the wrapper type Integer and the basic type int is that the wrapper class can be set to null.
If the absence is set to null, it is ok.

For another example, when we use mybatis, mybatis will judge whether the parameter attribute is empty or null. If an attribute in our entity class uses a basic data type, such as int, the default is 0, then mybatis cannot judge this parameter.

@Resource comes with java

@Autowired is spring's

useGeneratedKeys = "true" keyProperty="id" usage

Above usage

Application background
During the development process, multiple tables may be operated at one time. For example, there are two tables: user table and order table. The primary key id is self incremented.

Application scenario: a new user adds a new order.

Operation process:

Insert a new record into the user table,
Get the id of this user,
Then insert the relevant information of the order in the order table (such as product name, price... And user id).
Divided into three steps, it is too waste of resources linked to the database. Why not directly return the primary key of the new user together with the insertion result after inserting the user record?

At this time, in mapper It is more convenient to add the parameter useGeneratedKeys = "true" keyProperty = "id" in XML!

principle
The useGeneratedKeys parameter in the Mybatis configuration file is valid only for the insert statement, and the default value is false. When set to true, it means that if the inserted table takes the self incrementing column as the primary key, JDBC is allowed to support the automatic generation of the primary key and return the automatically generated primary key.
--------
I'll understand after reading the above

mybatis code details

<resultMap id="BaseResultMap" type="com.lin.entities.Payment">
    <id column="id" property="id" jdbcType="BIGINT"/>
    <result column="serial" property="serial" jdbcType="VARCHAR"/>
</resultMap>

<insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO payment(`serial`) VALUES(#{serial});
</insert>

<select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap" >
    SELECT * FROM payment WHERE id=#{id};
</select>
  • resultMap can help us map the returned elements of mysql query results to one of our objects, and then complete the attribute mapping one by one

  • useGeneratedKeys = "true" keyProperty="id" this is described above, so I won't talk about it

  • 2022-01-17 22:10:25.335 INFO 34924 — [nio-8001-exec-7] com.lin.controller.PaymentController: ***** insert operation return result: 1

    Returning this result is a bit of a slap in the face, but I realized it in an instant. Because I am not the result of self increment in this project, I will not return it? I don't know. I'll talk about it later

Set return code

if (result > 0) {
    return new CommonResult(200, "Insert database succeeded", result);
} else {
    return new CommonResult(444, "Insert database failed", null);
}
  • 200: indicates successful insertion
  • 444: indicates insertion failure

postman sends a request

post request, I found that I can spell it directly by saying hello, observe the phenomenon, and then through the essence.

Don't realize that what happened two years ago has changed now

Just do it, xdm

Run DashBoard

It can only appear when there are many projects. At present, it is still a project and can't see the effect

Source of the article

The above method is no longer useful to my idea

This article can

  1. Click the plus sign and select spring boot

04. Hot deployment Devtools

  1. Import dependencies in subprojects

  2. Configure in parent project

    • <build>
          <plugins>
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
                  <configuration>
                      <fork>true</fork>
                      <addResources>true</addResources>
                  </configuration>
              </plugin>
          </plugins>
      </build>
      
    • < fork > true < fork > it must be true

  3. idea check

05. Order module

RestTemplate

RestTemplate provides a variety of convenient ways to access remote Http services,
It is a simple and convenient template class for accessing restful services. It is the client template tool set provided by Spring for accessing restful services

usage method

Official website address

https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

use
Using restTemplate to access restful interface is very simple and rude.
(url, requestMap, ResponseBean.class) these three parameters represent
REST request address, request parameters and HTTP response are converted to the object type.

common method

Parameter interpretation:

  • url: the url of the request
  • Object request: the request body, which is received by @ RequestBody
  • Class<?> Responsetype: response body, returned parameter object
  • uriVariables: this should be that we use restful style to splice strings and pass the splicing parameters together

Engineering reconstruction

Extract the same class of entities of the two classes

cn.hutool

gitee open source code

Introduction: 🍬 The small and comprehensive Java tool class library makes Java as elegant as a functional language and makes the Java language "sweet".

usage method

maven command clean install

The role of these two things:

This is a maven operation command corresponding to pom,
Among these commands, what is the most commonly used command for packaging projects?
The two most common packaging methods:
1. clean first, then package
2. clean first and then install
They are described in detail below:
The most direct way to clean up is to act on the orange target directory. Before the actual build, do some cleanup to remove all files generated by the last build. Executing this command will delete the target file under the project path, but will not delete the jar file generated by the local maven warehouse.
Validate: translate: validate. Verify the correctness of the project and whether the required information is complete.
Translation: compile. Everyone knows that the java identification file is Class, compile to generate class files, compile commands, and only compile the selected target. No matter whether it has been compiled before or not, a target directory will be generated under your project path, which contains a classes folder full of generated class files and bytecode files. Difference from build: only the selected target is compiled, regardless of whether it has been compiled before.
Test: Translation: test. Unit test.
Package: Translation: package. Package the project file into the specified format, such as JAR, WAR, etc. (look at your project's pom file. The packaging tag is to specify the packaging type). This command will create a target directory under your project path, and has the function of compile command to compile. At the same time, it will generate the jar/war file of the project under the target directory. If project a depends on project b, when packaging project b, it will only be packaged under the target of project b, and an error will be reported when compiling project A. because the dependent project b cannot be found, it indicates that project a has not found the project b it depends on in the local warehouse, so the install command is used.
Verify: Translation: verify. It mainly checks whether the package is effective and meets the standards.
Install: install. Install the package to the local warehouse so that other projects can rely on it. This command includes the function of package command. It will not only generate class files and jar packages under the project path, but also generate jar files in your local maven warehouse, For other projects (if maven local warehouse has not been set, it is generally in the user /. m2 directory. If project a depends on project b, when installing project b, pom files and jar files will be generated in the local warehouse at the same time, which solves the problem of packaging package error above).
Build: build. The function is similar to compile, but the difference is to compile the whole project. Difference and feature from compile: completely recompile the whole project, regardless of whether it has been compiled or not. The build process often generates release packages, which depends on the configuration of the IDE. Build is rarely used in practice, because it is basically not used in development. ANT and other tools are generally used in release and production. Build takes a long time because it needs to compile all and perform additional work such as packaging.
Site: Translation: site. Generate site documents for the project.
deploy: translate: configure deployment. Copy to remote warehouse.

06. Eureka study

What is service governance

Spring Cloud encapsulates the Eureka module developed by Netflix to realize service governance

In the traditional rpc remote invocation framework, it is complex to manage the dependency relationship between each service and service, so it is necessary to use service governance to manage the dependency relationship between services, which can realize service invocation, load balancing, fault tolerance, service discovery and registration.

  • Between services
  • Dependency, management
  • Manage dependencies between services
  • Service call
  • load balancing
  • fault-tolerant
  • Service discovery and registration

What is service registration and discovery

Eureka adopts the design architecture of CS. Eureka Server is the server of service registration function. It is the service registration center. Other microservices in the system use Eureka's client to connect to Eureka Server and maintain heartbeat connection. In this way, the maintenance personnel of the system can monitor whether each micro service in the system is running normally through Eureka Server.
In service registration and discovery, there is a registry. When the server starts, it will register its current server information, such as service address and communication address, in the registration center in the form of alias. The other party (consumer | service provider) obtains the actual service communication address from the registry in the way of this alias, and then realizes the local RPC call. The core design idea of RPC remote call framework is that the registry is used to manage a dependency between each service and service (service governance concept). In any RPC remote framework, there will be a registry (storing information about service address (interface address))

Eureka consists of two components: Eureka Server and Eureka Client

1. Eureka Server provides service registration services
After each micro service node is started through configuration, it will be registered in EurekaServer. In this way, the service registry in EurekaServer will store the information of all available service nodes, and the information of service nodes can be seen intuitively in the interface.

2. EurekaClient is accessed through the registry
It is a Java client used to simplify the interaction of Eureka Server. The client also has a built-in load balancer using round robin load algorithm. After the application starts, a heartbeat will be sent to Eureka Server (the default cycle is 30 seconds). If Eureka Server does not receive the heartbeat of a node in multiple heartbeat cycles, Eureka Server will remove the service node from the service registry (90 seconds by default)

Eureka Server build

  1. Create a basic project

  2. Change pom

    • <dependencies>
          <!--eureka-server-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
          </dependency>
          <!-- Introduce self defined api General package, you can use Payment payment Entity -->
          <dependency>
              <groupId>com.lin</groupId>
              <artifactId>cloud-api-common</artifactId>
              <version>${project.version}</version>
          </dependency>
          <!--boot web actuator-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
          <!--General configuration-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
          </dependency>
      
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
          </dependency>
      </dependencies>
      
  3. Write yml

    • server:
        port: 7001
      
      
      
      eureka:
        instance:
          hostname: localhost #Instance name of eureka server
        client:
          #false means that you do not register yourself with the registry.
          register-with-eureka: false
          #false means that my client is the registration center. My responsibility is to maintain service instances and I don't need to retrieve services
          fetch-registry: false
          service-url:
            #This address is required for setting the address query service and registration service interacting with Eureka Server.
            defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      
      
  4. Main start

    • import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
      
      @EnableEurekaServer
      @SpringBootApplication
      public class CloudEurekaServer7001Application {
          public static void main(String[] args) {
              SpringApplication.run(CloudEurekaServer7001Application.class,args);
          }
      }
      
    • Be sure to add @ EnableEurekaServer, or it will be over. Don't add @ EnableEurekaClient

    • localhost:7001, you can see the following figure

Eureka server and client dependencies

  • Server

  • <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  • client

  • <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
  • Why doesn't Eureka need to add a version number? Is it because spring cloud is already limited?

Eureka build

  1. Create project

  2. Change pom

    • <!--eureka-client-->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      
  3. Write yml

    • eureka:
        client:
          #Indicates whether to register yourself with EurekaServer. The default is true.
          register-with-eureka: true
          #Whether to retrieve the existing registration information from EurekaServer. The default value is true. Single node doesn't matter. The cluster must be set to true to use load balancing with ribbon
          fetchRegistry: true
          service-url:
            defaultZone: http://localhost:7001/eureka
      
    • [fetch](javascript: 😉: vt. fetch; Pick up; arrive; Attract vi. take;

    • Register n; Registration; Registration; Nationality of ship

  4. Main start

  5. Self protection mechanism

    • emergency! eureka may be incorrectly claiming instances are up when they're not. renewals are lesser than threshold and hence the instances are not being expired just to be safe.

Failed to bind properties under 'eureka.client.service-url' to java.util.Map<java.lang.String, java.lang.String>

Eureka cluster construction

Question: what is the core of micro service RPC remote service call
High availability. Imagine that your registry has only one only one. If it fails, ha ha ( ̄▽  ̄) "will lead to the unavailability of the whole service environment, so

Solution: build Eureka Registration Center cluster to realize load balancing + fault tolerance

Eureka cluster construction

  1. First, configure our local hosts

    • C:\Windows\System32\drivers\etc

    • Then add

    • ####################SpringCloud2020.1.2##################
      127.0.0.1	eureka7001.com
      127.0.0.1	eureka7002.com
      
  2. Then create an Eureka server, port 7002

    • Write yml

      • # Cluster configuration
        eureka:
          instance:
            hostname: eureka7001.com #Instance name of eureka server
          client:
            register-with-eureka: false     #false means that you do not register yourself with the registry.
            fetch-registry: false     #false means that my client is the registration center. My responsibility is to maintain service instances and I don't need to retrieve services
            service-url:
              defaultZone: http://eureka7002.com:7002/eureka/
        
    • 7001 that should also be changed to this

  3. Finally, the consumer and the Eureka corresponding to the yml of payment need to be changed

    • eureka:
        client:
          #Indicates whether to register yourself with EurekaServer. The default is true.
          register-with-eureka: true
          #Whether to retrieve the existing registration information from EurekaServer. The default value is true. Single node doesn't matter. The cluster must be set to true to use load balancing with ribbon
          fetchRegistry: true
          service-url:
            defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #Cluster version
      

Payment module cluster construction

  • Make a copy and change the port,
  • It should be noted that“ http://CLOUD-PAYMENT-SERVICE ”
  • Then change the baseUrl, because

No load balancing error

resolvent

  • @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
  • Default load balancing rules:

    • Once per service
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Tue Jan 18 17:29:26 CST 2022
There was an unexpected error (type=Internal Server Error, status=500).
I/O error on GET request for "http://CLOUD-PAYMENT-SERVICE/payment/get/1": CLOUD-PAYMENT-SERVICE; nested exception is java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://CLOUD-PAYMENT-SERVICE/payment/get/1": CLOUD-PAYMENT-SERVICE; nested exception is java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:751)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:677)
	at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:318)
	at com.lin.controller.OrderController.getPayment(OrderController.java:27)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1591)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:196)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:162)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394)
	at java.net.Socket.connect(Socket.java:606)
	at java.net.Socket.connect(Socket.java:555)
	at sun.net.NetworkClient.doConnect(NetworkClient.java:180)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:463)
	at sun.net.www.http.HttpClient.openServer(HttpClient.java:558)
	at sun.net.www.http.HttpClient.<init>(HttpClient.java:242)
	at sun.net.www.http.HttpClient.New(HttpClient.java:339)
	at sun.net.www.http.HttpClient.New(HttpClient.java:357)
	at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1226)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1162)
	at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1056)
	at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:990)
	at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76)
	at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
	at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:742)
	... 57 more

Ribbon

  • After the integration of Ribbon and Eureka, the Consumer can directly call the service without * * caring about the address and port number, and the service also has the load function** O(∩_∩)O

Actor micro service information improvement

eureka:
  client:
    #Indicates whether to register yourself with EurekaServer. The default is true.
    register-with-eureka: true
    #Whether to retrieve the existing registration information from EurekaServer. The default value is true. Single node doesn't matter. The cluster must be set to true to use load balancing with ribbon
    fetchRegistry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #Cluster version
  instance:
    instance-id: payment8001
    prefer-ip-address: true

design sketch:

Service Discovery

@Resource
private DiscoveryClient discoveryClient;

@GetMapping(value = "/discovery")
public Object discovery() {
    List<String> services = discoveryClient.getServices();
    for (String element : services) {
        System.out.println(element);
    }

    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    for (ServiceInstance element : instances) {
        System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t"
                           + element.getUri());
    }
    return this.discoveryClient;
}

result:

cloud-consumer-order
cloud-payment-service

CLOUD-PAYMENT-SERVICE 192.168.1.6 8001 http://192.168.1.6:8001
CLOUD-PAYMENT-SERVICE 192.168.1.6 8002 http://192.168.1.6:8002

Eureka self protection

summary

The protection mode is mainly used to protect a group of clients and Eureka Server in the scenario of network partition. Once in protected mode,
Eureka Server will try to protect the information in its service registry and will not delete the data in the service registry, that is, it will not log off any micro services.

If you see the following prompt on the homepage of Eureka Server, Eureka has entered the protection mode:
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.
RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE

Why Eureka self-protection mechanism?
In order to prevent Eureka client from running normally, but when the network with Eureka server is disconnected, Eureka server will not immediately eliminate Eureka client service

What is the self-protection model?
By default, if EurekaServer does not receive the heartbeat of a micro service instance within a certain period of time, EurekaServer will log off the instance (90 seconds by default). However, when the network partition fails (delay, jam, congestion), the micro service and EurekaServer cannot communicate normally, and the above behavior may become very dangerous - because the micro service itself is actually healthy, and the micro service should not be cancelled at this time. Eureka solves this problem through "self-protection mode" - when Eureka server node loses too many clients in a short time (network partition failure may occur), the node will enter self-protection mode.

In self-protection mode, Eureka Server will protect the information in the service registry and will not log off any service instances.
Its * * design philosophy is to retain the wrong service registration information rather than blindly cancel any possible healthy service instances** In one sentence: it's better to live than to die

To sum up, self-protection mode is a security protection measure to deal with network abnormalities. Its architectural philosophy is to retain all micro services at the same time (both healthy and unhealthy micro services will be retained) rather than blindly cancel any healthy micro services. Using self-protection mode can make Eureka cluster more robust and stable.

Turn off protection mode

Use Eureka server. Enable self preservation = false to disable self-protection mode

It is on by default

Shut down is when the eureka server is shut down

Effect after turning off self-protection mode

Note: I conducted the above test in 7001 and haven't changed it back yet

Set the heartbeat sending interval of the client and the waiting time of the server

eureka:
  client:
    #Indicates whether to register yourself with EurekaServer. The default is true.
    register-with-eureka: true
    #Whether to retrieve the existing registration information from EurekaServer. The default value is true. Single node doesn't matter. The cluster must be set to true to use load balancing with ribbon
    fetchRegistry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #Cluster version
  instance:
    instance-id: payment8001
    prefer-ip-address: true
    lease-renewal-interval-in-seconds: 10 # The time interval between Eureka client sending heartbeat to server, unit: seconds (default: 30 seconds)
    lease-expiration-duration-in-seconds: 20 # The upper limit of waiting time of Eureka server after receiving the last heartbeat, in seconds (the default is 90 seconds). If it times out, the service will be excluded

  • Lease renewal interval in seconds: 10 # Eureka client sends heartbeat to the server in seconds (30 seconds by default)
  • Leave expiration duration in seconds: 20 # Eureka server's maximum waiting time after receiving the last heartbeat. The unit is seconds (90 seconds by default). The service will be rejected when it times out

To test the effect, you can turn off the 8001 service. As soon as you refresh the page, you will find that the 8001 service is directly gg removed by Eureka.

07. Zookeeper learning

Installing zookeeper

  • docker installation is simple and fast. Ha ha

  • docker pull zookeeper:3.5.9

    docker run -d -e TZ="Asia/Shanghai" -p 2181:2181 --name zookeeper --restart always zookeeper

Service registration and discovery

Service provider

  1. Create project

    • Create a new cloud provider payment8004
  2. Change pom

    • <dependencies>
          <!-- SpringBoot integration Web assembly -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency><!-- Introduce self defined api General package, you can use Payment payment Entity -->
              <groupId>com.lin</groupId>
              <artifactId>cloud-api-common</artifactId>
              <version>${project.version}</version>
          </dependency>
          <!-- SpringBoot integration zookeeper client -->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
      </dependencies>
      
  3. Write yml

    • #8004 indicates the port number of the payment service provider registered to the zookeeper server
      server:
        port: 8004
      
      
      #Service alias -- register zookeeper to the registry name
      spring:
        application:
          name: cloud-provider-payment
        cloud:
          zookeeper:
            connect-string: 47.98.251.199:2181
      
  4. Main start

    • @EnableDiscoveryClient //This annotation is used to register services when using consumer or zookeeper as the registry
      @SpringBootApplication
      public class CloudProviderPayment8004Application {
          public static void main(String[] args) {
              SpringApplication.run(CloudProviderPayment8004Application.class,args);
          }
      }
      
    • @EnableDiscoveryClient: this annotation is used to register services when using consumer or zookeeper as the registry

zookeeper dependency error reporting

  • The spring cloud starter zookeeper discovery dependency we introduced comes with a zookeeper 3 5.3. If our dependency is greater than this version, what should we do without changing the dependency? Here is the solution.

    <!-- SpringBoot integration zookeeper client -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        <!--Exclude the self-contained first zookeeper3.5.3-->
        <exclusions>
            <exclusion>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!--add to zookeeper3.4.9 edition-->
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.9</version>
    </dependency>
    
    • I installed the zookeeper server of 3.5.9 myself, so I shouldn't have to worry about this problem.

Enter the inside of the dooker container of zookeeper

  • docker exec -it d46a204f6e1c(this is id) bash

View the services registered in zookeeper

  1. docker exec -it d46a204f6e1c(this is id) bash
  2. cd bin
  3. ./zkCli.sh
  4. ls /services

My operation

[root@iZbp1cor8i4hqjofynoigtZ /]# docker exec -it 3fa9d17cb9d4 bash
root@3fa9d17cb9d4:/apache-zookeeper-3.5.9-bin# cd bin
root@3fa9d17cb9d4:/apache-zookeeper-3.5.9-bin/bin# ./zkCli.sh
Connecting to localhost:2181
2022-01-18 23:33:38,179 [myid:] - INFO  [main:Environment@109] - Client environment:zookeeper.version=3.5.9-83df9301aa5c2a5d284a9940177808c01bc35cef, built on 01/06/2021 19:49 GMT
2022-01-18 23:33:38,182 [myid:] - INFO  [main:Environment@109] - Client environment:host.name=3fa9d17cb9d4
2022-01-18 23:33:38,182 [myid:] - INFO  [main:Environment@109] - Client environment:java.version=11.0.13
2022-01-18 23:33:38,195 [myid:] - INFO  [main:Environment@109] - Client environment:java.vendor=Oracle Corporation
2022-01-18 23:33:38,195 [myid:] - INFO  [main:Environment@109] - Client environment:java.home=/usr/local/openjdk-11
2022-01-18 23:33:38,195 [myid:] - INFO  [main:Environment@109] - Client environment:java.class.path=/apache-zookeeper-3.5.9-bin/bin/../zookeeper-server/target/classes:/apache-zookeeper-3.5.9-bin/bin/../build/classes:/apache-zookeeper-3.5.9-bin/bin/../zookeeper-server/target/lib/*.jar:/apache-zookeeper-3.5.9-bin/bin/../build/lib/*.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/zookeeper-jute-3.5.9.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/zookeeper-3.5.9.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/slf4j-log4j12-1.7.25.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/slf4j-api-1.7.25.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/netty-transport-native-unix-common-4.1.50.Final.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/netty-transport-native-epoll-4.1.50.Final.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/netty-transport-4.1.50.Final.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/netty-resolver-4.1.50.Final.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/netty-handler-4.1.50.Final.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/netty-common-4.1.50.Final.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/netty-codec-4.1.50.Final.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/netty-buffer-4.1.50.Final.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/log4j-1.2.17.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/json-simple-1.1.1.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jline-2.14.6.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jetty-util-ajax-9.4.35.v20201120.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jetty-util-9.4.35.v20201120.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jetty-servlet-9.4.35.v20201120.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jetty-server-9.4.35.v20201120.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jetty-security-9.4.35.v20201120.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jetty-io-9.4.35.v20201120.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jetty-http-9.4.35.v20201120.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/javax.servlet-api-3.1.0.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jackson-databind-2.10.5.1.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jackson-core-2.10.5.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/jackson-annotations-2.10.5.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/commons-cli-1.2.jar:/apache-zookeeper-3.5.9-bin/bin/../lib/audience-annotations-0.5.0.jar:/apache-zookeeper-3.5.9-bin/bin/../zookeeper-*.jar:/apache-zookeeper-3.5.9-bin/bin/../zookeeper-server/src/main/resources/lib/*.jar:/conf:
2022-01-18 23:33:38,195 [myid:] - INFO  [main:Environment@109] - Client environment:java.library.path=/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
2022-01-18 23:33:38,195 [myid:] - INFO  [main:Environment@109] - Client environment:java.io.tmpdir=/tmp
2022-01-18 23:33:38,195 [myid:] - INFO  [main:Environment@109] - Client environment:java.compiler=<NA>
2022-01-18 23:33:38,195 [myid:] - INFO  [main:Environment@109] - Client environment:os.name=Linux
2022-01-18 23:33:38,196 [myid:] - INFO  [main:Environment@109] - Client environment:os.arch=amd64
2022-01-18 23:33:38,196 [myid:] - INFO  [main:Environment@109] - Client environment:os.version=3.10.0-1160.31.1.el7.x86_64
2022-01-18 23:33:38,196 [myid:] - INFO  [main:Environment@109] - Client environment:user.name=root
2022-01-18 23:33:38,196 [myid:] - INFO  [main:Environment@109] - Client environment:user.home=/root
2022-01-18 23:33:38,202 [myid:] - INFO  [main:Environment@109] - Client environment:user.dir=/apache-zookeeper-3.5.9-bin/bin
2022-01-18 23:33:38,202 [myid:] - INFO  [main:Environment@109] - Client environment:os.memory.free=22MB
2022-01-18 23:33:38,204 [myid:] - INFO  [main:Environment@109] - Client environment:os.memory.max=247MB
2022-01-18 23:33:38,204 [myid:] - INFO  [main:Environment@109] - Client environment:os.memory.total=29MB
2022-01-18 23:33:38,225 [myid:] - INFO  [main:ZooKeeper@868] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@2344fc66
2022-01-18 23:33:38,244 [myid:] - INFO  [main:X509Util@79] - Setting -D jdk.tls.rejectClientInitiatedRenegotiation=true to disable client-initiated TLS renegotiation
2022-01-18 23:33:38,290 [myid:] - INFO  [main:ClientCnxnSocket@237] - jute.maxbuffer value is 4194304 Bytes
2022-01-18 23:33:38,308 [myid:] - INFO  [main:ClientCnxn@1653] - zookeeper.request.timeout value is 0. feature enabled=
Welcome to ZooKeeper!
2022-01-18 23:33:38,359 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1112] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2022-01-18 23:33:38,404 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@959] - Socket connection established, initiating session, client: /127.0.0.1:55092, server: localhost/127.0.0.1:2181
2022-01-18 23:33:38,421 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x101ef1ffe2d0001, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] ls /services
[cloud-provider-payment]
[zk: localhost:2181(CONNECTED) 1] ls /services/cloud-provider-payment
[13bce8e5-9b9d-4c3e-9820-d23077e45bfb]
[zk: localhost:2181(CONNECTED) 2] ls /services/cloud-provider-payment/13bce8e5-9b9d-4c3e-9820-d23077e45bfb
[]
[zk: localhost:2181(CONNECTED) 3] get /services/cloud-provider-payment/13bce8e5-9b9d-4c3e-9820-d23077e45bfb
{"name":"cloud-provider-payment","id":"13bce8e5-9b9d-4c3e-9820-d23077e45bfb","address":"192.168.1.6","port":8004,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"cloud-provider-payment","metadata":{}},"registrationTimeUTC":1642519693310,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}
[zk: localhost:2181(CONNECTED) 4] 

Service node

Rough classification: temporary node and persistent node

Subdivision: temporary node with serial number and temporary node; Node with serial number

The zoomeeper client we normally open is a temporary node by default. When we stop our service, we can't query this service node in zoomeeper. When we open this node again, we will find that the serial number of our service node in zoomeeper has changed.

Through this phenomenon, we can also see this situation.

Eureka won't hate so much, but will keep the serial number when it is opened again.

[zk: localhost:2181(CONNECTED) 4] ls /services/cloud-provider-payment
[13bce8e5-9b9d-4c3e-9820-d23077e45bfb]
[zk: localhost:2181(CONNECTED) 5] ls /services/cloud-provider-payment
Node does not exist: /services/cloud-provider-payment
[zk: localhost:2181(CONNECTED) 6] ls /services/cloud-provider-payment
[4fb25cc0-8f37-41a1-8ead-16bb7507e081]

Then I have a question

Is Eureka in protected mode by default? It seems so, but why is it that when I close a service during the test, the service with protection mode turned on and the server without protection mode can't display that service.

Here is the answer you want

1, Turn on Eureka self-protection mode
When visiting Eureka's home page, if you see such a bright red sentence:

*EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.*

Then it shows that Eureka's self-protection mode is activated.

There are several ways to solve this situation:
\1. Wait for Eureka Server to recover automatically
Under normal circumstances, after waiting for network recovery (or no frequent startup and shutdown of instances), Eureka Server will automatically turn off the self-protection mode after waiting for a period of time. However, if it fails to turn off the mode for a long time, you can try to turn it off manually, as shown below.

\2. Restart Eureka Server
Generally speaking, the PRD environment recommends load balancing the Eureka Server, so that after the Eureka Server is shut down and turned on in turn, the invalid instances will be cleared and will not affect the normal use.

\3. Turn off Eureka's self-protection mode
Later

2, Eureka self-protection mode principle
By default, if more than 85% of the client nodes do not have a normal heartbeat within 15 minutes, Eureka considers that there is a network failure between the client and the registry (such as network failure or frequent startup and shutdown of the client), and Eureka Server automatically enters the self-protection mode. No more services will be eliminated. When the network fault recovers, the node will automatically exit the self-protection mode.

eureka:
  server:
    #In the self-protection mode, when there are network partition failures, frequent opening and closing of clients, and eureka loses too many clients in a short time, it will enter the self-protection mode, that is, if a service does not send heartbeat for a long time, eureka will not delete it. The default is true
    enable-self-preservation: true
    #The time interval for eureka server to clean up invalid nodes. The default is 60000 milliseconds, that is, 60 seconds
    eviction-interval-timer-in-ms: 60000
    #The time interval of threshold update, in milliseconds, is 15 * 60 * 1000 by default
    renewal-threshold-update-interval-ms: 15 * 60 * 1000
    #The threshold factor is 0.85 by default. If the threshold is greater than the minimum value, the self-protection mode will be turned on
    renewal-percent-threshold: 0.85
    #The time interval between the wake-up of the cleaning task program and the cleaning of expired incremental information. The unit is milliseconds. The default is 30 * 1000
    delta-retention-timer-interval-in-ms: 30000

Self protection mode is a security protection measure for network abnormalities. Using self-protection mode makes Eureka cluster more robust and stable.

3, Turn off Eureka's self-protection mode
You can use Eureka server. Enable self preservation = false to disable the self-protection mode, * * * * is suitable for use in the development / test environment. It is recommended to turn on the self-protection mode in the production environment****

For Eureka Server in the development / test environment, I personally recommend turning off its self-protection mode, because you may need to constantly turn on and off instances. If the self-protection mode is not turned off, it is easy to trigger the self-protection mode. At this time, debugging will be relatively troublesome.

However, when the self-protection mode is turned off, there may be another possible problem, that is, after a period of time, the instance may not be closed but cannot be accessed through the gateway. At this time, it is likely that the instance (or gateway) is disconnected from Eureka Server due to network problems, and Eureka Server has logged it off (after the network is restored, the instance will not be registered again), At this point, restart the Eureka Server node or instance and wait for a short period of time.

Turn off self-protection mode, which can be configured on the server and client.

Server configuration:
eureka:
  server:
    enable-self-preservation: false
    #The time interval for eureka server to clean up invalid nodes. The default is 60000 milliseconds, that is, 60 seconds
    eviction-interval-timer-in-ms: 60000 # Unit: ms

Client configuration:
# Heartbeat detection and renewal time
# Set the value lower during the test to ensure that the registration center can kick out the service in time after the service is closed
eureka:
  instance:
    lease-renewal-interval-in-seconds: 1
    lease-expiration-duration-in-seconds: 2
 Configuration description lease-renewal-interval-in-seconds 1 per interval s,Send a heartbeat to the server to prove that you are still "alive".
lease-expiration-duration-in-seconds  Tell me if server 2 s If I don't send you a heartbeat within, it means I'm "dead". Please kick me out.

4, Eureka's health examination

Note: UP is displayed in the Status column, indicating that the application Status is normal. Other values are DOWN and OUT_OF_SERVICE, UNKNOWN, etc. only the UP micro service will be requested.

Since the heartbeat mechanism is used between Eureka Server and Eureka Client to determine the state of Eureka Client, by default, the heartbeat of server and client remains normal, and the application will always maintain the "UP" state, so the UP of microservice can not fully reflect the state of the application.

Spring Boot Actuator provides the / health endpoint, which can display the health information of the application. You can only propagate the health status in the endpoint to Eureka Server. This is very simple. You only need to configure the following for the micro service:
#Enable health check (spring boot starter actuator dependency)

eureka.client.healthcheck.enabled = true

Cluster construction (self-study)

  • I don't think it's necessary to focus on learning. Nacos is the focus. Then I learned it twice, hahaha, er..., Now I don't know what I've learned
  • So be sure to take notes

Self feeling and confusion

How do we implement remote call?

We inject RestTemplate and add @ LoadBalanced to it. Then our service has been registered into the server, so we initiate the request

Our restTemplate object will be found in the registry through the url

public static final String INVOKE_URL = "http://cloud-provider-payment";
//Cloud provider payment: service name. The service is registered in the service center

08. Consul learning

brief introduction

Consul is an open source distributed service discovery and configuration management system developed by HashiCorp in Go language.

It provides the functions of service governance, configuration center, control bus and so on. Each of these functions can be used alone or together to build a comprehensive service grid. In short, Consul provides a complete service grid solution.

It has many advantages. Including: Based on raft protocol, relatively simple; It supports health check, HTTP and DNS protocols, WAN clusters across data centers, graphical interfaces across platforms, Linux, Mac and Windows

What can I do

install

docker pull consul:1.6.1

docker run -d -p 8500:8500 --restart=always --name:consul consul:1.6.1

Create consumer

  1. establish

  2. Change pom

    • <dependencies>
          <!--SpringCloud consul-server -->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-consul-discovery</artifactId>
          </dependency>
          <!-- SpringBoot integration Web assembly -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
          <!--Daily general jar Package configuration-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
      </dependencies>
      
  3. Write yml

    • ###Consumer service port number
      server:
        port: 80
      
      spring:
        application:
          name: consul-consumer-order
        ####Address of consumer Registration Center
        cloud:
          consul:
            host: 47.98.251.199
            port: 8500
            discovery:
              #hostname: 127.0.0.1
              service-name: ${spring.application.name}
              heartbeat:
                enabled: true # Heartbeat transmission
      
  4. Main start

    • import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      
      @EnableDiscoveryClient
      @SpringBootApplication
      public class PaymentMain8006 {
          public static void main(String[] args) {
              SpringApplication.run(PaymentMain8006.class,args);
          }
      }
      

CAP

C: Consistency (strong consistency)

A: Availability

P: Partition tolerance

CPA theory focuses on the granularity of data rather than the strategy of overall system design.

The core of CAP theory

At most, two can be satisfied at the same time.
The core of CAP theory is that a distributed system cannot meet the three requirements of consistency, availability and partition fault tolerance at the same time,
Therefore, according to the CAP principle, NoSQL database is divided into three categories: meeting the CA principle, meeting the CP principle and meeting the AP principle:
CA - single point cluster, a system that meets consistency and availability, is usually not very powerful in scalability.
CP - systems that meet consistency and partition tolerance, usually have low performance.
AP - a system that meets the requirements of availability and partition tolerance. Generally, it may have lower requirements for consistency.

Eureka: AP architecture

AP architecture
After the network partition appears, in order to ensure the availability, system B can return the old value to ensure the availability of the system.
Conclusion: it violates the requirements of consistency C and only meets the requirements of availability and partition fault tolerance, that is, AP

Zookeeper / Consumer: CP architecture

CP architecture
When the network partition appears, in order to ensure the consistency, the request must be rejected, otherwise the consistency cannot be guaranteed
Conclusion: it violates the requirements of availability A and only meets consistency and partition fault tolerance, that is, CP

Ribbon load balancing

brief introduction

Spring Cloud Ribbon is a set of client-side load balancing tools based on Netflix Ribbon.

In short, ribbon is an open source project released by Netflix. Its main function is to provide software load balancing algorithms and service calls on the client. Ribbon client component provides a series of perfect configuration items, such as connection timeout, Retry, etc. To put it simply, list all the machines behind the Load Balancer (LB) in the configuration file. The ribbon will automatically help you connect these machines based on certain rules (such as simple polling, random connection, etc.). We can easily use ribbon to implement a custom load balancing algorithm.

What can I do

What is LB load balance
Simply put, it is to distribute the user's requests equally to multiple services, so as to achieve the HA (high availability) of the system.
Common load balancing include software Nginx, LVS, hardware F5, etc.

Ribbon local load balancing client VS Nginx server load balancing difference
Nginx is server load balancing. All client requests will be handed over to nginx, and then nginx will forward the requests. That is, load balancing is realized by the server.

Ribbon local load balancing, when calling the micro service interface, will obtain the registration information service list on the registry and cache it to the JVM local, so as to realize the RPC remote service call technology locally.

Centralized LB

That is, an independent LB facility (which can be hardware, such as F5, or software, such as nginx) is used between the service consumer and the service provider, and the facility is responsible for forwarding the access request to the service provider through some policy;

In process LB

Integrate LB logic into the consumer. The consumer knows which addresses are available from the service registry, and then selects a suitable server from these addresses.

Ribbon belongs to in-process LB, which is just a class library integrated into the consumer process, through which the consumer obtains the address of the service provider.

Load balancing + RestTemplate call

Architecture description

Ribbon works in two steps
The first step is to select Eureka server, which gives priority to servers with less load in the same region
The second step is to select an address from the service registration list obtained from the server according to the policy specified by the user.
Among them, Ribbon provides a variety of strategies: such as polling, random and weighting according to response time.

Summary: Ribbon is actually a client component of soft load balancing,
It can be used in combination with other clients that need requests, and the combination with eureka is just one example.

use

Ribbon and Eureka are configured and used. We can easily find that Eureka has built-in ribbon

Use with RestTemplate

T getForObject(String url, Class responseType, Object... uriVariables);

T getForObject(String url, Class responseType, Map<String, ?> uriVariables);

T getForObject(URI url, Class responseType);

ResponseEntity getForEntity(String url, Class responseType, Object... uriVariables);

ResponseEntity getForEntity(String url, Class responseType, Map<String, ?> uriVariables);

ResponseEntity getForEntity(URI var1, Class responseType);

T postForObject(String url, @Nullable Object request, Class responseType, Object... uriVariables);

T postForObject(String url, @Nullable Object request, Class responseType, Map<String, ?> uriVariables);

T postForObject(URI url, @Nullable Object request, Class responseType);

ResponseEntity postForEntity(String url, @Nullable Object request, Class responseType, Object... uriVariables);

ResponseEntity postForEntity(String url, @Nullable Object request, Class responseType, Map<String, ?> uriVariables);

ResponseEntity postForEntity(URI url, @Nullable Object request, Class responseType);

IRule: select a service to be accessed from the service list according to a specific algorithm

  • com. netflix. loadbalancer. Roundrobin rule: polling
  • com.netflix.loadbalancer.RandomRule: random
  • com.netflix.loadbalancer.RetryRule: first obtain the service according to the round robin rule (polling) policy. If the service acquisition fails, it will retry within the specified time to obtain the available service
  • Weighted responsetimerule: an extension of round robin rule. The faster the response speed, the greater the weight of instance selection, and the easier it is to be selected
  • Best available rule: it will first filter out the services in the circuit breaker tripping state due to multiple access faults, and then select a service with the least concurrency
  • Availability filtering rule: filter out the failed instances first, and then select the less concurrent instances
  • ZoneAvoidanceRule: the default rule, which determines the performance of the region where the server is located and the availability of the server, and selects the server

Practical use

The official document clearly gives a warning:
This custom configuration class cannot be placed under the current package and sub package scanned by @ ComponentScan,
Otherwise, the configuration class we customized will be shared by all Ribbon clients, and the purpose of customization will not be achieved.

1. Disposition

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule() {
        return new RandomRule();//Defined as random
    }
}

2. Main start

@RibbonClient(name = "cloud-payment-service",configuration = MySelfRule.class)//Deliberately use lowercase names
@EnableEurekaClient
@SpringBootApplication
public class CloudConsumerOrder80Application {
    public static void main(String[] args) {
        SpringApplication.run(CloudConsumerOrder80Application.class,args);
    }
}

3,restTemplate

@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
  • Don't forget this
  • Tested it. It's really no problem

principle

Load balancing algorithm: the number of requests of the rest interface% the total number of server clusters = the subscript of the actual calling server location. The count of the rest interface starts from 1 after each service restart.

List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");

For example: List [0] instances = 127.0.0.1:8002
   List [1] instances = 127.0.0.1:8001

8001 + 8002 are combined into clusters. They have two machines in total, and the total number of clusters is 2. According to the principle of polling algorithm:

When the total number of requests is 1: 1% 2 = 1 and the corresponding subscript position is 1, the service address obtained is 127.0.0.1:8001
When the total request digit is 2: 2% 2 = 0 and the corresponding subscript position is 0, the service address is 127.0.0.1:8002
When the total request digit is 3: 3% 2 = 1 and the corresponding subscript position is 1, the service address is 127.0.0.1:8001
When the total request digit is 4: 4% 2 = 0 and the corresponding subscript position is 0, the service address is 127.0.0.1:8002
And so on

Source code interpretation

It involves the knowledge of JUC. I can't understand it at present. I'll talk about it later.

Zhou Yang said that JUC is very good. I'll brush it all sometime

Try to write a local load balancer yourself

At present, I have no way to master my ability

import org.springframework.cloud.client.ServiceInstance;

import java.util.List;

public interface LoadBalancer {
    ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class MyLoadBalancer implements LoadBalancer{

    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public final int getAndIncrement() {
        int current;
        int next;
        do {
            current = this.atomicInteger.get();
            next = current >= Integer.MAX_VALUE ? 0 : current + 1;
        } while (!this.atomicInteger.compareAndSet(current,next));
        System.out.println("*****next: "+next);
        return next;
    }

    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}

OpenFeign learning

What is it?

Official website explanation:
https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/#spring-cloud-openfeign

Feign is a declarative Web Service client. Using feign makes it easier to write a Web Service client.
It is used by defining a service interface and then adding annotations on it. Feign also supports pluggable encoders and decoders. Spring Cloud encapsulates feign to support Spring MVC standard annotations and HttpMessageConverters. Feign can be used in combination with Eureka and Ribbon to support load balancing

What can I do

What can Feign do
Feign aims to make it easier to write Java Http clients.
When Ribbon+RestTemplate is used earlier, a set of template calling methods is formed by encapsulating http requests with RestTemplate. However, in the actual development, because there may be more than one invocation of service dependencies, and often an interface will be invoked in multiple places, some client classes are usually encapsulated for each micro service to wrap the invocation of these dependent services. Therefore, Feign made further encapsulation on this basis to help us define and implement the definition of dependent service interfaces. Under the implementation of Feign, we only need to create an interface and configure it in the way of annotation (previously, the Dao interface was marked with Mapper annotation, but now it is a micro service interface marked with Feign annotation), so as to complete the interface binding to the service provider, which simplifies the development of automatically encapsulating the service call client when using the Spring cloud Ribbon.

Feign integrates Ribbon
The Ribbon is used to maintain the service list information of Payment, and the load balancing of the client is realized through polling. Unlike Ribbon, feign only needs to define the service binding interface and implements the service invocation gracefully and simply in a declarative way

Differences between Feign and OpenFeign

Practical use

  1. Create project

  2. Change pom

    • <dependencies>
          <!--openfeign-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-openfeign</artifactId>
          </dependency>
          <!--eureka client-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
          </dependency>
          <!-- Introduce self defined api General package, you can use Payment payment Entity -->
          <dependency>
              <groupId>com.lin</groupId>
              <artifactId>cloud-api-common</artifactId>
              <version>${project.version}</version>
          </dependency>
          <!--web-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
          <!--General basic general configuration-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
      </dependencies>
      
  3. Write yml

    • server:
        port: 80
      
      eureka:
        client:
          register-with-eureka: false
          service-url:
            defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
      
  4. Main start

    • import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.openfeign.EnableFeignClients;
      
      @EnableFeignClients
      @SpringBootApplication
      public class OrderFeignMain80 {
          public static void main(String[] args) {
              SpringApplication.run(OrderFeignMain80.class,args);
          }
      }
      
    • @EnableFeignClients: don't forget this

  5. Business class

    • Interface requiring remote call

      • import com.lin.entities.CommonResult;
        import com.lin.entities.Payment;
        import org.springframework.cloud.openfeign.FeignClient;
        import org.springframework.stereotype.Component;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.PathVariable;
        
        @Component
        @FeignClient("CLOUD-PAYMENT-SERVICE")
        public interface  PaymentFeignService {
            @GetMapping(value = "/payment/get/{id}")
            CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
        }
        
    • The project's own control layer

      • @RestController
        public class OrderFeignController {
            @Resource
            private PaymentFeignService paymentFeignService;
        
            @GetMapping(value = "/consumer/payment/get/{id}")
            public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
                return paymentFeignService.getPaymentById(id);
            }
        }
        
      • This call is really high, tens of thousands of times stronger than me

  6. test

    • No problem. Then it must be equipped with Ribbon. If you don't, it's the default rule.

It is nice to implement load balancing in the class and call other services

  • I'm curious, why did you learn it once before, and then feel like you didn't learn it? Now after reliving it again, I still feel that I learned lonely at the beginning and didn't outline the previous knowledge at all.

OpenFeign timeout control

  • OpenFeign will wait for 1 second by default, and an error will be reported after it is exceeded

Deliberate timeout demonstration

  1. package com.atguigu.springcloud.controller;
    
    import com.atguigu.springcloud.entities.CommonResult;
    import com.atguigu.springcloud.entities.Payment;
    import com.atguigu.springcloud.service.PaymentService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.web.bind.annotation.*;
    
    import javax.annotation.Resource;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @auther zzyy
     * @create 2020-01-27 21:17
     */
    @RestController
    @Slf4j
    public class PaymentController
    {
        @Value("${server.port}")
        private String serverPort;
    
        @Resource
        private PaymentService paymentService;
    
        @Resource
        private DiscoveryClient discoveryClient;
    
        @PostMapping(value = "/payment/create")
        public CommonResult create(@RequestBody Payment payment)
        {
            int result = paymentService.create(payment);
            log.info("*****Insert operation returns results:" + result);
    
            if(result > 0)
            {
                return new CommonResult(200,"Insert successful,Return results"+result+"\t Service port:"+serverPort,payment);
            }else{
                return new CommonResult(444,"Insert failed",null);
            }
        }
    
        @GetMapping(value = "/payment/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
        {
            Payment payment = paymentService.getPaymentById(id);
            log.info("*****Query results:{}",payment);
            if (payment != null) {
                return new CommonResult(200,"query was successful"+"\t Service port:"+serverPort,payment);
            }else{
                return new CommonResult(444,"No corresponding record,query ID: "+id,null);
            }
        }
    
        @GetMapping(value = "/payment/discovery")
        public Object discovery()
        {
            List<String> services = discoveryClient.getServices();
            for (String element : services) {
                System.out.println(element);
            }
    
            List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
            for (ServiceInstance element : instances) {
                System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t"
                        + element.getUri());
            }
            return this.discoveryClient;
        }
    
        @GetMapping(value = "/payment/lb")
        public String getPaymentLB()
        {
            System.out.println("*****lb from port: "+serverPort);
            return serverPort;
        }
    
        @GetMapping(value = "/payment/feign/timeout")
        public String paymentFeignTimeOut()
        {
            System.out.println("*****paymentFeignTimeOut from port: "+serverPort);
            //Pause the thread for a few seconds
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            return serverPort;
        }
    
    }
    
  2.  
    package com.atguigu.springcloud.service;
    
    import com.atguigu.springcloud.entities.CommonResult;
    import com.atguigu.springcloud.entities.Payment;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    /**
     * @auther zzyy
     * @create 2020-02-03 12:00
     */
    @Component
    @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
    public interface PaymentFeignService
    {
        @GetMapping(value = "/payment/get/{id}")
        CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
    
        @GetMapping(value = "/payment/feign/timeout")
        String paymentFeignTimeOut();
    }
    
  3.  
    package com.atguigu.springcloud.controller;
    
    import com.atguigu.springcloud.entities.CommonResult;
    import com.atguigu.springcloud.entities.Payment;
    import com.atguigu.springcloud.service.PaymentFeignService;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    
    /**
     * @auther zzyy
     * @create 2020-02-03 14:10
     */
    @RestController
    public class OrderFeignController
    {
        @Resource
        private PaymentFeignService paymentFeignService;
    
        @GetMapping(value = "/consumer/payment/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
        {
            return paymentFeignService.getPaymentById(id);
        }
    
        @GetMapping(value = "/consumer/payment/feign/timeout")
        public String paymentFeignTimeOut()
        {
            return paymentFeignService.paymentFeignTimeOut();
        }
    }
    

Configure openfeign timeout

By default, the Feign client only waits for one second, but the server processing takes more than one second, so the Feign client doesn't want to wait and directly returns an error.
To avoid this situation, sometimes we need to set the timeout control of Feign client.

Open configuration in yml file

Play, configuration

The client configuration is introduced in feign

#Set feign client timeout (OpenFeign supports ribbon by default)
ribbon:
  #It refers to the time taken to establish a connection, which is applicable to the time taken to connect both ends under normal network conditions
  ReadTimeout: 5000
  #It refers to the time taken to read available resources from the server after the connection is established
  ConnectTimeout: 5000

Log printing function

What is it?

Feign provides log printing function. We can adjust the log level through configuration to understand the details of Http requests in feign.
To put it bluntly, it is to monitor and output the call of Feign interface

None: default, no logs are displayed; none

Basic: only record the request method, URL, response status code and execution time; basic

Headers: in addition to the information defined in BASIC, there are also header information of request and response; headers

Full: in addition to the information defined in HEADERS, there are also the body and metadata of the request and response. full

to configure
@Configuration
public class FeignConfig
{
    @Bean
    Logger.Level feignLoggerLevel()
    {
        return Logger.Level.FULL;
    }
}
  1. logging:
      level:
        com.lin.service.PaymentFeignService: debug
    
  2. 2022-01-19 21:53:57.623 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] <--- HTTP/1.1 200 (3041ms)
    2022-01-19 21:53:57.623 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] connection: keep-alive
    2022-01-19 21:53:57.623 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] content-length: 4
    2022-01-19 21:53:57.623 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] content-type: text/plain;charset=UTF-8
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] date: Wed, 19 Jan 2022 13:53:57 GMT
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] keep-alive: timeout=60
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] 
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] 8001
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] <--- END HTTP (4-byte body)
    
    • Log information.

#It refers to the time taken to read available resources from the server after the connection is established

ConnectTimeout: 5000


Log printing function

What is it?

Feign provides log printing function. We can adjust the log level through configuration to understand the details of Http requests in feign.
To put it bluntly, it is to monitor and output the call of Feign interface

None: default, no logs are displayed; none

Basic: only record the request method, URL, response status code and execution time; basic

Headers: in addition to the information defined in BASIC, there are also header information of request and response; headers

In addition to the metadata in the body of the request and the response, there are also metadata in the body of the request and the response. full

to configure
@Configuration
public class FeignConfig
{
    @Bean
    Logger.Level feignLoggerLevel()
    {
        return Logger.Level.FULL;
    }
}
  1. logging:
      level:
        com.lin.service.PaymentFeignService: debug
    
  2. 2022-01-19 21:53:57.623 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] <--- HTTP/1.1 200 (3041ms)
    2022-01-19 21:53:57.623 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] connection: keep-alive
    2022-01-19 21:53:57.623 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] content-length: 4
    2022-01-19 21:53:57.623 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] content-type: text/plain;charset=UTF-8
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] date: Wed, 19 Jan 2022 13:53:57 GMT
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] keep-alive: timeout=60
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] 
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] 8001
    2022-01-19 21:53:57.624 DEBUG 39224 --- [p-nio-80-exec-8] com.lin.service.PaymentFeignService      : [PaymentFeignService#paymentFeignTimeOut] <--- END HTTP (4-byte body)
    
    • Log information.

Keywords: Java Spring Boot Microservices

Added by Brit on Sat, 05 Mar 2022 07:35:07 +0200