Dios loco springcloud aprendizaje

aprendizaje de nubes de primavera

Clasificación de notas fuente B estación UP maestro dios loco dijo https://www.bilibili.com/video/BV1jJ411S7xr
Referencia: rookie Xiaojiezi https://blog.csdn.net/lijie0213/article/details/107914619
Referencia: Luffy https:/ /csp1999.blog.csdn.net/article/details/106255122?spm=1001.2014.3001.5502

1. Información general

1.1 Requisitos previos
  • Uso experto del marco de desarrollo springboot.
  • Comprender la base distribuida de Dubbo + Zookeeper
  • La memoria de configuración de la computadora no es inferior a 8G (la mía es 16G)
1.2 Propósito de aprendizaje
  • Competencia en el uso de springcloud para construir un marco de microservicio
  • Más información sobre los microservicios (preguntas de la entrevista)

2. Construcción del proyecto Springcloud

2.1 Introducción general
  • Usaremos un módulo de departamento Dept para hacer un caso general de microservicios.El consumidor (Cliente) llama al servicio provisto por el Proveedor proveedor (Servidor) a través de REST.
  • Recordar los conocimientos previos de Spring, SpringMVC, Mybatis, etc.
  • Revisión de la arquitectura del módulo de subpaquetes de Maven

En pocas palabras, un proyecto principal contiene múltiples subproyectos

Un proyecto principal con múltiples submódulos de Moudule

Proyecto principal de MicroServiceCloud (Proyecto) con 3 submódulos (Módulo) por primera vez

microservicecloud-api [entidad global encapsulada/interfaz/configuración pública, etc.]
microservicecloud-consumer-dept-80 [proveedor de servicios]
microservicecloud-provider-dept-8001 [consumidor de servicios]

2.2, selección de versión de springcloud

Descripción de la versión principal

SpringBoot PrimaveraNube relación
1.2.x Versión Ángel (Ángel) Compatible con SpringBoot1.2x
1.3.x Edición Brixton (Brixton) Compatible con SpringBoot1.3x, también compatible con SpringBoot1.4x
1.4.x Versión Camden (Camden) Compatible con SpringBoot1.4x, también compatible con SpringBoot1.5x
1.5.x Versión de Dalston (Dalston) Compatible con SpringBoot1.5x, no compatible con SpringBoot2.0x
1.5.x Edición Edgware (Edgware) Compatible con SpringBoot1.5x, no compatible con SpringBoot2.0x
2.0.x Versión Finchley (Finchley) Compatible con SpringBoot2.0x, no compatible con SpringBoot1.5x
2.1.x Versión de Greenwich (Greenwich)

Relación de versión de desarrollo real

spring-boot-arrancador-padre primavera-nube-dependencias
número de versión fecha de lanzamiento número de versión fecha de lanzamiento
1.5.2.LIBERACIÓN 2017-03 Dalston.RC1 2017-x
1.5.9.LIBERAR 2017-11 Edgware.RELEASE 2017-11
1.5.16.LIBERAR 2018-04 Edgware.SR5 2018-10
1.5.20.LIBERAR 2018-09 Edgware.SR5 2018-10
2.0.2.LIBERAR 2018-05 Fomchiey.BULD-INSTANTÁNEA 2018-x
2.0.6.LIBERAR 2018-10 Fomchiey-SR2 2018-10
2.1.4.LIBERACIÓN 2019-04 Greenwich.SR1 2019-03

Se recomienda utilizar las dos últimas versiones de desarrollo.

2.3 Crear proyectos relacionados

inserte la descripción de la imagen aquí

1. Crear un nuevo proyecto principal

Cree un nuevo proyecto maven como se muestra a continuación

inserte la descripción de la imagen aquí

  • Creado de la siguiente manera:

inserte la descripción de la imagen aquí

Elimine el archivo src y mantenga solo un archivo pom (el proyecto principal no necesita escribir contenido lógico)

  • contenido del archivo 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">
    <modelVersion>4.0.0</modelVersion>
<!-- 打包方式 pom-->
    <packaging>pom</packaging>

    <groupId>org.example</groupId>
    <artifactId>springCloudStudy</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>springCloud-api</module>
        <module>springCloud-provider-dept-8001</module>
        <module>springCloud-consumer-dept-80</module>
    </modules>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <lombok.version>1.18.16</lombok.version>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>

    </properties>
<!--    添加详细依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>0.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
<!--            引入springcloud依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
<!--            引入springboot-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
<!--            数据源-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.10</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
<!--            mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
<!--            日志相关-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
<!--            lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

Uso de tipo y alcance en herencia múltiple en maven (revisión):

configuración del archivo pom

¿Por qué la dependencia tiene un tipo de pom y cuál es el valor predeterminado?

El tipo de dependencia predeterminado es jar, es decir, se introduce un paquete jar específico. Entonces, ¿por qué todavía hay un tipo de pom? Cuando necesitamos introducir muchos paquetes jar, el pom.xml será demasiado grande. Una solución que podemos pensar es definir un proyecto principal, pero solo hay un proyecto principal, que también puede causar que el archivo pom.xml del proyecto principal sea demasiado grande. En este momento, introdujimos un tipo de pom, lo que significa que podemos empaquetar todos los paquetes jar en un pom, y luego dependemos de pom, es decir, podemos descargar todos los paquetes jar dependientes.

alcance alcance

  • compilar: el alcance predeterminado, que indica que las dependencias en este alcance son válidas en compilación, operación y prueba
  • proporcionado: las pruebas y la compilación son válidas
  • tiempo de ejecución: ejecutar y probar válido
  • prueba: válido para la prueba
  • system: Indica que la dependencia la proporcionamos nosotros, y maven no necesita buscarla en el almacén. Cuando se usa, debe usarse systemPathjunto con otra etiqueta. Esta etiqueta indica la ubicación de la dependencia en el sistema, usando una ruta absoluta

ejemplo:

<dependency>
  <groupId>sun.jdk</groupId>
  <artifactId>tools</artifactId>
  <version>1.5.0</version>
  <scope>system</scope>
  <systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
  • import se utiliza cuando la herencia múltiple

Al heredar las dependencias de un proyecto, puede declarar en el subproyecto que necesita usar las dependencias definidas en la gestión de dependencias del proyecto principal. Pero cada proyecto solo puede declarar un proyecto padre único, lo que limitará el establecimiento de nuestro proyecto en algún momento.

Para ello, Maven nos proporciona un método, es decir, establecer el socpe de la dependencia como import. Tenga en cuenta que este método solo tiene efecto en versiones anteriores a Maven2.0.9.

Solo se puede usar en la gestión de dependencias.

Dependencias del proyecto padre:

<project>  
       ...  
       <groupId>groupA</groupId>  
       <artifactId>artifactA</artifactId>  
       <version>1.0</version>  
       <packaging>pom</packaging>  
       <dependencyManagement>  
              <dependencies>  
                     <dependency>  
                            <groupId>test</groupId>  
                            <artifactId>A</artifactId>  
                            <version>1.0</version>  
                     </dependency>  
                     <dependency>  
                            <groupId>test</groupId>  
                            <artifactId>B</artifactId>  
                            <version>1.1</version>  
                     </dependency>  
                   
              </dependencies>  
       </dependencyManagement>  
       ...  
</project> 

Si se utiliza el mecanismo de herencia anterior, el archivo pom.xml del subproyecto artefactoB se define de la siguiente manera:

<project>  
       ...  
       <parent>  
              <groupId>groupA</groupId>  
              <artifactId>artifactA</artifactId>  
              <version>1.0</version>  
       </parent>  
    
       <groupId>groupA</groupId>  
       <artifactId>artifactB</artifactId>  
       <version>1.0</version>  
       <packaging>pom</packaging> 
    
       <dependencies>  
              <dependency>  
                     <groupId>test</groupId>  
                     <artifactId>A</artifactId>  
              </dependency>  
              <dependency>  
                     <groupId>test</groupId>  
                     <artifactId>D</artifactId>  
                     <scope>runtime</scope>  
              </dependency>  
       </dependencies>  
       ...  
</project>  

método de importación

<project>  
       ...  
       <groupId>groupA</groupId>  
       <artifactId>artifactB</artifactId>  
       <version>1.0</version>  
       <packaging>pom</packaging>  
    
       <dependencyManagement>  
              <dependencies>  
                     <dependency>  
                            <groupId>groupA</groupId>  
                            <artifactId>artifactA</artifactId>  
                            <version>1.0</version>  
                            <type>pom</type>  
                            <scope>import</scope>  
                     </dependency>  
              </dependencies>  
       </dependencyManagement>  
    
       <dependencies>  
              <dependency>  
                     <groupId>test</groupId>  
                     <artifactId>A</artifactId>  
              </dependency>  
              <dependency>  
                     <groupId>test</groupId>  
                     <artifactId>D</artifactId>  
                     <scope>runtime</scope>  
              </dependency>  
       </dependencies>  
       ...  
   
</project>  
2. Crear entidad springcloud-api
  • Encapsular las entidades involucradas en el servicio, configuración pública, etc.

inserte la descripción de la imagen aquí

  • Cree la clase de entidad de departamento de departamento:
package com.lzh.springcloud.dept;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * 部门信息
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 16:44:34
 */
@Data
@Accessors
@NoArgsConstructor
public class Dept {
    
    

    /**主键*/
    private long deptno;

    /**部门名称*/
    private String dname;

    /**存储数据库名称*/
    private String db_source;


}

  • El guión se ve así:
DROP TABLE IF EXISTS `dept_test`;
CREATE TABLE `dept_test`  (
  `deptno` bigint(20) NOT NULL COMMENT '主键',
  `dname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门名称',
  `db_source` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '存储数据库名称',
  PRIMARY KEY (`deptno`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '部门数据' ROW_FORMAT = Compact;

-- ----------------------------
-- Records of dept_test
-- ----------------------------
INSERT INTO `dept_test` VALUES (1, '开发部', 'mysql');
INSERT INTO `dept_test` VALUES (2, '研发部', 'mysql');
INSERT INTO `dept_test` VALUES (3, '事业部', 'mysql');

SET FOREIGN_KEY_CHECKS = 1;
3. Crear un proveedor de servicios

inserte la descripción de la imagen aquí

  • El archivo pom se ve así:
<?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>springCloudStudy</artifactId>-->
<!--        <groupId>org.example</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springCloud-provider-dept-8001</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>springCloudStudy</artifactId>
                <version>1.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!--            引入实体-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springCloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>
  • Archivo de configuración aplicación.yml
server:
  port: 8001
mybatis:
#  配置检索的实体的包的前缀
  type-aliases-package: com.lzh.springcloud.dept
  mapper-locations: classpath:mybatis/mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
  application:
#    微服务的唯一标识
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowMultiQueries=true
    username: root
    password: root

  • Escribir código comercial, crud de tabla única

  • Controlador de departamento:

package com.lzh.springcloud.dept.controller;

import com.lzh.springcloud.dept.Dept;
import com.lzh.springcloud.dept.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 16:51:49
 */
@RestController
@RequestMapping("/dept")
public class DeptController {
    
    

    @Autowired
    private DeptService deptService;

    @PostMapping("/add")
    public boolean addDept(Dept dept) {
    
    
        return deptService.addDept(dept);
    }

    @RequestMapping("/get/{id}")
    public Dept queryById(@PathVariable("id") Long id) {
    
    
        return deptService.queryById(id);
    }

    @RequestMapping("/list")
    public List<Dept> queryAll() {
    
    
        return deptService.queryAll();
    }
}

  • Servicio de departamento:
package com.lzh.springcloud.dept.service;

import com.lzh.springcloud.dept.Dept;

import java.util.List;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 16:52:38
 */
public interface DeptService {
    
    


    /**
     * 添加部门
     *
     * @param dept
     * @return
     * @author LZH
     * @date 2023/4/7 17:34:21
     * @version 1.0
     */
    boolean addDept(Dept dept);
    /**
     * 根据id查出一个部门
     *
     * @param id
     * @return
     * @author LZH
     * @date 2023/4/7 17:34:21
     * @version 1.0
     */
    Dept queryById(Long id);
    /**
     * 查询所有部门信息
     *
     * @return
     * @author LZH
     * @date 2023/4/7 17:34:21
     * @version 1.0
     */
    List<Dept> queryAll();
}

  • DeptServiceImpl
package com.lzh.springcloud.dept.service.Impl;

import com.lzh.springcloud.dept.Dept;
import com.lzh.springcloud.dept.dao.DeptDao;
import com.lzh.springcloud.dept.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 16:53:09
 */
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {

    @Autowired
    private DeptDao deptDao;
    @Override
    public boolean addDept(Dept dept) {
        return deptDao.addDept(dept);
    }
    @Override
    public Dept queryById(Long id) {
        return deptDao.queryById(id);
    }
    @Override
    public List<Dept> queryAll() {
        return deptDao.queryAll();
    }

}

  • Departamento Dao:
package com.lzh.springcloud.dept.dao;

import com.lzh.springcloud.dept.Dept;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 16:58:08
 */
@Mapper
public interface DeptDao {
    
    

    /**
     * 添加部门
     *  
     * @param dept 
     * @return
     * @author LZH
     * @date 2023/4/7 17:34:21
     * @version 1.0
     */
    boolean addDept(Dept dept);
    /**
     * 根据id查出一个部门
     *
     * @param id
     * @return
     * @author LZH
     * @date 2023/4/7 17:34:21
     * @version 1.0
     */
    Dept queryById(Long id);
    /**
     * 查询所有部门信息
     *
     * @return
     * @author LZH
     * @date 2023/4/7 17:34:21
     * @version 1.0
     */
    List<Dept> queryAll();
}

  • DeptMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--核心配置文件-->
<mapper namespace="com.lzh.springcloud.dept.dao.DeptDao">
    <!--增加一个部门-->
    <insert id="addDept" parameterType="com.lzh.springcloud.dept.Dept">
        insert into dept_test (dname,db_source) values (#{dname},DATABASE())
    </insert>
    <!--根据id查询部门信息-->
    <select id="queryById" resultType="com.lzh.springcloud.dept.Dept">
        select * from dept_test where deptno = #{depono};
    </select>
    <!--查询所有的部门信息-->
    <select id="queryAll" resultType="com.lzh.springcloud.dept.Dept">
        select * from dept_test;
    </select>
</mapper>
  • Clase de inicio:
package com.lzh.springcloud;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 启动类
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 17:44:41
 */
@Slf4j
@SpringBootApplication
public class springcloud_8001 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(springcloud_8001.class);
        log.info("启动成功!!");
    }
}
  • Prueba después del inicio:

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

4. Escribe al consumidor:

inserte la descripción de la imagen aquí

  • dependencias 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>springCloudStudy</artifactId>-->
<!--        <groupId>org.example</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springCloud-provider-dept-80</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>springCloudStudy</artifactId>
                <version>1.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--            引入实体-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springCloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>
  • Archivo de configuración:
server:
  port: 80
mybatis:
  #  配置检索的实体的包的前缀
  type-aliases-package: com.lzh.springcloud.dept
  mapper-locations: classpath:mybatis/mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
  application:
    #    微服务的唯一标识
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowMultiQueries=true
    username: root
    password: root
  • Controlador de consumidor de departamento:
package com.lzh.springcloud.deptController;

import com.lzh.springcloud.dept.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * 消费者
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 18:06:35
 */
@RestController
public class DeptConsumerController {
    
    
    @Autowired
    private RestTemplate restTemplate;

    // 理解:消费者,不该有service层
    // RestTemplate.. 里面有方法供我们调用即可,注册到spring中
    //(String url,实体, Class<T> responseType)

    //提供多种便捷访问远程http服务的方法,简单的Restful服务模板

    //声明提供者的localhost路径
    private static final String rest_url_prefix = "http://localhost:8001";

    //调用8001提供者的控制器=>根据id查询数据
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
    
    
        // restTemplate.注意和提供者的getmapping或postmapping保持一致
        return restTemplate.getForObject(rest_url_prefix+"/dept/get/"+id,Dept.class);
    }
    //调用8001提供者的控制器=>添加方法
    @RequestMapping("/consumer/dept/add")
    public Boolean add(Dept dept){
    
    
        // restTemplate.注意和提供者的getmapping或postmapping保持一致
        return restTemplate.postForObject(rest_url_prefix+"/dept/add",dept,Boolean.class);
    }

    //调用8001提供者的控制器=>查询所有
    @RequestMapping("/consumer/dept/list")
    public List<Dept> queryall(){
    
    
        // restTemplate.注意和提供者的getmapping或postmapping保持一致
        return restTemplate.getForObject(rest_url_prefix+"/dept/list",List.class);
    }
}
  • Configuración:
package com.lzh.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 18:08:30
 */
@Configuration
public class Config {
    
    
    @Bean
    public RestTemplate getRestTemplate(){
    
    
        return new RestTemplate();
    }
}
  • Clase de inicio:
package com.lzh.springcloud;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 18:14:38
 */
@Slf4j
@SpringBootApplication
public class Springcloud_80 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Springcloud_80.class);
        log.info("启动成功!!");
    }
}
  • Inicie el servicio 8001 y el servicio 80, use el servicio 80 para llamar al servicio 8001

inserte la descripción de la imagen aquí

3. Centro de registro de servicios de Eureka

3.1 ¿Qué es Eureka?

Netflix sigue el principio API cuando se trata de Eureka.Eureka
es un submódulo de Netflix y uno de los módulos principales. Eureka es un servicio basado en REST que se utiliza para ubicar servicios para realizar el descubrimiento de servicios y la conmutación por error en la capa de middleware de la nube. El registro y descubrimiento de servicios son muy importantes para los microservicios. Con el registro y descubrimiento de servicios, solo necesita usar el identificador de servicio, puede acceder al servicio sin modificar el archivo de configuración llamado por el servicio La función es similar al centro de registro de Dubbo, como Zookeeper.

3.2 Comprensión del principio

Arquitectura básica de Eureka

Springcloud encapsula el módulo Eureka desarrollado por Netflix para realizar el registro y descubrimiento de servicios (en comparación con Zookeeper).

Eureka adopta el diseño de arquitectura de CS EurekaServer es el servidor de la función de registro de servicios y es el centro de registro de servicios.

Otros microservicios en el sistema usan el cliente de Eureka para conectarse a EurekaServer y mantener una conexión de latido. De esta forma, los mantenedores del sistema pueden usar EurekaServer para monitorear si cada microservicio en el sistema se ejecuta normalmente, y algunos otros módulos de Springcloud (como Zuul) pueden usar EurekaServer para descubrir otros microservicios en el sistema y ejecutar la lógica relacionada.

inserte la descripción de la imagen aquí

En comparación con la arquitectura Dubbo.

inserte la descripción de la imagen aquí

Eureka consta de dos componentes: Eureka Server y Eureka Client.

Eureka Server proporciona registro de servicio. Después de iniciar cada nodo, se registrará en EurekaServer, de modo que el registro de servicio en Eureka Server almacenará la información de todos los nodos de servicio de clase, y la información de los nodos de servicio se puede ver intuitivamente en la interfaz. . .

Eureka Client es un cliente Java que simplifica la interacción con EurekaServer. El cliente también tiene un equilibrador de carga incorporado que utiliza un algoritmo de carga de turno rotativo. Después de que se inicie la aplicación, se enviará un latido a EurekaServer (el período predeterminado es de 30 segundos). Si Eureka Server no recibe el latido de un nodo dentro de varios ciclos de latidos, EurekaServer eliminará el nodo de servicio del registro de servicio (el ciclo predeterminado es de 90 s).

tres roles

Servidor Eureka: proporciona registro y detección de servicios
. Proveedor de servicios: productor de servicios, registra su propio servicio en Eureka
, para que el consumidor del servicio pueda encontrar.

3.3, configurar el centro de registro del servicio Eureka

1. Introduzca la dependencia de Eureka en el archivo pom

2. Configure la configuración relacionada con Eureka en el archivo de configuración

3. Agregue anotaciones Eureka a la clase de inicio

inserte la descripción de la imagen aquí

1. Clase de inicio:
package com.lzh.springcloud;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/10 11:42:21
 */
@SpringBootApplication
//表示为Eureka的启动类,接受别人注册进来
@EnableEurekaServer
@Slf4j
public class Springcloud_7001 {
    
    
    public static void main(String[] args) {
    
    
        ConfigurableApplicationContext run = SpringApplication.run(Springcloud_7001.class);
        log.info("启动成功!!");
    }
}
2. Archivo de configuración:
server:
  port: 7001
# Eureka配置
eureka:
  instance:
#    eureka实例名称
    hostname: 127.0.0.1
  client:
    # 表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)
    register-with-eureka: false
    # fetch-registry如果为false,则表示自己为注册中心,客户端的化为 ture
    fetch-registry: false
    # Eureka监控页面~
    service-url:
      defaultZone: http://${
    
    eureka.instance.hostname}:${
    
    server.port}/eureka/
3. archivo 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>springCloudStudy</artifactId>-->
<!--        <groupId>org.example</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springCloud-eureka-7001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
<!--    引入父依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>springCloudStudy</artifactId>
                <version>1.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
<!--    引入eureka依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>
4. El acceso es el siguiente:

inserte la descripción de la imagen aquí

Consumo del servicio Eureka, registro, configuración de la información, mecanismo de autoprotección

5. Agregue la dependencia de Eureka en springCloud-provider-dept-8001

1. archivo pom:

<!--        添加Eureka依赖-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

Agregar anotaciones Eureka a la clase de inicio

package com.lzh.springcloud;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * 启动类
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 17:44:41
 */
@Slf4j
@SpringBootApplication
//再服务启动后自动注册到Eureka注册中心去
@EnableEurekaClient
public class springcloud_8001 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(springcloud_8001.class);
        log.info("启动成功!!");
    }
}

Agregue la configuración de Eureka a la clase de configuración

eureka:
  client:
    service-url:
#      访问7001
      defaultZone: http://localhost:7001/eureka/
  instance:
      #修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
    instance-id: springcloud-provider-dept8001

Inicie el servicio 8001 y el servicio 7001 de la siguiente manera:

La descripción en el estado es el contenido de la ID de instancia bajo la instancia bajo el Eureka configurado en la clase de configuración

inserte la descripción de la imagen aquí

Detenga el servicio 8001 y después de esperar 30 segundos, se activará el mecanismo de protección:

inserte la descripción de la imagen aquí

Configure la información de monitoreo cargada por el servicio:

inserte la descripción de la imagen aquí

Si no lo configuras es 404

Añadir al archivo pom:

<!--        添加status跳转出页面的详情-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

Añadir al archivo de configuración:

info:
  app.name: com.lzh.springclod
  company.name: 苏州xx公司

Haga clic en el salto de ruta debajo del estado

inserte la descripción de la imagen aquí

Como sigue:

inserte la descripción de la imagen aquí

3.4 El mecanismo de autoprotección de EureKa: es mejor vivir que morir

El resumen de una oración es: cierto microservicio no está disponible en un momento determinado, eureka no lo limpiará de inmediato y aún guardará la información del microservicio.

De manera predeterminada, cuando el servidor eureka no recibe el latido de la instancia dentro de un cierto período de tiempo, eliminará la instancia del registro (el valor predeterminado es 90 segundos), pero si se pierde una gran cantidad de latidos de la instancia en un Por un corto período de tiempo, activará el mecanismo de autoprotección del servidor eureka, por ejemplo, durante el desarrollo y las pruebas, las instancias de microservicio deben reiniciarse con frecuencia, pero rara vez reiniciamos el servidor eureka juntos (porque el centro de registro de eureka no se modificará durante el proceso de desarrollo), cuando se cierra en un minuto. Este mecanismo de protección se activará cuando la cantidad de latidos recibidos disminuya significativamente. Puede ver el umbral de Renovaciones y Renovaciones (último minuto) en la interfaz de administración de eureka. Cuando el último (número de latidos recibidos en el último minuto) es menor que el primero (umbral de latidos), el mecanismo de protección se activará y aparecerá una advertencia roja. aparecerá: ¡EMERGENCIA! EUREKA PUEDE AFIRMAR INCORRECTAMENTE QUE LAS INSTANCIAS ESTÁN ACTIVAS CUANDO NO LO ESTÁN. LAS RENOVACIONES SON INFERIORES AL UMBRAL Y POR LO TANTO LAS INSTANCIAS NO ESTÁN COMENZANDO A EXPIRAR SOLO PARA ESTAR SEGUROS. Como se puede ver en la advertencia, Eureka cree que aunque el No se puede recibir el latido de la instancia, pero cree que la instancia aún está en buen estado, y eureka protegerá estas instancias y no las eliminará del registro.

El propósito de este mecanismo de protección es evitar fallas en la conexión de la red. Cuando ocurre una falla en la red, el microservicio y el centro de registro no pueden comunicarse normalmente, pero el servicio en sí está en buen estado y no debe cancelarse. Si eureka falla, el microservicio debe a falla de la red Eliminado por error, incluso si la red se restaura, el microservicio no se volverá a registrar en el servidor eureka, porque la solicitud de registro solo se iniciará cuando se inicie el microservicio, y solo se realizarán las solicitudes de latido y lista de servicios. enviado más tarde En este caso, aunque la instancia se está ejecutando, nunca será conocida por otros servicios. Por lo tanto, cuando el servidor eureka pierde demasiados latidos del corazón del cliente en un corto período de tiempo, entrará en el modo de autoprotección.En este modo, eureka protegerá la información en el registro y no cerrará la sesión de ningún microservicio.Cuando la red falla se recupera, eureka saldrá automáticamente del modo protegido. El modo de autoconservación puede hacer que el clúster sea más sólido.

Sin embargo, durante la fase de desarrollo y prueba, necesitamos reiniciar la versión con frecuencia. Si se activa el mecanismo de protección, la instancia de servicio anterior no se elimina. En este momento, la solicitud puede ir a la instancia anterior y la instancia se ha eliminado. cerrado, lo que conduce a La solicitud es incorrecta, lo que afecta el desarrollo y las pruebas. Por lo tanto, en la fase de desarrollo y prueba, podemos desactivar el modo de autoconservación, simplemente agregue la siguiente configuración al archivo de configuración del servidor eureka: eureka.server.enable-self-preservation=false【No se recomienda desactivar el mecanismo de autoconservación】

3.5 Obtener información sobre el servicio registrado

Clase de inicio más anotaciones para obtener servicios de cliente

package com.lzh.springcloud;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * 启动类
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 17:44:41
 */
@Slf4j
@SpringBootApplication
//开启Eureka客户端注解,再服务启动后自动注册到Eureka注册中心去
@EnableEurekaClient
//开启服务获取客户端注解,获取一些服务,得到一些信息
@EnableDiscoveryClient
public class springcloud_8001 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(springcloud_8001.class);
        log.info("启动成功!!");
    }
}

Obtenga información relacionada con el servicio desde la interfaz

@Autowired
private DiscoveryClient discoveryClient;

@GetMapping("/get/discoveryInfo")
public Object discoveryInfo(){
    
    
    List<String> services = discoveryClient.getServices();
    List<ServiceInstance> instances = discoveryClient.getInstances("springcloud-provider-dept");
    instances.forEach(l->{
    
    
        System.out.println("主机:"+l.getHost());
        System.out.println("主机:"+l.getUri());
        System.out.println("主机:"+l.getInstanceId());
        System.out.println("主机:"+l.getServiceId());
        System.out.println("主机:"+l.getScheme());
    });
    return services;
}

accede de la siguiente manera

inserte la descripción de la imagen aquí

3.6 Construcción del clúster Eureka, solo échale un vistazo por el momento

Eureka contra el cuidador del zoológico

  1. Revise el principio CAP
    RDBMS (MySQL\Oracle\sqlServer) ===> ACID

NoSQL (Redis\MongoDB) ===> CAP

  1. ¿Qué es ÁCIDO?
    A (Atomicidad) Atomicidad
    C (Consistencia) Consistencia
    I (Aislamiento) Aislamiento
    D (Durabilidad) Persistencia

  2. ¿Qué es CAP?
    C (Consistencia) Consistencia fuerte
    A (Disponibilidad) Disponibilidad
    P (Tolerancia de partición) Tolerancia a fallas de partición
    CAP tres en dos: CA, AP, CP

  3. El núcleo de la teoría CAP
    Es imposible que un sistema distribuido satisfaga los tres requisitos de consistencia, disponibilidad y tolerancia de partición al mismo tiempo.Según
    el principio CAP, las bases de datos NoSQL se dividen en tres categorías que satisfacen el principio CA, satisfacen el principio CP y satisfacer el principio AP
    CA: clúster de un solo punto, sistema que cumple con la consistencia y la disponibilidad, por lo general tiene poca escalabilidad
    CP: sistema que cumple con la consistencia y la tolerancia a la partición, por lo general no tiene un rendimiento particularmente alto
    AP: sistema que cumple con la disponibilidad y la Tolerancia de partición, por lo general puede ser consistente menos exigente

  4. Como registro de servicios distribuidos, ¿cómo es Eureka mejor que Zookeeper?
    La famosa teoría CAP señala que es imposible que un sistema distribuido satisfaga C (consistencia), A (disponibilidad) y P (tolerancia a fallas) al mismo tiempo. Dado que la tolerancia a fallas de partición P debe estar garantizada en un sistema distribuido, Solo se puede hacer una compensación entre A y C.

Lo que Zookeeper garantiza es CP —> un sistema que cumple con la consistencia y la tolerancia de partición, por lo general el rendimiento no es particularmente alto. Eureka
garantiza AP —> un sistema que cumple con la disponibilidad y la tolerancia de partición, por lo general puede tener requisitos más bajos de consistencia.
Zookeeper garantiza CP

Al consultar la lista de servicios desde el centro de registro, podemos tolerar que el centro de registro devuelva la información de registro hace unos minutos, pero no podemos recibir el servicio y cerrarlo directamente y dejar de estar disponible. En otras palabras, la función de registro de servicios tiene mayores requisitos de usabilidad que de consistencia. Sin embargo, habrá tal situación en zookeeper, cuando el nodo maestro pierda el contacto con otros nodos debido a una falla en la red, los nodos restantes volverán a elegir al líder. El problema es que se tarda demasiado en elegir un líder, 30-120, y todo el grupo de cuidadores del zoológico no está disponible durante la elección, lo que lleva a la parálisis del servicio de registro durante la elección. En un entorno de despliegue en la nube, es muy probable que el cluster zookeeper pierda el nodo maestro por problemas de red, aunque el servicio eventualmente se puede restaurar, el largo tiempo de elección hace que el registro no esté disponible por mucho tiempo, lo cual es intolerable.

Eureka garantiza AP

Eureka entiende esto, por lo que prioriza la usabilidad en el diseño. Todos los nodos de Eureka son iguales, y la falla de varios nodos no afectará el trabajo de los nodos normales, y los nodos restantes aún pueden brindar servicios de registro y consulta. Cuando el cliente Eureka se registra con un Eureka, si encuentra que la conexión falla, cambiará automáticamente a otros nodos.Mientras un Eureka todavía esté allí, se puede mantener la disponibilidad del servicio de registro, pero es posible que la información encontrada no ser el último. Sí, además, Eureka también tiene un mecanismo de autoprotección. Si más del 85% de los nodos no tienen un latido normal dentro de los 15 minutos, entonces Eureka piensa que hay una falla en la red entre el cliente y el centro de registro Las siguientes situaciones:

Eureka no está eliminando de la lista de registro que deberían caducar porque no han recibido latidos durante mucho tiempo
servicios el situación en la que algunos nodos pierden contacto debido a una falla en la red y no paralizarán todo el servicio de registro como zookeeper

4. Ribbon: equilibrio de carga (basado en el cliente)

4.1 Equilibrio de carga y cinta

¿Qué es la cinta?

Spring Cloud Ribbon es un conjunto de herramientas de equilibrio de carga de clientes basadas en Netflix Ribbon.
En pocas palabras, Ribbon es un proyecto de código abierto lanzado por Netflix. Su función principal es proporcionar un algoritmo de equilibrio de carga de software del lado del cliente y conectar los servicios de nivel medio de Netflix entre sí. El componente de cliente de Ribbon proporciona una serie de elementos de configuración completos, tales como: tiempo de espera de conexión, reintento, etc. En pocas palabras, es enumerar todos los LoadBalancer (LB: Load Balancer) siguientes en el archivo de configuración, y Ribbon lo ayudará automáticamente a conectar estas máquinas según ciertas reglas (como sondeo simple, conexión aleatoria, etc.). ¡También podemos usar Ribbon fácilmente para implementar un algoritmo de equilibrio de carga personalizado!
¿Qué puede hacer la cinta?

inserte la descripción de la imagen aquí

LB, o Load Balancer, es una aplicación que se usa a menudo en microservicios o clústeres distribuidos.
En pocas palabras, el equilibrio de carga es distribuir las solicitudes de los usuarios de manera uniforme a múltiples servicios, a fin de lograr HA (alta utilización) del sistema.
El software común de equilibrio de carga incluye Nginx, Lvs, etc.
Tanto Dubbo como SpringCloud nos brindan equilibrio de carga, y el algoritmo de equilibrio de carga de SpringCloud se puede personalizar.
Clasificación simple del equilibrio de carga:
LB centralizado
significa usar una instalación de LB independiente entre el proveedor de servicios y el consumidor, como Nginx (servidor proxy inverso), que es responsable de reenviar la solicitud de acceso al proveedor de servicios a través de un cuadrado de estrategia determinado.
El LB basado en procesos
integra la lógica LB en el consumidor. El consumidor aprende qué direcciones están disponibles en el registro del servicio y luego selecciona un servidor adecuado a partir de estas direcciones.
Ribbon pertenece al LB en proceso, es solo una biblioteca de clases, integrada en el proceso del consumidor, ¡y el consumidor obtiene la dirección del proveedor de servicios a través de él!

4.2 Integrar la cinta en el cliente consumidor

Introducir dependencias de cinta y dependencias de Eureka en el archivo pom

<!--        引入Eureka,ribbon可以从Eureka中获取需要拿的服务-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
<!--        引入ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

Agregar anotaciones Eureka a la clase de inicio

//加入Eureka服务
@EnableEurekaClient

Configure las dependencias de Eureka en el archivo de configuración

# 配置 Eureka
eureka:
  client:
    service-url:
#      访问路径
      defaultZone: http://localhost:7001/eureka/
#      不需要向Eureka中注册自己
    register-with-eureka: false

Agregue anotaciones de cinta a la clase de configuración de configuración

package com.lzh.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 18:08:30
 */
@Configuration
public class Config {
    
    

    @LoadBalanced //配置负载均衡实现RestTemplate
    @Bean
    public RestTemplate getRestTemplate(){
    
    
        return new RestTemplate();
    }
}

Modifique la ruta de acceso del proveedor en DeptConsumerController:

private static final String rest_url_prefix = "http://SPRINGCLOUD-PROVIDER-DEPT";

Crear proyectos 8002 y 8003 a su vez, siguiendo 8001, y crear bases de datos correspondientes a 8002 y 8003

inserte la descripción de la imagen aquí

Modifique el método de conexión, modifique la descripción del servicio en el archivo de configuración, cambie el atributo de ID de instancia a springcloud-provider-dept8003 y 8002, y cambie el nombre de la fuente de datos en la tabla dept_test a db02 y db03

Comience el proyecto en secuencia

inserte la descripción de la imagen aquí

Ver registro del servicio Eureka

inserte la descripción de la imagen aquí

Acceda a la interfaz de lista para verificar de qué servicio obtiene datos la cinta

inserte la descripción de la imagen aquí

Actualizar se ve así:

inserte la descripción de la imagen aquí

El uso de la cinta para lograr el equilibrio de carga se ha implementado utilizando

4.3 Algoritmo de equilibrio de carga de cinta personalizado:

En el pasado, la cinta usaba el algoritmo de sondeo y cambiaba al algoritmo para usar un servicio cinco veces y luego usar el siguiente servicio

Algoritmo aleatorio en cinta: archivo RandomRule.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.loadbalancer;

import com.netflix.client.config.IClientConfig;
import edu.umd.cs.findbugs.annotations.SuppressWarnings;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

public class RandomRule extends AbstractLoadBalancerRule {
    
    
    public RandomRule() {
    
    
    }

    @SuppressWarnings({
    
    "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
    public Server choose(ILoadBalancer lb, Object key) {
    
    
        if (lb == null) {
    
    
            return null;
        } else {
    
    
            Server server = null;

            while(server == null) {
    
    
                if (Thread.interrupted()) {
    
    
                    return null;
                }

                List<Server> upList = lb.getReachableServers();
                List<Server> allList = lb.getAllServers();
                int serverCount = allList.size();
                if (serverCount == 0) {
    
    
                    return null;
                }

                int index = this.chooseRandomInt(serverCount);
                server = (Server)upList.get(index);
                if (server == null) {
    
    
                    Thread.yield();
                } else {
    
    
                    if (server.isAlive()) {
    
    
                        return server;
                    }

                    server = null;
                    Thread.yield();
                }
            }

            return server;
        }
    }

    protected int chooseRandomInt(int serverCount) {
    
    
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

    public Server choose(Object key) {
    
    
        return this.choose(this.getLoadBalancer(), key);
    }

    public void initWithNiwsConfig(IClientConfig clientConfig) {
    
    
    }
}

Cree la siguiente carpeta fuera del directorio de inicio

inserte la descripción de la imagen aquí

RuleConfig se ve así:

package com.lzh.myrule;

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

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/12 10:44:11
 */
@Configuration
public class RuleConfig {
    
    

    @Bean
    public IRule myRule(){
    
    
        return new MyRibbonRule();
    }
}

El código de MyRibbonRule es el siguiente:

package com.lzh.myrule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/12 10:47:08
 */
public class MyRibbonRule extends AbstractLoadBalancerRule {
    
    

    int totalCount = 0;
    int currentIndex = 0;
    @SuppressWarnings({
    
    "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
    public Server choose(ILoadBalancer lb, Object key) {
    
    
//        老的版本 RandomRule 采用的是轮询算法,改成新的算法,每个服务依次用5次,然后再调用其他服务
        if (lb == null) {
    
    
            return null;
        } else {
    
    
            Server server = null;

            while(server == null) {
    
    
                if (Thread.interrupted()) {
    
    
                    return null;
                }
//                获取active的服务
                List<Server> upList = lb.getReachableServers();
//                获取所有的服务
                List<Server> allList = lb.getAllServers();
                int serverCount = allList.size();
                if (serverCount == 0) {
    
    
                    return null;
                }
//                新的算法
                if (totalCount < 5){
    
    
//                    每个服务用五次
                    totalCount++;
                    server = upList.get(currentIndex);
                }else {
    
    
//                    totalCount值大于5次说明,已经进入下一个服务了
                    totalCount = 0;
                    currentIndex++;
                    if (currentIndex>upList.size()) {
    
    
                        currentIndex = 0;
                    }
                    server = upList.get(currentIndex);
                }
//              老的算法
//                int index = this.chooseRandomInt(serverCount);
//                server = (Server)upList.get(index);

                if (server == null) {
    
    
                    Thread.yield();
                } else {
    
    
                    if (server.isAlive()) {
    
    
                        return server;
                    }

                    server = null;
                    Thread.yield();
                }
            }

            return server;
        }
    }
    protected int chooseRandomInt(int serverCount) {
    
    
//      获取当前线程的下一个随机整数
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

    @Override
    public Server choose(Object key) {
    
    
        return this.choose(this.getLoadBalancer(), key);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
    
    
    }
}

Agregar a la clase de inicio

package com.lzh.springcloud;

import com.lzh.myrule.MyRibbonRule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClientName;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 18:14:38
 */
@Slf4j
//加入Eureka服务
@EnableEurekaClient
//启用自己创建的ribbon算法规则
@SpringBootApplication
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = MyRibbonRule.class)
public class Springcloud_80 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Springcloud_80.class);
        log.info("启动成功!!");
    }
}

Proyecto de inicio:

Actualizar cinco veces para ingresar al siguiente servicio

inserte la descripción de la imagen aquí

5. Fingir: equilibrio de carga (basado en el servidor)

5.1 Introducción a Fingir

Fingir es un cliente de servicio web declarativo, que facilita las llamadas entre microservicios, de forma similar a como un controlador llama a un servicio. SpringCloud integra Ribbon y Eureka, y puede usar Feigin para proporcionar un cliente http con equilibrio de carga

Simplemente cree una interfaz y agregue anotaciones ~

Fingir, principalmente la versión comunitaria, todos están acostumbrados a la programación orientada a la interfaz. Esta es la norma para muchos desarrolladores. Llame a microservicios para acceder a dos métodos

Nombre del microservicio [cinta]
interfaz y anotación [fingir]
¿Qué puede hacer Fingir?

Fingir tiene como objetivo facilitar la escritura de clientes Http de Java.Cuando
se usa Ribbon + RestTemplate, RestTemplate se usa para encapsular solicitudes Http para formar un conjunto de métodos de llamada con plantilla. Sin embargo, en el desarrollo real, dado que puede haber más de una llamada a la dependencia del servicio, a menudo se llamará a una interfaz desde varios lugares, por lo que generalmente se encapsula una clase de cliente para cada microservicio para envolver las llamadas de estos servicios dependientes. Por lo tanto, Feign ha realizado una mayor encapsulación sobre esta base, y nos ayudará a definir e implementar la definición de interfaces de servicio dependientes. Bajo la implementación de Feign, solo necesitamos crear una interfaz y usar anotaciones para configurarla (similar a las anotaciones de Mapper anteriores están marcados en la interfaz Dao, y ahora una interfaz de microservicio está marcada con una anotación Fingir), y se puede completar el enlace de la interfaz con el proveedor de servicios, lo que simplifica el desarrollo de encapsular automáticamente el cliente de llamada de servicio cuando se usa Spring Cloud Ribbon.
Fingir integra Ribbon por defecto

Ribbon se utiliza para mantener la información de la lista de servicios de MicroServiceCloud-Dept, y el equilibrio de carga del cliente se realiza a través del sondeo. A diferencia de Ribbon, Fingir solo necesita definir la interfaz de enlace del servicio y usar un método declarativo, que es elegante y simple. Implementado una llamada de servicio

1. Crear un nuevo proyecto de simulación

inserte la descripción de la imagen aquí

2. Introducir la dependencia fingida en la clase de inicio
<?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>springCloudStudy</artifactId>-->
<!--        <groupId>org.example</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springCloud-consumer-dept-feign-80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>springCloudStudy</artifactId>
                <version>1.0-SNAPSHOT</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!--            引入实体-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springCloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        引入Eureka,ribbon可以从Eureka中获取需要拿的服务-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--        引入ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
<!--        引入feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    </dependencies>


</project>
3. Clase de configuración
server:
  port: 80
mybatis:
  #  配置检索的实体的包的前缀
  type-aliases-package: com.lzh.springcloud.dept
  mapper-locations: classpath:mybatis/mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
  application:
    #    微服务的唯一标识
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowMultiQueries=true
    username: root
    password: root
  # 配置Eureka
eureka:
  client:
#    不注册自己
    register-with-eureka: false
    service-url:
      defaultZone: http://localhost:7001/eureka/
4. Llamada de atención al consumidor
package com.lzh.springcloud.deptController;

import com.lzh.springcloud.dept.Dept;
import com.lzh.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * 消费者
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 18:06:35
 */
@RestController
public class DeptConsumerController {
    
    

    @Autowired
    private DeptService deptClientService;

    /**
     * 消费方添加部门信息
     * @param dept
     * @return
     */
    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept) {
    
    
        return deptClientService.addDept(dept);
    }

    /**
     * 消费方根据id查询部门信息
     * @param id
     * @return
     */
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
    
    
        return deptClientService.queryById(id);
    }

    /**
     * 消费方查询部门信息列表
     * @return
     */
    @RequestMapping("/consumer/dept/list")
    public List<Dept> list() {
    
    
        return deptClientService.queryAll();
    }
}
5. Clase de inicio
package com.lzh.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/15 13:17:21
 */
@SpringBootApplication
@EnableEurekaClient
// feign客户端注解,并指定要扫描的包以及配置接口DeptClientService
@EnableFeignClients(basePackages = {
    
    "com.lzh.springcloud"})
public class springcloud_feign {
    
    
    public static void main(String[] args) {
    
    
        ConfigurableApplicationContext run = SpringApplication.run(springcloud_feign.class);
        System.out.println("feign启动成功!!");
    }
}

6. Desde que se introdujo fingir en springCloud-api y se escribió la interfaz de servicio

<!--        引入feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

7. Interfaz de departamento:

package com.lzh.springcloud.service;

import com.lzh.springcloud.dept.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;

/**
 * dept相关service
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/15 13:34:39
 */
// @FeignClient:微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptService {
    
    

    @GetMapping("/dept/get/{id}")
     Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
     List<Dept> queryAll();

    @PostMapping("/dept/add")
     boolean addDept(Dept dept);
}

8. Comience en secuencia

inserte la descripción de la imagen aquí

9. Obtenido con éxito:

inserte la descripción de la imagen aquí

6. Hystrix: fusible de servicio

Problemas que enfrentan los sistemas distribuidos

Las aplicaciones en arquitecturas distribuidas complejas tienen docenas de dependencias, ¡cada una de las cuales inevitablemente fallará en algún momento!

6.1 Servicio Avalancha

Al llamar entre varios microservicios, suponga que el microservicio A llama al microservicio B y al microservicio C, y el microservicio B y el microservicio C llaman a otros microservicios. Esta es la llamada "distribución". Si la distribución Si el tiempo de respuesta de la llamada de un el microservicio en el enlace es demasiado largo, o si no está disponible, la llamada al microservicio A ocupará más y más recursos del sistema, provocando que el sistema se bloquee, el llamado "efecto avalancha".

inserte la descripción de la imagen aquí

Para aplicaciones de alto tráfico, una sola dependencia de back-end puede hacer que todos los recursos en todos los servidores se saturen en decenas de segundos. Peor que las fallas, estas aplicaciones también pueden causar un aumento de la latencia entre los servicios, sobrecargando las colas de respaldo, los subprocesos y otros recursos del sistema, lo que genera más fallas en cascada en todo el sistema, todo lo cual representa la necesidad de monitorear las fallas y la latencia. Aislamiento y administración para que la falla de una sola dependencia no afecta la operación completa de la aplicación o del sistema.

Necesitamos, abandonar el coche para salvar guapo!

6.2 ¿Qué es Hystrix?

Hystrix es una biblioteca de código abierto que se usa para lidiar con el retraso y la tolerancia a fallas de los sistemas distribuidos. En los sistemas distribuidos, muchas dependencias inevitablemente fallarán en llamar, como tiempos de espera, excepciones, etc. Hystrix puede garantizar que en el caso de una dependencia problema, no causará la falla de todo el servicio del sistema, evitará fallas en cascada y mejorará la resistencia del sistema distribuido.

El "disyuntor" en sí mismo es un dispositivo de conmutación. Cuando falla una unidad de servicio, a través del monitoreo de fallas del disyuntor (similar a un fusible fundido), se devuelve a la persona que llama una respuesta alternativa esperada y procesable (FallBack). de esperar durante mucho tiempo o lanzar una excepción que no puede ser manejada por el método de llamada, para garantizar que el subproceso de la persona que llama al servicio no esté ocupado durante mucho tiempo y sea innecesario, evitando así la propagación de fallas en el distribuido sistema Incluso una avalancha.

inserte la descripción de la imagen aquí

6.3 ¿Qué puede hacer Hystrix?

Degradación del servicio
Interrupción del circuito del
servicio Limitación del servicio
Supervisión casi en tiempo real
...
Cuando todo es normal, el flujo de solicitudes puede ser el siguiente:

inserte la descripción de la imagen aquí

Cuando existe un servicio potencialmente bloqueador entre muchos sistemas backend, puede bloquear toda la solicitud del usuario:

inserte la descripción de la imagen aquí

Con un gran volumen de tráfico, existe la posibilidad de que una sola dependencia de back-end sature todos los recursos en todos los servidores en cuestión de segundos.

Cada punto de su aplicación donde se puede realizar una solicitud de red a través de la red o una biblioteca de cliente es una fuente de falla potencial. Peor que fallar, estas aplicaciones también pueden causar un aumento de la latencia entre los servicios, haciendo copias de seguridad de las colas, subprocesos y otros recursos del sistema, lo que provoca más fallas en cascada entre los sistemas.

inserte la descripción de la imagen aquí

La arquitectura que se muestra en el diagrama anterior cambia de manera similar al diagrama a continuación cuando se usa Hystrix para envolver cada dependencia subyacente. Cada dependencia está aislada entre sí, limitada en los recursos que puede llenar cuando ocurre un retraso y envuelta en una lógica de respaldo que determina qué hacer en respuesta a cualquier tipo de falla en una dependencia:

inserte la descripción de la imagen aquí

Información del sitio web oficial: https://github.com/Netflix/Hystrix/wiki

6.4 Disyuntor de servicio

¿Qué es un fusible de servicio?
El mecanismo de fusible es un mecanismo de protección de enlace de microservicio que gana el efecto de avalancha.

Cuando un microservicio del enlace fan-out no está disponible o el tiempo de respuesta es demasiado largo, el servicio se degradará y luego se interrumpirá la llamada del microservicio del nodo y se devolverá rápidamente la información de respuesta incorrecta. Después de detectar que la respuesta de llamada del microservicio del nodo es normal, se restaura el enlace de llamada. En el marco SpringCloud, Hystrix implementa el mecanismo de fusión. Hystrix monitoreará el estado de las llamadas entre microservicios. Cuando la llamada fallida alcanza cierto umbral, el valor predeterminado es 20 llamadas fallidas en 5 segundos y el mecanismo de fusible se activará. La anotación del mecanismo de fusible es: @HystrixCommand.

6.5 El disyuntor de servicio resuelve los siguientes problemas:

Cuando el objeto dependiente es inestable, puede lograr el propósito de falla rápida;
después de la falla rápida, puede probar dinámicamente si el objeto dependiente se restaura de acuerdo con un algoritmo determinado.

1. Copie el módulo springCloud-provider-dept-8001

inserte la descripción de la imagen aquí

2. Agregar servicio de fusión de servicios en el archivo 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>springCloudStudy</artifactId>-->
<!--        <groupId>org.example</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springCloud-provider-dept-hystrix-8001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>springCloudStudy</artifactId>
                <version>1.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!--            引入实体-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springCloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        添加Eureka依赖-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--        添加服务熔断依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--        添加status跳转出页面的详情-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.25</version>
        </dependency>
    </dependencies>

</project>
3. Agregue la clase de inicio, anotación de fusible de servicio
package springcloud;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * 启动类
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 17:44:41
 */
@Slf4j
@SpringBootApplication
//开启Eureka客户端注解,再服务启动后自动注册到Eureka注册中心去
@EnableEurekaClient
//开启服务获取客户端注解,获取一些服务,得到一些信息
@EnableDiscoveryClient
//开启服务熔断注解
@EnableCircuitBreaker
public class springcloud_hystrix_8001 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(springcloud_hystrix_8001.class);
        log.info("启动成功!!");
    }
}

4. Se agrega el controlador y el contenido relevante después de que se rompe el servicio
package springcloud.dept.controller;

import cn.hutool.core.util.ObjectUtil;
import com.lzh.springcloud.dept.Dept;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springcloud.dept.service.DeptService;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 16:51:49
 */
@RestController
public class DeptController {
    
    

    @Autowired
    private DeptService deptService;

    @RequestMapping("/dept/get/{id}")
//    添加服务熔断注解
    @HystrixCommand(fallbackMethod = "hystrixMethod")
    public Dept get(@PathVariable("id") Long id){
    
    
        Dept dept = deptService.queryById(id);
        if (ObjectUtil.isEmpty(dept)){
    
    
            throw new RuntimeException("此id无法查询到用户信息");
        }
        return dept;
    }
    /**
     * 服务熔断
     *
     * @param id
     * @return
     * @author LZH
     * @date 2023/4/17 15:17:48
     * @version 1.0
     */
    public Dept hystrixMethod(@PathVariable("id") Long id){
    
    
        return new Dept().setDeptno(id).setDname("服务熔断备选部门名称").setDb_source("服务数据源");
    }
}
5. Iniciar el proyecto

inserte la descripción de la imagen aquí

Acceder a datos inexistentes:

inserte la descripción de la imagen aquí

Lanzar una excepción hizo que el servicio se fusionara

Por lo tanto, para evitar el reporte de errores de toda la aplicación o página web debido a una excepción o error en el fondo de un microservicio, es necesario usar un fusible

6.6 Degradación del servicio
1. ¿Qué es la degradación del servicio?

La degradación del servicio se refiere a cuando la presión sobre el servidor aumenta bruscamente, de acuerdo con la situación comercial y el tráfico reales, algunos servicios y páginas no se procesan estratégicamente o no se manejan de manera simple, a fin de liberar los recursos del servidor para garantizar el funcionamiento normal de el negocio principal u Operar de manera eficiente. Para decirlo sin rodeos, es ceder los recursos del sistema a los servicios de alta prioridad tanto como sea posible.

Los recursos son limitados, pero las solicitudes son ilimitadas. Si el servicio no se degrada durante el período pico de concurrencia, por un lado, definitivamente afectará el rendimiento del servicio general y, en casos severos, puede causar tiempo de inactividad y la falta de disponibilidad de algunos servicios importantes. Por lo tanto, generalmente durante el período pico, para garantizar la disponibilidad de los servicios funcionales básicos, algunos servicios deben degradarse. Por ejemplo, durante el evento Double 11, todos los servicios no relacionados con las transacciones se degradarán, como ver Ant Forest, ver pedidos históricos, etc.

¿Para qué escenarios se utilizan principalmente las degradaciones de servicio? Cuando la carga general de toda la arquitectura de microservicio supera el umbral superior preestablecido o se espera que el próximo tráfico supere el umbral preestablecido, para garantizar que los servicios básicos o importantes puedan ejecutarse normalmente, algunos no importantes o no urgentes Uso retrasado o suspensión de uso del servicio por parte de un servicio o tarea.

La forma de degradar se puede determinar de acuerdo con el negocio. Puede retrasar el servicio, como retrasar la adición de puntos al usuario, simplemente ponerlo en un caché y esperar a que el servicio se estabilice antes de ejecutarlo; o cerrar el servicio dentro de un rango granular, como cerrar la recomendación de artículos relacionados.

inserte la descripción de la imagen aquí

Como se puede ver en la figura anterior, cuando el número de visitas al servicio A aumenta considerablemente dentro de un cierto período de tiempo, mientras que el número de visitas al servicio B y C es menor, para aliviar la presión sobre el servicio A, B y C necesitan cerrar temporalmente algunas funciones de servicio en este momento para soportar la carga. Parte del servicio de A, para compartir la presión por A, se denomina degradación del servicio.

Preguntas a considerar en la degradación del servicio
1) Qué servicios son servicios centrales y qué servicios no son servicios centrales
2) Qué servicios pueden soportar la degradación, qué servicios no pueden soportar la degradación, cuál es la estrategia de degradación
3) ¿Hay algún negocio más complejo además del servicio? degradación Suelta la escena, ¿cuál es la estrategia?
Clasificación de degradación automática
1) Descenso de tiempo de espera: configure principalmente el período de tiempo de espera, la cantidad de reintentos de tiempo de espera y el mecanismo, y use el mecanismo asíncrono para detectar la respuesta

2) El número de fallas se reduce: principalmente para algunas API inestables. Cuando el número de llamadas fallidas alcanza un cierto umbral, se degradará automáticamente. También es necesario utilizar un mecanismo asíncrono para detectar la respuesta.

3) Degradación por falla: por ejemplo, si el servicio remoto al que se va a llamar cuelga (falla de red, falla de DNS, el servicio http devuelve un código de estado incorrecto, el servicio rpc genera una excepción), se puede degradar directamente. Las soluciones posteriores a la degradación incluyen: valor predeterminado (por ejemplo, si el servicio de inventario está inactivo, regrese al lugar predeterminado), datos de bolsillo (por ejemplo, si el anuncio está inactivo, regrese a algunas páginas estáticas preparadas con anticipación), caché (algunos datos en caché almacenados temporalmente antes)

4) Descenso del límite actual: cuando se eliminan rápidamente o se compran algunos productos restringidos, el sistema puede bloquearse debido a demasiado tráfico en este momento. En este momento, la limitación de tráfico se utilizará para limitar el tráfico. Cuando el umbral del límite de tráfico es alcanzado, las solicitudes posteriores se degradarán; la solución después de la degradación puede ser: página de cola (dirija al usuario a la página de cola y espere un momento para volver a intentarlo), agotado (informar directamente al usuario que el stock está agotado), página de error (si el evento es demasiado popular, espere un momento) Vuelva a intentarlo).

2. Implementación sencilla

Agregar clase de implementación al servicio en springCloud-api

inserte la descripción de la imagen aquí

package com.lzh.springcloud.service;

import com.lzh.springcloud.dept.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 服务熔断内容
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/18 13:49:53
 */
@Component
public class DeptCilentServiceFallBackFactory implements FallbackFactory {
    
    
    @Override
    public DeptService create(Throwable throwable) {
    
    
        return new DeptService(){
    
    

            @Override
            public Dept queryById(Long id) {
    
    
                return new Dept().setDeptno(id).setDname("降级了,没有数据了").setDb_source("降级啦");
            }

            @Override
            public List<Dept> queryAll() {
    
    
                return null;
            }

            @Override
            public boolean addDept(Dept dept) {
    
    
                return false;
            }
        };
    }
}

Agregue el método de degradación del servicio en DeptService

package com.lzh.springcloud.service;

import com.lzh.springcloud.dept.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;

/**
 * dept相关service
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/15 13:34:39
 */
// @FeignClient:微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptCilentServiceFallBackFactory.class)
public interface DeptService {
    
    

    @GetMapping("/dept/get/{id}")
     Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
     List<Dept> queryAll();

    @PostMapping("/dept/add")
     boolean addDept(Dept dept);
}

Habilite la degradación del servicio en el lado del consumidor springCloud-consumer-dept-feign-80

server:
  port: 80
mybatis:
  #  配置检索的实体的包的前缀
  type-aliases-package: com.lzh.springcloud.dept
  mapper-locations: classpath:mybatis/mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
  application:
    #    微服务的唯一标识
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowMultiQueries=true
    username: root
    password: root
  # 配置Eureka
eureka:
  client:
#    不注册自己
    register-with-eureka: false
    service-url:
      defaultZone: http://localhost:7001/eureka/
#开启服务降级
feign:
  hystrix:
    enabled: true
6.7 La diferencia entre fusible de servicio y degradación

Fusión del servicio —> servidor: un tiempo de espera o anormalidad del servicio, que causa la fusión~, similar a la degradación del servicio de fusión (autofusión)
—> cliente: considerando la carga general de la solicitud del sitio web, cuando un servicio se fusiona o se apaga, el servicio lo hará ya no se llama En este momento, en el lado del cliente, podemos preparar un FallBackFactory y devolver un valor predeterminado (valor predeterminado). Conducirá a una disminución en el servicio general, pero se puede usar de todos modos, lo cual es mejor que colgar directamente.
Las razones desencadenantes son diferentes. La fusión del servicio generalmente es causada por una falla del servicio (servicio descendente), y la degradación del servicio generalmente se considera a partir de la carga general; el nivel de los objetivos de administración es diferente. La fusión es en realidad un proceso a nivel de marco. Cada micro Se requieren todos los servicios (sin jerarquía), y la degradación generalmente debe ser jerárquica para el negocio (por ejemplo, la degradación generalmente comienza desde el servicio más periférico). El método de implementación es diferente, y la degradación del servicio es invasiva del código (completada por
el controlador/o degradación automática), la fusión generalmente se denomina autofusión.
Fusible, degradación, límite de corriente:

Limitación actual: limite la cantidad de acceso de solicitud concurrente, si excede el umbral, será rechazado;

Degradación: priorice los servicios, sacrifique los servicios no básicos (no disponibles) y garantice la estabilidad de los servicios básicos, tenga en cuenta la carga general;

Fusible: la falla de los servicios descendentes dependientes activa un fusible para evitar que el sistema se bloquee; el sistema se ejecuta y se recupera automáticamente

6.8 Supervisión del flujo del tablero

Cree un nuevo módulo springcloud-consumer-hystrix-dashboard

inserte la descripción de la imagen aquí

Agregue la dependencia del tablero al archivo 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>springCloudStudy</artifactId>-->
<!--        <groupId>org.example</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springCloud-consumer-dept-hystrix-dashbord</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>springCloudStudy</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <!--dashboard流监控-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <!--            引入实体-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springCloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        引入Eureka,ribbon可以从Eureka中获取需要拿的服务-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!--        引入ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    </dependencies>
</project>

Archivo de configuración:

server:
  port: 9001

Clase de inicio:

package com.lzh.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;

/**
 * 描述
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/18 17:17:37
 */
@SpringBootApplication
//开启dashboard监控
@EnableHystrixDashboard
public class dept_hystrix_dashbord {
    
    
    public static void main(String[] args) {
    
    
        ConfigurableApplicationContext run = SpringApplication.run(dept_hystrix_dashbord.class);
        System.out.println("启动成功!!");
    }

}

Se agregó la clase de inicio springCloud-provider-dept-hystrix-8001

package springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

/**
 * 启动类
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/07 17:44:41
 */
@Slf4j
@SpringBootApplication
//开启Eureka客户端注解,再服务启动后自动注册到Eureka注册中心去
@EnableEurekaClient
//开启服务获取客户端注解,获取一些服务,得到一些信息
@EnableDiscoveryClient
//开启服务熔断注解
@EnableCircuitBreaker
public class springcloud_hystrix_8001 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(springcloud_hystrix_8001.class);
        log.info("启动成功!!");
    }


    //增加一个 Servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
    
    
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        //访问该页面就是监控页面
        registrationBean.addUrlMappings("/actuator/hystrix.stream");

        return registrationBean;
    }
}

Visite http://localhost:9001/hystrix y complete los servicios de monitoreo relevantes

inserte la descripción de la imagen aquí
Llame al servicio, puede ver el monitoreo en tiempo real

inserte la descripción de la imagen aquí

7. Puerta de enlace de enrutamiento Zuul

7.1, qué es Zuul

Zuul incluye dos funciones principales de enrutamiento y filtrado de solicitudes:
la función de enrutamiento es responsable de reenviar solicitudes externas a instancias de microservicio específicas, que es la base para realizar una entrada unificada para el acceso externo, mientras que la función de filtro es responsable del procesamiento de solicitudes Intervención en el El proceso de procesamiento es la base para implementar funciones como la verificación de solicitudes y la agregación de servicios. Zuul y Eureka están integrados, y el propio Zuu se registra como una aplicación bajo la gestión de servicios de Eureka, y al mismo tiempo, se obtienen otras noticias de microservicios de Eureka, es decir, se obtiene acceso futuro a los microservicios después de saltar a través de Zuul.

Nota: el servicio Zuul finalmente se registrará en Eureka

Proporcione: proxy + enrutamiento + filtrado de tres funciones principales

7.2 Qué puede hacer Zuul


Filtro de enrutamiento
Documentación del sitio web oficial => https://github.com/Netflix/zuul

7.3 Por qué construir Zuul

El volumen y la variedad del tráfico de Netflix.API a veces pueden hacer que surjan problemas de producción rápidamente y sin previo aviso. Necesitamos un sistema que nos permita
cambiar rápidamente el comportamiento en respuesta a estas situaciones.

Zuul utiliza una variedad de diferentes tipos de filtros, que nos permiten aplicar funciones de manera rápida y flexible a los servicios de borde. Estos filtros
nos ayudan a realizar las siguientes funciones:

Autenticación y seguridad identifica los requisitos de autenticación para cada recurso y rechaza las solicitudes que no cumplen con los requisitos.
Perspectivas y monitoreo Generar datos y estadísticas significativos en el borde para brindarnos una imagen precisa de la producción.
El enrutamiento dinámico enruta dinámicamente las solicitudes a diferentes clústeres de back-end según sea necesario.
Las pruebas de estrés aumentan gradualmente el tráfico al clúster para evaluar el rendimiento.
Reducción de carga: reduce la capacidad asignada para cada tipo de solicitud y elimina las solicitudes que superan el límite.
Manejo de respuestas estáticas: cree algunas respuestas directamente en el borde. En lugar de reenviarlo al clúster interno,
las solicitudes de rutas elásticas de múltiples regiones entre las regiones de AWS para diversificar nuestro uso de ELB y acercar nuestras fortalezas a nuestros miembros Para obtener más detalles: Cómo usamos Zuul en Netfio

7.4 Componentes Zuul

zuul-core–zuul core library, que contiene las funciones principales de compilación y ejecución de filtros
zuul-simple-webapp–zuul web application example, que muestra cómo usar zuul-core para crear aplicaciones
zuul-netflix–lib package, que integra otros NetflixOSS componentes Agréguelo a Zuul, por ejemplo, use el área funcional para ingresar el procesamiento de solicitud de enrutamiento
zuul-netflix-webapp-webapp, que encapsula zuul-core y zuul-netflix en un paquete de proyecto de aplicación web simple

7.5 Construcción del proyecto de puerta de enlace de enrutamiento Zuul

Crear proyecto maven springcloud/springcloud-zuul-9527

Importe todas las dependencias del proyecto springcloud-consumer-hystrix-dashboard y agregue las dependencias de Zuul
para crear subproyectos:

inserte la descripción de la imagen aquí

archivo de configuración

server:
  port: 9527
spring:
  application:
#    服务名称
    name: springcloud-zuul
#Eureka注册
eureka:
  client:
    service-url:
      #      访问7001
      defaultZone: http://localhost:7001/eureka/
  instance:
    #修改Eureka中status的默认描述信息。不配置默认为DESKTOP-XXX描述
    instance-id: springcloud-zuul
    prefer-ip-address: true
info:
  app.name: com.lzh.springclod
  company.name: 苏州xx公司
zuul:
  routes:
    mydept.serviceId: springcloud-provider-dept
      #之前的查询链接地址 http://activate.navicat.com:9527/springcloud-provider-dept/dept/get/1
      #现在的查询链接地址,配置后为 http://activate.navicat.com:9527/mydept/dept/get/1
    #两者都皆可访问(原路径+现配路径)。配置自定义的前缀后 可不让客户端知道真实的ip地址
    mydept.path: /mydept/**
      #加上此配置后 原路径不能访问(springcloud-provider-dept/dept/get/6),只能通过自定义的规则路径访问。
      #ignored-services: springcloud-provider-dept
    #星号(*) 隐藏全部的项目真实名字
  ignored-services: "*"
  prefix: /lzh #设置公共的地址前缀 配置后链接为:activate.navicat.com:9527/li/mydept/dept/get/11

archivo 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>springCloudStudy</artifactId>-->
<!--        <groupId>org.example</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springCloud-zuul</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>springCloudStudy</artifactId>
                <version>1.0-SNAPSHOT</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
<!--        引入zuul网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
<!--        引入Eureka注册中心-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
<!--        引入feign负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
<!--        引入Hystrix服务熔断-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
<!--        引入ribbon客户端的负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
<!--        引入实体类-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springCloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
<!--        web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

Clase de inicio:

package com.lzh.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * 网关启动类
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/20 16:25:45
 */
@SpringBootApplication
@EnableZuulProxy // 开启Zuul
public class Springcloud_zuul {
    
    
    public static void main(String[] args) {
    
    
        ConfigurableApplicationContext run = SpringApplication.run(Springcloud_zuul.class);
        System.out.println("启动成功!!!");
    }

}

Iniciar el servicio de prueba

inserte la descripción de la imagen aquí

Ver C:\Windows\System32\drivers\etc\hosts para simular la puerta de enlace zuul

127.0.0.1       activate.navicat.com

El acceso antes de configurar zuul es el siguiente:

inserte la descripción de la imagen aquí

Después de agregar la configuración de zuul, el acceso es el siguiente:

inserte la descripción de la imagen aquí

Vemos que el nombre del microservicio se reemplaza y se oculta, se reemplaza con nuestro nombre de microservicio personalizado mydept, y el prefijo haust se agrega al mismo tiempo, ¡para que el acceso al ventilador de enrutamiento esté encriptado!

Para obtener más información, consulte el componente zuul de la comunidad china springcloud: https://www.springcloud.cc/spring-cloud-greenwich.html#_router_and_filter_zuul

8. Configuración distribuida Spring Cloud Config

Dalston.RELEASE

Spring Cloud Config proporciona soporte de servidor y cliente para la configuración externa en sistemas distribuidos. Con Config Server, puede administrar las propiedades externas de las aplicaciones en todos los entornos. El mapeo conceptual en el cliente y el servidor es el mismo que las abstracciones Spring Environment y PropertySource, por lo que encajan bien con las aplicaciones Spring, pero se pueden usar con cualquier aplicación que se ejecute en cualquier idioma. A medida que la aplicación pasa por el proceso de implementación desde el desarrollador hasta la prueba y la producción, puede administrar la configuración entre estos entornos y asegurarse de que la aplicación tenga todo lo que necesita para ejecutarse cuando migre. La implementación predeterminada del backend de almacenamiento del servidor usa git, por lo que admite fácilmente versiones etiquetadas de entornos de configuración, así como acceso a varias herramientas para administrar contenido. Es fácil agregar implementaciones alternativas y conectarlas usando la configuración de Spring.

Descripción general
de los sistemas distribuidos que enfrentan: problemas con el archivo de configuración

Los microservicios significan dividir el negocio en una sola aplicación en subservicios. La granularidad de cada servicio es relativamente pequeña, por lo que habrá una gran cantidad de servicios en el sistema. Dado que cada servicio requiere la información de configuración necesaria para ejecutarse, por lo tanto, un sistema centralizado , la instalación de gestión de configuración dinámica es esencial. Spring Cloud proporciona configServer para resolver este problema. Cada uno de nuestros microservicios lleva una aplicación.yml. ¡Es un dolor de cabeza modificar cientos de archivos de configuración!

¿Qué es el centro de configuración distribuido SpringCloud config?

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y cargarla directamente (img-pE2ByaTt-1683193762693)(\49.png)]

Spring Cloud config proporciona soporte externo centralizado para microservicios en la arquitectura de microservicios, y el servidor de configuración proporciona una configuración externa centralizada para todos los enlaces de diferentes aplicaciones de microservicios.

La configuración de Spring Cloud se divide en dos partes: servidor y cliente.

El servidor, también conocido como centro de configuración distribuido, es una aplicación de microservicio independiente que se utiliza para conectarse al servidor de configuración y proporcionar interfaces de acceso para que el cliente obtenga información de configuración, cifre y descifre información.

El cliente administra los recursos de la aplicación y el contenido de configuración relacionado con el negocio a través del centro de configuración designado y obtiene y carga la información de configuración del centro de configuración al inicio. De forma predeterminada, el servidor de configuración usa git para almacenar información de configuración, lo que es útil para la gestión de versiones de la configuración del entorno. Y el contenido de configuración se puede administrar y acceder fácilmente a través de la herramienta de cliente git.

¿Qué puede hacer el centro de configuración distribuido spring cloud config?

Administración centralizada de archivos de configuración
Diferentes entornos, diferentes configuraciones, actualizaciones de configuración dinámicas e implementación en diferentes entornos, como /dev /test /prod /beta /release
ajustan dinámicamente la configuración durante la operación, ya no es necesario escribir en cada máquina de implementación de servicio Configuración archivo, el servicio extraerá y configurará su propia información desde el centro de configuración.
Cuando la configuración cambia, el servicio puede detectar el cambio de configuración y aplicar la nueva configuración sin reiniciar.
Exponga la información de configuración a
Spring Cloud en forma de una interfaz REST .config Centro de configuración distribuido e integración de GitHub

Dado que spring cloud config usa git para almacenar archivos de configuración de forma predeterminada (hay otras formas, como SVN autosuficiente y archivos locales), pero git es el más recomendado y usa la forma de acceso http / https.

código de registro de configuración de compilación del entorno de configuración de springcloud
cuenta en la nube https://gitee.com/. Puede iniciar sesión a través de qq wechat

Cree un nuevo almacén springcloud-config, configúrelo como público y seleccione java para el idioma y la plantilla. Licencia de código abierto GPL-3.0, copie la dirección del túnel SSH del almacén actual después de crear el almacén

Cree una nueva carpeta en la computadora, use la herramienta GitBash para ejecutar la dirección SSH copiada por git clone springcloud-config y extraiga el contenido del almacén. Después de extraer, seleccione sí, porque los permisos no existen, necesita configurar el Git actual

Git Daquan[https://gitee.com/all-about-git]

1. El primer paso es crear un almacén en git

inserte la descripción de la imagen aquí

2. Extraiga la información del almacén

Comandos comunes

# 显示当前的Git配置
$ git config --list

# 编辑Git配置文件
$ git config -e [--global]

# 设置提交代码时的用户信息
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"
# 下载一个项目和它的整个代码历史
$ git clone [url]

código de extracción

inserte la descripción de la imagen aquí

En este punto, el código remoto se ha obtenido
inserte la descripción de la imagen aquí

Cree el archivo application.ynl y envíelo al almacén.

spring:
  profiles:
    active: dev
---
spring:
  profiles: dev
  application:
    name: springcloud-config-dev
---
spring:
  profiles: test
  application:
    name: springcloud-config-test

Enviado satisfactoriamente:

inserte la descripción de la imagen aquí

Estudio de caso de introducción

Crear un nuevo subproyecto:

inserte la descripción de la imagen aquí

El archivo pom se ve así:

<?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>springCloudStudy</artifactId>-->
<!--        <groupId>org.example</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springCloud-config-server-2233</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>springCloudStudy</artifactId>
                <version>1.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
<!--        引入springboot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
<!--        监控可不加-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

</project>

Inicie la clase, abra la anotación de configuración del servicio

package com.lzh.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

/**
 * 启动类
 *
 * @author LZH
 * @version 1.0
 * @date 2023/04/24 14:39:34
 */
@SpringBootApplication
//开启配置服务
@EnableConfigServer
public class springcloud_2233 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(springcloud_2233.class);
        System.out.println("启动成功!!");
    }
}

archivo de configuración

server:
  port: 2233
spring:
  application:
    name: springcloud-config-server
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/xxx/lzh_springcloud.git
		#不加报错 Authentication is required but no CredentialsProvider has been registered
          username: xxx
          password: xxx

Una conexión privada requiere un nombre de usuario y contraseña

Error:

Se requiere autenticación pero no se ha registrado CredentialsProvider

accede de la siguiente manera

http://localhost:2233/aplicación-dev.yml

inserte la descripción de la imagen aquí

http://localhost:2233/prueba-de-aplicación.yml

inserte la descripción de la imagen aquí

Agregue el archivo de configuración config-cilent.yml en el almacén

El contenido es el siguiente:

#启动环境选择的配置
spring:
  profiles:
    active: dev

#springboot启动多环境的配置
---
server:
  port: 8201
#spring的配置
spring:
  profiles: dev
  application:
    name: springcloud-config-client-dev
#Eureka的配置。 服务注册到Eureka中,需要一个路径地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
---
server:
  port: 8202
#spring的配置
spring:
  profiles: test
  application:
    name: springcloud-config-client-test

#Eureka的配置。 服务注册到Eureka中,需要一个路径地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/

Empuje el archivo al almacén remoto

inserte la descripción de la imagen aquí

El comando git es el siguiente:

GitBash打开命令工具
cd 至 springcloud-config

git add .  将文件添加到暂存区

git status 查看状态

git commit -m “一次提交” 本地提交,-m为提交时写的信息

git push origin master 提交到远程的当前路径分枝

Supongo que te gusta

Origin blog.csdn.net/weixin_43987718/article/details/130492058
Recomendado
Clasificación