Deus louco springcloud aprendendo

aprendizado de nuvem de primavera

Fonte de classificação de notas B estação UP master mad god said https://www.bilibili.com/video/BV1jJ411S7xr
Referência: novato Xiaojiezi https://blog.csdn.net/lijie0213/article/details/107914619
Referência: Luffy https:/ /csp1999.blog.csdn.net/article/details/106255122?spm=1001.2014.3001.5502

1. Visão Geral

1.1. Pré-requisitos
  • Uso qualificado do framework de desenvolvimento springboot
  • Entenda a fundação distribuída Dubbo + Zookeeper
  • A memória de configuração do computador não é inferior a 8G (a minha é 16G)
1.2. Objetivo de aprendizagem
  • Proficiência no uso do springcloud para construir uma estrutura de microsserviços
  • Saiba mais sobre microsserviços (perguntas da entrevista)

2. Construção do projeto Springcloud

2.1. Introdução geral
  • Utilizaremos um módulo de departamento Dept para fazer um caso geral de microsserviços: O consumidor (Cliente) chama o serviço prestado pelo provedor Provedor (Servidor) através de REST.
  • Lembre-se do conhecimento anterior de Spring, SpringMVC, Mybatis, etc.
  • Revisão da arquitetura do módulo de subpacote do Maven

Simplificando, um projeto pai contém vários subprojetos

Um projeto pai com vários submódulos Moudule

Projeto pai MicroServiceCloud (Projeto) com 3 submódulos (Módulo) pela primeira vez

microservicecloud-api [entidade geral encapsulada/interface/configuração pública, etc.]
microservicecloud-consumer-dept-80 [provedor de serviço]
microservicecloud-provider-dept-8001 [consumidor de serviço]

2.2, seleção de versão do springcloud

Descrição da versão principal

SpringBoot SpringCloud relação
1.2.x Versão Anjo (Anjo) Compatível com SpringBoot1.2x
1.3.x Edição Brixton (Brixton) Compatível com SpringBoot1.3x, também compatível com SpringBoot1.4x
1.4.x Versão de Camden (Camden) Compatível com SpringBoot1.4x, também compatível com SpringBoot1.5x
1.5.x Versão Dalston (Dalston) Compatível com SpringBoot1.5x, não compatível com SpringBoot2.0x
1.5.x Edição Edgware (Edgware) Compatível com SpringBoot1.5x, não compatível com SpringBoot2.0x
2.0.x Versão Finchley (Finchley) Compatível com SpringBoot2.0x, não compatível com SpringBoot1.5x
2.1.x Versão Greenwich (Greenwich)

Relacionamento real da versão de desenvolvimento

spring-boot-starter-pai dependências de nuvens de primavera
número da versão data de lançamento número da versão data de lançamento
1.5.2.LIBERAÇÃO 2017-03 Dalston.RC1 2017-x
1.5.9.LIBERAÇÃO 2017-11 Edgware.RELEASE 2017-11
1.5.16.LIBERAÇÃO 2018-04 Edgware.SR5 2018-10
1.5.20.LIBERAÇÃO 2018-09 Edgware.SR5 2018-10
2.0.2.LIBERAÇÃO 2018-05 Fomchiey.BULD-SNAPSHOT 2018-x
2.0.6.LIBERAÇÃO 2018-10 Fomchiey-SR2 2018-10
2.1.4.LIBERAÇÃO 2019-04 Greenwich.SR1 2019-03

Recomenda-se usar as duas últimas versões de desenvolvimento

2.3. Criar projetos relacionados

insira a descrição da imagem aqui

1. Crie um novo projeto pai

Crie um novo projeto maven como mostrado abaixo

insira a descrição da imagem aqui

  • Criado da seguinte forma:

insira a descrição da imagem aqui

Exclua o arquivo src e mantenha apenas um arquivo pom (o projeto pai não precisa escrever conteúdo lógico)

  • conteúdo do arquivo 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 e escopo em herança múltipla no maven (revisão):

configurações do arquivo pom

Por que a dependência tem um tipo de pom e qual é o valor padrão?

O tipo na dependência padrão é jar, ou seja, um pacote jar específico é introduzido. Então, por que ainda existe um tipo de pom? Quando precisamos introduzir muitos pacotes jar, o pom.xml será muito grande. Uma solução que podemos pensar é definir um projeto pai, mas há apenas um projeto pai, que também pode causar O arquivo pom.xml do projeto pai é muito grande. Neste momento, introduzimos um tipo de pom, o que significa que podemos empacotar todos os pacotes jar em um pom, e então dependemos do pom, ou seja, podemos baixar todos os pacotes jar dependentes

escopo escopo

  • compile: o escopo padrão, indicando que as dependências neste escopo são válidas na compilação, operação e teste
  • fornecido: teste e compilação são válidos
  • tempo de execução: executar e testar válido
  • teste: Válido para teste
  • system: Indica que a dependência é fornecida por nós, e o maven não precisa procurá-la no warehouse. Quando usado, precisa ser systemPathusado em conjunto com outro rótulo. Esse rótulo indica a localização da dependência no sistema, usando um caminho absoluto

exemplo:

<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 é usado quando herança múltipla

Ao herdar as dependências de um projeto, você pode declarar no subprojeto que precisa usar as dependências definidas no dependencyMangement do projeto pai. Mas cada projeto só pode declarar um único projeto pai, o que limitará o estabelecimento de nosso projeto em algum momento.

Para isso, o Maven nos fornece um método, ou seja, definindo o escopo da dependência como import. Observe que este método só tem efeito em versões acima do Maven2.0.9.

Só pode ser usado em dependencyManagement

Dependências do projeto pai:

<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> 

Caso seja utilizado o mecanismo de herança anterior, o arquivo pom.xml do subprojeto artefatoB é definido da seguinte forma:

<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 importação

<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. Criar entidade springcloud-api
  • Encapsule as entidades envolvidas no serviço, configuração pública, etc.

insira a descrição da imagem aqui

  • Crie a classe de entidade do departamento dept:
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;


}

  • O script fica assim:
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. Crie um provedor de serviços

insira a descrição da imagem aqui

  • O arquivo pom fica assim:
<?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>
  • Arquivo de configuração application.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

  • Escreva código comercial, crud de tabela única

  • DeptController:

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();
    }
}

  • Departamento de Serviço:
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>
  • Classe de inicialização:
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("启动成功!!");
    }
}
  • Teste após a inicialização:

insira a descrição da imagem aqui

insira a descrição da imagem aqui

4. Escreva ao consumidor:

insira a descrição da imagem aqui

  • dependências do 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>
  • Arquivo de configuração:
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
  • DeptConsumerController:
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);
    }
}
  • Configuração:
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();
    }
}
  • Classe de inicialização:
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 o serviço 8001 e o serviço 80, use o serviço 80 para ligar para o serviço 8001

insira a descrição da imagem aqui

3. Centro de Registro do Serviço Eureka

3.1 O que é Eureka

A Netflix segue o princípio da API quando se trata de Eureka.
Eureka é um submódulo da Netflix e um dos módulos principais. Eureka é um serviço baseado em REST usado para localizar serviços para realizar descoberta de serviço e failover na camada de middleware da nuvem. Registro e descoberta de serviço são muito importantes para microsserviços. Com registro e descoberta de serviço, você só precisa usar o identificador de serviço, você pode acessar o serviço sem modificar o arquivo de configuração chamado pelo serviço.A função é semelhante à central de cadastro do Dubbo, como o Zookeeper.

3.2 Entendimento do princípio

Arquitetura básica do Eureka

O Springcloud encapsula o módulo Eureka desenvolvido pela Netflix para realizar o registro e a descoberta de serviços (em comparação com o Zookeeper).

Eureka adota o design de arquitetura do CS. EurekaServer é o servidor da função de registro do serviço e é o centro de registro do serviço.

Outros microsserviços no sistema usam o cliente Eureka para se conectar ao EurekaServer e manter uma conexão de pulsação. Desta forma, os mantenedores do sistema podem usar o EurekaServer para monitorar se cada microsserviço no sistema está rodando normalmente, e alguns outros módulos do Springcloud (como o Zuul) podem usar o EurekaServer para descobrir outros microsserviços no sistema e executar a lógica relacionada.

insira a descrição da imagem aqui

Comparado com a arquitetura Dubbo.

insira a descrição da imagem aqui

Eureka consiste em dois componentes: Eureka Server e Eureka Client.

O Eureka Server fornece o registro do serviço. Após cada nó ser iniciado, ele será registrado no EurekaServer, de forma que o registro do serviço no Eureka Server armazenará as informações de todos os nós do serviço da classe, e as informações dos nós do serviço podem ser visualizadas intuitivamente na interface .

O Eureka Client é um cliente Java que simplifica a interação com o EurekaServer.O cliente também possui um balanceador de carga embutido que usa um algoritmo de carga round-robin. Após o início do aplicativo, uma pulsação será enviada ao EurekaServer (o período padrão é de 30 segundos). Se o Eureka Server não receber a pulsação de um nó em vários ciclos de pulsação, o EurekaServer removerá o nó de serviço do registro de serviço (o ciclo padrão é 90s).

três funções

Servidor Eureka: Fornece registro e descoberta
de serviços Provedor de serviços: Produtor de serviços, registra seu próprio serviço no Eureka, para que o consumidor do serviço possa encontrar
Consumidor do serviço: Consumidor do serviço, obtém a lista de serviços registrados da Eureka, para encontrar o consumidor Servir

3.3, configurar o centro de registro do serviço Eureka

1. Introduza a dependência do Eureka no arquivo pom

2. Defina a configuração relacionada ao Eureka no arquivo de configuração

3. Adicione anotações Eureka à classe de inicialização

insira a descrição da imagem aqui

1. Aula de inicialização:
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. Arquivo de configuração:
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. arquivo 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. O acesso é o seguinte:

insira a descrição da imagem aqui

Consumo do serviço Eureka, registro, configuração de informações, mecanismo de autoproteção

5. Adicione a dependência Eureka em springCloud-provider-dept-8001

1. arquivo 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>

Adicionar anotações Eureka à classe de inicialização

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("启动成功!!");
    }
}

Adicione a configuração do Eureka à classe de configuração

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

Inicie o serviço 8001 e o serviço 7001 da seguinte forma:

A descrição no status é o conteúdo do ID da instância sob a instância sob o Eureka configurado na classe de configuração

insira a descrição da imagem aqui

Pare o serviço 8001 e, após aguardar 30s, o mecanismo de proteção será ativado:

insira a descrição da imagem aqui

Configure as informações de monitoramento carregadas pelo serviço:

insira a descrição da imagem aqui

Se você não configurar, é 404

Adicione ao arquivo pom:

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

Adicione ao arquivo de configuração:

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

Clique no salto de rota em status

insira a descrição da imagem aqui

Do seguinte modo:

insira a descrição da imagem aqui

3.4. Mecanismo de autoproteção de EureKa: é melhor viver do que morrer

O resumo de uma frase é: um determinado microsserviço está indisponível em um determinado momento, o eureka não o limpará imediatamente e ainda salvará as informações do microsserviço!

Por padrão, quando o servidor eureka não recebe o heartbeat da instância dentro de um determinado período de tempo, ele excluirá a instância do registro (o padrão é 90 segundos), mas se um grande número de heartbeats da instância for perdido em um curto período de tempo, ele acionará o mecanismo de autoproteção do servidor eureka, por exemplo, durante o desenvolvimento e teste, as instâncias de microsserviço precisam ser reiniciadas com frequência, mas raramente reiniciamos o servidor eureka juntos (porque o centro de registro eureka não será modificado durante o processo de desenvolvimento), quando fechado dentro de um minuto Este mecanismo de proteção será acionado quando o número de heartbeats recebidos diminuir significativamente. Você pode ver Renews threshold e Renews(last min) na interface de gerenciamento do eureka. Quando o último (número de pulsações recebidas no último minuto) for menor que o primeiro (limite de pulsação), o mecanismo de proteção será acionado e um aviso vermelho aparecerá: EMERGÊNCIA! EUREKA PODE ESTAR INCORRETAMENTE REIVINDICANDO QUE AS INSTÂNCIAS ESTÃO ATIVAS QUANDO NÃO ESTÃO. AS RENOVAÇÕES SÃO MENOR QUE O LIMITE E, POR ISSO, AS INSTÂNCIAS NÃO ESTÃO COMEÇANDO A EXPIRAR APENAS PARA SEGURAR. Como pode ser visto no aviso, Eureka acredita que, embora o A pulsação da instância não pode ser recebida, mas considera que a instância ainda está íntegra e o eureka protegerá essas instâncias e não as excluirá do registro.

O objetivo desse mecanismo de proteção é evitar falhas de conexão de rede. Quando ocorre uma falha de rede, o microsserviço e o centro de registro não podem se comunicar normalmente, mas o serviço em si está íntegro e não deve ser cancelado. Se o eureka falhar, o microsserviço devido por falha de rede Excluído por engano, mesmo que a rede seja restaurada, o microsserviço não será registrado novamente no servidor eureka, pois a solicitação de registro só será iniciada quando o microsserviço for iniciado, e apenas solicitações de heartbeat e lista de serviços serão enviado posteriormente. Nesse caso, embora a instância esteja em execução, ela nunca será conhecida por outros serviços. Portanto, quando o servidor eureka perder muitos heartbeats do cliente em um curto período de tempo, ele entrará no modo de autoproteção. Nesse modo, o eureka protegerá as informações no registro e não desconectará nenhum microsserviço. Quando a rede Se a falha for recuperada, o eureka sairá automaticamente do modo protegido. O modo de autopreservação pode tornar o cluster mais robusto.

No entanto, durante a fase de desenvolvimento e teste, precisamos reiniciar o lançamento com frequência. Se o mecanismo de proteção for acionado, a instância do serviço antigo não é excluída. Nesse momento, a solicitação pode ir para a instância antiga e a instância foi fechado, o que leva a A solicitação está errada, o que afeta o desenvolvimento e o teste. Portanto, na fase de desenvolvimento e teste, podemos desligar o modo de autopreservação, basta adicionar a seguinte configuração ao arquivo de configuração do servidor eureka: eureka.server.enable-self-preservation=false【Não é recomendado desligar o mecanismo de autopreservação】

3.5. Obtenha algumas informações sobre o serviço registrado

Classe de inicialização mais anotações para obter serviços ao 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("启动成功!!");
    }
}

Obtenha informações relacionadas ao serviço da interface

@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;
}

acesse da seguinte forma

insira a descrição da imagem aqui

3.6. Construção do cluster Eureka, apenas dê uma olhada por enquanto

Eureka vs zookeeper

  1. Revise o princípio CAP
    RDBMS (MySQL\Oracle\sqlServer) ===> ACID

NoSQL (Redis\MongoDB) ===> CAP

  1. O que é ACID?
    A (Atomicidade) Atomicidade
    C (Consistência) Consistência
    I (Isolamento) Isolamento
    D (Durabilidade) Persistência

  2. O que é CAP?
    C (Consistência) Forte consistência
    A (Disponibilidade) Disponibilidade
    P (Tolerância de partição) Tolerância a falhas de partição
    CAP três em dois: CA, AP, CP

  3. O núcleo da teoria CAP
    É impossível para um sistema distribuído satisfazer os três requisitos de consistência, disponibilidade e tolerância de partição ao mesmo tempo.
    De acordo com o princípio CAP, os bancos de dados NoSQL são divididos em três categorias que satisfazem o princípio CA, o princípio CP, e satisfaz o princípio AP.
    CA: cluster de ponto único, sistema que atende consistência e disponibilidade, geralmente tem baixa escalabilidade
    CP: sistema que atende consistência e tolerância de partição, geralmente não é particularmente alto desempenho
    AP: sistema que atende disponibilidade e tolerância à partição, geralmente pode ser consistente menos exigente

  4. Como um registro de serviço distribuído, como o Eureka é melhor do que o Zookeeper?
    A famosa teoria CAP aponta que é impossível para um sistema distribuído satisfazer C (consistência), A (disponibilidade) e P (tolerância a falhas) ao mesmo tempo. Visto que a tolerância a falhas de partição P deve ser garantida em um sistema distribuído, nós apenas A trade-off pode ser feito entre A e C.

O que o Zookeeper garante é CP —> um sistema que atende à consistência e tolerância à partição, geralmente o desempenho não é particularmente alto.
Eureka garante AP —> um sistema que atende à disponibilidade e tolerância à partição, geralmente pode ter requisitos mais baixos de consistência.
Zookeeper garante CP

Ao consultar a lista de serviços do centro de registro, podemos tolerar que o centro de registro retorne as informações de registro alguns minutos atrás, mas não podemos receber o serviço e desligar diretamente e ficar indisponível. Em outras palavras, a função de registro do serviço tem requisitos mais altos de usabilidade do que de consistência. No entanto, haverá tal situação no zookeeper.Quando o nó mestre perde o contato com outros nós devido a falha de rede, os nós restantes reelegerão o líder. O problema é que demora muito para eleger um líder, 30-120s, e todo o cluster de tratadores fica indisponível durante a eleição, o que leva à paralisação do serviço de cadastro durante a eleição. Em um ambiente de implantação em nuvem, é muito provável que o cluster do zookeeper perca o master node devido a problemas de rede. Embora o serviço possa eventualmente ser restaurado, o longo tempo de eleição torna o registro indisponível por muito tempo, o que é intolerável.

Eureka garante AP

A Eureka entende isso, por isso prioriza a usabilidade no design. Todos os nós do Eureka são iguais e a falha de vários nós não afetará o trabalho dos nós normais, e os nós restantes ainda podem fornecer serviços de registro e consulta. Quando o cliente Eureka se registra com um Eureka, se constatar que a conexão falha, ele automaticamente muda para outros nós. Enquanto um Eureka ainda estiver lá, a disponibilidade do serviço de registro pode ser mantida, mas as informações encontradas podem não ser o mais recente. Sim, além disso, o Eureka também possui um mecanismo de autoproteção. Se mais de 85% dos nós não tiverem uma pulsação normal em 15 minutos, o Eureka pensará que há uma falha de rede entre o cliente e o centro de registo. As seguintes situações:

O Eureka não está removendo da lista de cadastro que deveriam expirar por não receberem heartbeats há muito tempo
serviços situação em que alguns nós perdem o contato devido a falha na rede e não paralisam todo o serviço de registro como o zookeeper

4. Faixa de opções: balanceamento de carga (baseado no cliente)

4.1 Balanceamento de carga e fita

O que é Fita?

O Spring Cloud Ribbon é um conjunto de ferramentas de balanceamento de carga do cliente baseado no Netflix Ribbon.
Simplificando, Ribbon é um projeto de código aberto lançado pela Netflix, cuja principal função é fornecer um algoritmo de balanceamento de carga de software do lado do cliente e conectar os serviços intermediários da Netflix. O componente cliente do Ribbon fornece uma série de itens de configuração completos, como: tempo limite de conexão, repetição, etc. Simplificando, é listar todos os seguintes LoadBalancer (LB: Load Balancer) no arquivo de configuração, e a Faixa de opções ajudará você a conectar essas máquinas automaticamente com base em certas regras (como votação simples, conexão aleatória etc.). Também podemos usar o Ribbon facilmente para implementar um algoritmo de balanceamento de carga personalizado!
O que a Faixa de opções pode fazer?

insira a descrição da imagem aqui

LB, ou Load Balancer, é um aplicativo frequentemente usado em microsserviços ou clusters distribuídos.
Simplificando, o balanceamento de carga é distribuir as solicitações do usuário uniformemente para vários serviços, de modo a obter HA (alta utilização) do sistema.
O software comum de balanceamento de carga inclui Nginx, Lvs e assim por diante.
Tanto o Dubbo quanto o SpringCloud nos fornecem balanceamento de carga, e o algoritmo de balanceamento de carga do SpringCloud pode ser personalizado.
Classificação simples de balanceamento de carga:
LB centralizado
significa utilizar uma facilidade de LB independente entre o provedor de serviço e o consumidor, como o Nginx (servidor proxy reverso), que é responsável por encaminhar a solicitação de acesso ao provedor de serviço por meio de uma determinada praça estratégica!
O LB baseado em processo
integra a lógica do LB ao consumidor.O consumidor aprende quais endereços estão disponíveis no registro de serviço e, em seguida, seleciona um servidor adequado a partir desses endereços.
Ribbon pertence ao LB em processo, é apenas uma biblioteca de classes, integrada no processo do consumidor, e o consumidor obtém o endereço do provedor de serviços através dela!

4.2. Integre a fita ao cliente consumidor

Introduzir dependências de faixa de opções e dependências Eureka no arquivo 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>

Adicionar anotações Eureka à classe de inicialização

//加入Eureka服务
@EnableEurekaClient

Configure as dependências do Eureka no arquivo de configuração

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

Adicionar anotações da faixa de opções à classe de configuração de configuração

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 o caminho de acesso do provedor em DeptConsumerController:

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

Crie projetos 8002 e 8003 sucessivamente, seguindo 8001, e crie bancos de dados correspondentes a 8002 e 8003

insira a descrição da imagem aqui

Modifique o método de conexão, modifique a descrição do serviço no arquivo de configuração, altere o atributo instance-id para springcloud-provider-dept8003 e 8002 e altere o nome da fonte de dados na tabela dept_test para db02 e db03

Iniciar o projeto em sequência

insira a descrição da imagem aqui

Exibir o registro do serviço Eureka

insira a descrição da imagem aqui

Acesse a interface da lista para verificar de qual serviço a faixa de opções obtém dados

insira a descrição da imagem aqui

A atualização fica assim:

insira a descrição da imagem aqui

O uso da fita para obter o balanceamento de carga foi implementado usando

4.3. Algoritmo de balanceamento de carga de ribbon personalizado:

No passado, a faixa de opções usava o algoritmo de pesquisa e mudava para o algoritmo para usar um serviço cinco vezes e depois usar o próximo serviço

Algoritmo aleatório na faixa de opções: arquivo 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) {
    
    
    }
}

Crie a seguinte pasta fora do diretório inicial

insira a descrição da imagem aqui

RuleConfig se parece com isso:

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();
    }
}

O código MyRibbonRule é o seguinte:

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) {
    
    
    }
}

Adicionar à classe de inicialização

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("启动成功!!");
    }
}

Projeto de inicialização:

Atualize cinco vezes para entrar no próximo serviço

insira a descrição da imagem aqui

5. Fingir: balanceamento de carga (baseado no servidor)

5.1 Introdução ao fingimento

Feign é um cliente Web Service declarativo, que facilita as chamadas entre microsserviços, semelhante a como um controlador chama um serviço. SpringCloud integra Ribbon e Eureka e pode usar Feigin para fornecer um cliente http com balanceamento de carga

Basta criar uma interface e adicionar anotações~

Finja, principalmente a versão da comunidade, todos estão acostumados com programação orientada a interface. Esta é a norma para muitos desenvolvedores. Chame microsserviços para acessar dois métodos

Nome do microsserviço [ribbon]
interface e anotação [feign]
O que o Feign pode fazer?

Feign visa tornar mais fácil escrever clientes Java Http
. Ao usar Ribbon + RestTemplate, o RestTemplate é usado para encapsular solicitações Http para formar um conjunto de métodos de chamada padronizados. No entanto, no desenvolvimento real, como pode haver mais de uma chamada para a dependência do serviço, uma interface geralmente será chamada de vários locais; portanto, geralmente uma classe de cliente é encapsulada para cada microsserviço para agrupar as chamadas desses serviços dependentes. Portanto, Feign fez mais encapsulamento com base nisso e nos ajudará a definir e implementar a definição de interfaces de serviço dependentes. Na implementação de Feign, precisamos apenas criar uma interface e usar anotações para configurá-la (semelhante às anotações anteriores do Mapper são marcados na interface Dao e agora uma interface de microsserviço é marcada com uma anotação Feign), e a ligação da interface ao provedor de serviços pode ser concluída, o que simplifica o desenvolvimento do encapsulamento automático do cliente de chamada de serviço ao usar o Spring Cloud Ribbon.
Feign integra o Ribbon por padrão

Ribbon é usado para manter as informações da lista de serviço do MicroServiceCloud-Dept, e o balanceamento de carga do cliente é realizado por meio de polling. Ao contrário do Ribbon, Feign precisa apenas definir a interface de ligação do serviço e usar um método declarativo, que é elegante e simples uma chamada de serviço

1. Crie um novo projeto de simulação

insira a descrição da imagem aqui

2. Introduzir dependência simulada na aula de inicialização
<?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. Classe de configuração
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. Chamada de atendimento ao 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. Aula de inicialização
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 o feign foi introduzido no springCloud-api, e a interface de serviço foi escrita

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

7. Interface do 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. Comece em sequência

insira a descrição da imagem aqui

9. Obtido com sucesso:

insira a descrição da imagem aqui

6. Hystrix: fusível de serviço

Problemas enfrentados por sistemas distribuídos

Os aplicativos em arquiteturas distribuídas complexas têm dezenas de dependências, cada uma das quais inevitavelmente falhará em algum momento!

6.1 Avalanche de Serviço

Ao chamar entre vários microsserviços, suponha que o microsserviço A chame o microsserviço B e o microsserviço C, e o microsserviço B e o microsserviço C chamem outros microsserviços. Isso é chamado de "fan-out". Se o fan-out Se o tempo de resposta da chamada de um microsserviço no link for muito longo, ou se estiver indisponível, a chamada para o microsserviço A irá ocupar cada vez mais recursos do sistema, causando o travamento do sistema, o chamado "efeito avalanche".

insira a descrição da imagem aqui

Para aplicativos de alto tráfego, uma única dependência de back-end pode fazer com que todos os recursos em todos os servidores fiquem saturados em dezenas de segundos. Pior que falha, esses aplicativos também podem causar aumento da latência entre serviços, sobrecarregando filas de backup, threads e outros recursos do sistema, levando a mais falhas em cascata em todo o sistema, o que representa a necessidade de monitorar falhas e latência Isolamento e gerenciamento para que a falha de uma única dependência não afeta todo o aplicativo ou a operação do sistema.

Precisamos, abandonar o carro para salvar bonitão!

6.2 O que é Hystrix?

Hystrix é uma biblioteca de código aberto usada para lidar com atraso e tolerância a falhas de sistemas distribuídos. Em sistemas distribuídos, muitas dependências inevitavelmente falharão ao chamar, como timeouts, exceções, etc. Hystrix pode garantir isso no caso de uma dependência problema, não causará a falha de todo o serviço do sistema, evitará falhas em cascata e melhorará a resiliência do sistema distribuído.

O próprio "disjuntor" é um dispositivo de comutação. Quando uma unidade de serviço falha, através do monitoramento de falha do disjuntor (semelhante a um fusível queimado), uma resposta alternativa esperada e processável (FallBack) é retornada ao chamador. , em vez disso de esperar muito tempo ou lançar uma exceção que não pode ser tratada pelo método chamador, de forma a garantir que a thread do chamador do serviço não fique ocupada por muito tempo e desnecessária, evitando assim a propagação de falhas no distribuído sistema. Até mesmo uma avalanche.

insira a descrição da imagem aqui

6.3 O que o Hystrix pode fazer?

Degradação do serviço
Interrupção do circuito do serviço
Limitação do serviço
Monitoramento quase em tempo real
...
Quando tudo está normal, o fluxo de solicitação pode ser o seguinte:

insira a descrição da imagem aqui

Quando há um serviço potencialmente bloqueador entre muitos sistemas de back-end, ele pode bloquear toda a solicitação do usuário:

insira a descrição da imagem aqui

Com tráfego de alto volume, o potencial de uma única dependência de back-end satura todos os recursos em todos os servidores em segundos.

Cada ponto em seu aplicativo em que uma solicitação de rede pode ser feita por meio da rede ou de uma biblioteca cliente é uma fonte de falha potencial. Pior do que falhar, esses aplicativos também podem causar maior latência entre os serviços, fazendo backup de filas, threads e outros recursos do sistema, causando mais falhas em cascata nos sistemas.

insira a descrição da imagem aqui

A arquitetura mostrada no diagrama acima muda de forma semelhante ao diagrama abaixo quando o Hystrix é usado para agrupar cada dependência subjacente. Cada dependência é isolada uma da outra, limitada nos recursos que pode preencher quando ocorre um atraso e envolvida em uma lógica de fallback que determina o que fazer em resposta a qualquer tipo de falha em uma dependência:

insira a descrição da imagem aqui

Informações oficiais do site: https://github.com/Netflix/Hystrix/wiki

6.4 Disjuntor de serviço

O que é um fusível de serviço
O mecanismo de fusível é um mecanismo de proteção de link de microsserviço que vence o efeito avalanche.

Quando um microsserviço do link fan-out estiver indisponível ou o tempo de resposta for muito longo, o serviço será degradado e, em seguida, a chamada do microsserviço do nó será interrompida e as informações de resposta incorretas serão retornadas rapidamente. Após detectar que a resposta da chamada do microsserviço do nó está normal, o link da chamada é restaurado. Na estrutura SpringCloud, o mecanismo de fusível é implementado por meio do Hystrix. O Hystrix monitorará o status das chamadas entre os microsserviços. Quando a chamada com falha atingir um determinado limite, o padrão é 20 falhas de chamada em 5 segundos e o mecanismo de fusível será ativado. A anotação do mecanismo de fusível é: @HystrixCommand.

6.5 O disjuntor de serviço resolve os seguintes problemas:

Quando o objeto dependente é instável, pode atingir o objetivo de falha rápida;
após a falha rápida, pode testar dinamicamente se o objeto dependente é restaurado de acordo com um determinado algoritmo.

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

insira a descrição da imagem aqui

2. Adicione o serviço de fusão de serviço no arquivo 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. Adicione a classe de inicialização, anotação de fusível de serviço
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. O controlador é adicionado e o conteúdo relacionado após o serviço ser interrompido
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. Inicie o projeto

insira a descrição da imagem aqui

Acessar dados inexistentes:

insira a descrição da imagem aqui

Lançar uma exceção fez com que o serviço se fundisse

Portanto, para evitar o relatório de erros de todo o aplicativo ou página da Web devido a uma exceção ou erro em segundo plano de um microsserviço, é necessário usar um fusível

6.6. Rebaixamento do serviço
1. O que é downgrade de serviço?

A degradação do serviço refere-se a quando a pressão no servidor aumenta acentuadamente, de acordo com a situação real do negócio e do tráfego, alguns serviços e páginas não são estrategicamente processados, ou manipulados de forma simples, de modo a liberar recursos do servidor para garantir o funcionamento normal do o core business ou Operar com eficiência. Para ser franco, é abrir mão dos recursos do sistema para serviços de alta prioridade o máximo possível.

Os recursos são limitados, mas os pedidos são ilimitados. Se o serviço não for rebaixado durante o período de pico de concorrência, por um lado, isso afetará definitivamente o desempenho do serviço geral e, em casos graves, poderá causar paralisações e indisponibilidade de alguns serviços importantes. Portanto, geralmente durante o período de pico, para garantir a disponibilidade de serviços funcionais principais, alguns serviços devem ser rebaixados. Por exemplo, durante o evento Double 11, todos os serviços não relacionados a transações serão rebaixados, como visualização de Ant Forest, visualização de pedidos históricos e assim por diante.

Para quais cenários os downgrades de serviço são usados ​​principalmente? Quando a carga geral de toda a arquitetura de microsserviços excede o limite superior predefinido ou espera-se que o próximo tráfego exceda o limite predefinido, a fim de garantir que serviços importantes ou básicos possam ser executados normalmente, algum uso sem importância ou não urgente ou suspensão atrasada de uso do serviço por um serviço ou tarefa.

A forma de downgrade pode ser determinada de acordo com o negócio. Você pode atrasar o serviço, como atrasar a adição de pontos ao usuário, basta colocar em um cache, e esperar o serviço estabilizar antes de executá-lo; ou fechar o serviço dentro um intervalo granular, como fechar a recomendação de artigos relacionados.

insira a descrição da imagem aqui

Como pode ser visto na figura acima, quando o número de visitas ao serviço A aumenta acentuadamente em um determinado período de tempo, enquanto o número de visitas aos serviços B e C é menor, a fim de aliviar a pressão sobre o serviço A, B e C precisa fechar temporariamente algumas funções de serviço neste momento para suportar o ônus. Parte do serviço de A, para compartilhar a pressão por A, é chamada de degradação de serviço.

Questões a serem consideradas na degradação do serviço
1) Quais serviços são serviços essenciais e quais serviços não são essenciais
2) Quais serviços podem suportar degradação, quais serviços não podem suportar degradação, qual é a estratégia de degradação
3) Existe algum negócio mais complexo além do serviço degradação Saia da cena, qual é a estratégia?
Classificação automática de downgrade
1) Downgrade de tempo limite: principalmente configurar o período de tempo limite, o número de tentativas de tempo limite e o mecanismo e usar o mecanismo assíncrono para detectar a resposta

2) O número de falhas é rebaixado: principalmente para algumas APIs instáveis. Quando o número de chamadas com falha atingir um determinado limite, ele será rebaixado automaticamente. Também é necessário usar um mecanismo assíncrono para detectar a resposta

3) Downgrade de falha: Por exemplo, se o serviço remoto a ser chamado travar (falha de rede, falha de DNS, serviço http retornar um código de status incorreto, serviço rpc lançar uma exceção), ele poderá ser rebaixado diretamente. As soluções pós-downgrade incluem: valor padrão (por exemplo, se o serviço de inventário estiver inativo, retorne ao local padrão), dados de bolso (por exemplo, se o anúncio estiver inativo, retorne a algumas páginas estáticas preparadas com antecedência), cache (alguns dados em cache armazenados temporariamente antes)

4) Rebaixamento do limite atual: Ao eliminar rapidamente ou adquirir alguns produtos restritos, o sistema pode travar devido ao excesso de tráfego neste momento. Neste momento, a limitação de tráfego será usada para limitar o tráfego. Quando o limite do limite de tráfego for atingido, as solicitações subsequentes serão rebaixadas; a solução após o rebaixamento pode ser: página de fila (direcionar o usuário para a página de fila e aguardar um pouco para tentar novamente), fora de estoque (informar diretamente ao usuário que o estoque acabou), página de erro (se o evento for muito popular, aguarde um pouco) Tente novamente).

2. Implementação simples

Adicionar classe de implementação ao serviço em springCloud-api

insira a descrição da imagem aqui

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;
            }
        };
    }
}

Adicionar método de downgrade de serviço em 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);
}

Habilitar downgrade de serviço no lado do 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 A diferença entre fusível de serviço e downgrade

Fusão de serviço —> servidor: um tempo limite de serviço ou anormalidade, causando fusão~, semelhante à degradação de serviço de fusível (autofusão)
—> cliente: considerando a carga geral de solicitação do site, quando um serviço está sendo fundido ou encerrado, o serviço será não é mais chamado. Neste momento, do lado do cliente, podemos preparar um FallBackFactory e retornar um valor padrão (default value). Isso levará a um declínio no serviço geral, mas pode ser usado de qualquer maneira, o que é melhor do que desligar diretamente.
Os motivos de acionamento são diferentes. A fusão de serviço geralmente é causada por uma falha de serviço (serviço downstream), e a degradação do serviço é geralmente considerada a partir da carga geral; o nível de metas de gerenciamento é diferente. A fusão é, na verdade, um processo em nível de estrutura. Cada micro Todos os serviços são necessários (sem hierarquia) e o downgrade geralmente precisa ser hierárquico para os negócios (por exemplo, o downgrade geralmente começa no serviço mais periférico)
. controlador/ou downgrade automático), a fusão é geralmente chamada de autofusão.
Fusível, downgrade, limite de corrente:

Limitação atual: limite a quantidade de acesso de solicitação simultânea, se exceder o limite, será rejeitado;

Degradação: priorize serviços, sacrifique serviços não essenciais (indisponíveis) e garanta a estabilidade dos serviços principais; considere a carga geral;

Fuse: A falha de serviços downstream dependentes aciona um fusível para evitar travar o sistema; o sistema executa e recupera automaticamente

6.8 Monitoramento de Fluxo do Painel

Crie um novo módulo springcloud-consumer-hystrix-dashboard

insira a descrição da imagem aqui

Adicionar dependência do painel ao arquivo 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>

Arquivo de configuração:

server:
  port: 9001

Classe de inicialização:

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("启动成功!!");
    }

}

classe de inicialização springCloud-provider-dept-hystrix-8001 adicionada

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 e preencha os serviços de monitoramento relevantes

insira a descrição da imagem aqui
Ligue para o serviço, você pode ver o monitoramento em tempo real

insira a descrição da imagem aqui

7. Gateway de roteamento Zuul

7.1, o que é Zuul

O Zuul inclui duas funções principais de roteamento e filtragem de solicitações:
a função de roteamento é responsável por encaminhar solicitações externas para instâncias de microsserviços específicas, que é a base para realizar uma entrada unificada para acesso externo, enquanto a função de filtro é responsável pelo processamento de solicitações Intervenção no processo de processamento é a base para a implementação de funções como verificação de solicitação e agregação de serviço. Zuul e Eureka estão integrados, e o próprio Zuu é registrado como um aplicativo no gerenciamento de serviços Eureka e, ao mesmo tempo, outras notícias de microsserviços são obtidas de Eureka, ou seja, o acesso futuro aos microsserviços é obtido após o salto pelo Zuul.

Observação: o serviço Zuul será eventualmente registrado no Eureka

Forneça: proxy + roteamento + filtragem três funções principais

7.2 O que Zuul pode fazer


Documentação do site oficial do filtro de roteamento
=> https://github.com/Netflix/zuul

7.3. Por que construir o Zuul

Às vezes, o volume e a variedade do tráfego Netflix.API podem causar problemas de produção rapidamente e sem aviso. Precisamos de um sistema que nos permita
mudar rapidamente o comportamento em resposta a essas situações.

O Zuul usa uma variedade de tipos diferentes de filtros, que nos permitem aplicar funções de forma rápida e flexível aos serviços de ponta. Esses filtros
nos ajudam a realizar as seguintes funções:

Autenticação e segurança identifica os requisitos de autenticação para cada recurso e rejeita solicitações que não atendem aos requisitos.
Insights e monitoramento Geração de dados e estatísticas significativas na borda para nos fornecer uma imagem precisa da produção.
O roteamento dinâmico roteia dinamicamente as solicitações para diferentes clusters de back-end conforme necessário.
O teste de estresse aumenta gradualmente o tráfego para o cluster para avaliar o desempenho.
Descarte de Carga - Reduz a capacidade alocada para cada tipo de solicitação e elimina as solicitações que excedem o limite.
Manipulação de resposta estática - Construa algumas respostas diretamente na borda. Em vez de encaminhá-lo para o cluster interno
Solicitações de rotas elásticas multi-regionais entre regiões da AWS para diversificar nosso uso de ELB e aproximar nossos pontos fortes de nossos membros Para mais detalhes: Como usamos o Zuul no Netfio

7.4. Componentes Zuul

zuul-core–zuul core library, que contém as principais funções de compilação e execução de filtros
zuul-simple-webapp–zuul exemplo de aplicação web, mostrando como usar zuul-core para construir aplicações
zuul-netflix–lib pacote, que integra outros NetflixOSS componentes Adicione-o ao Zuul, por exemplo, use a área funcional para inserir o processamento da solicitação de roteamento
zuul-netflix-webapp-webapp, que encapsula zuul-core e zuul-netflix em um pacote de projeto webapp simples

7.5. Construção do projeto de gateway de roteamento Zuul

Criar projeto maven springcloud/springcloud-zuul-9527

Importe todas as dependências do projeto springcloud-consumer-hystrix-dashboard e adicione as dependências do Zuul
para criar subprojetos:

insira a descrição da imagem aqui

arquivo de configuração

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

arquivo 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>

Classe de inicialização:

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("启动成功!!!");
    }

}

Inicie o serviço para teste

insira a descrição da imagem aqui

Visualize C:\Windows\System32\drivers\etc\hosts para simular o gateway zuul

127.0.0.1       activate.navicat.com

O acesso antes de configurar o zuul é o seguinte:

insira a descrição da imagem aqui

Após adicionar a configuração do zuul, o acesso é o seguinte:

insira a descrição da imagem aqui

Vemos que o nome do microsserviço é substituído e oculto, substituído por nosso nome de microsserviço personalizado mydept, e o prefixo haust é adicionado ao mesmo tempo, para que o acesso ao ventilador de roteamento seja criptografado!

Para obter detalhes, consulte o componente zuul da comunidade chinesa springcloud: https://www.springcloud.cc/spring-cloud-greenwich.html#_router_and_filter_zuul

8. Configuração distribuída do Spring Cloud Config

Dalston.LANÇAMENTO

O Spring Cloud Config fornece suporte de servidor e cliente para configuração externa em sistemas distribuídos. Usando o Config Server, você pode gerenciar propriedades externas de aplicativos em todos os ambientes. O mapeamento conceitual no cliente e no servidor é o mesmo das abstrações Spring Environment e PropertySource, portanto, eles se adaptam bem aos aplicativos Spring, mas podem ser usados ​​com qualquer aplicativo em execução em qualquer idioma. À medida que o aplicativo passa pelo processo de implantação, do desenvolvedor ao teste e produção, você pode gerenciar a configuração entre esses ambientes e garantir que o aplicativo tenha tudo o que precisa para ser executado durante a migração. A implementação padrão do back-end de armazenamento do servidor usa git, portanto, suporta facilmente versões marcadas de ambientes de configuração, bem como acesso a várias ferramentas para gerenciamento de conteúdo. É fácil adicionar implementações alternativas e conectá-las usando a configuração do Spring.

Visão Geral
dos Sistemas Distribuídos – Problemas do Arquivo de Configuração

Microsserviços significa dividir o negócio em um único aplicativo em sub-serviços. A granularidade de cada serviço é relativamente pequena, então haverá um grande número de serviços no sistema. Como cada serviço requer as informações de configuração necessárias para executar, , o recurso de gerenciamento de configuração dinâmica é essencial. O Spring cloud fornece o configServer para resolver esse problema. Cada um de nossos microsserviços carrega um application.yml. É uma dor de cabeça modificar centenas de arquivos de configuração!

O que é o centro de configuração distribuído SpringCloud config?

[Falha na transferência da imagem do link externo, o site de origem pode ter um mecanismo anti-leeching, é recomendável salvar a imagem e carregá-la diretamente (img-pE2ByaTt-1683193762693)(\49.png)]

O spring cloud config fornece suporte externo centralizado para microsserviços na arquitetura de microsserviços, e o servidor de configuração fornece uma configuração externa centralizada para todos os links de diferentes aplicativos de microsserviços.

A configuração do spring cloud é dividida em duas partes: servidor e cliente.

O servidor, também conhecido como centro de configuração distribuído, é um aplicativo de microsserviço independente usado para se conectar ao servidor de configuração e fornecer interfaces de acesso para o cliente obter informações de configuração, criptografar e descriptografar informações.

O cliente gerencia os recursos do aplicativo e o conteúdo de configuração relacionado aos negócios por meio do centro de configuração designado e obtém e carrega as informações de configuração do centro de configuração na inicialização. Por padrão, o servidor de configuração usa git para armazenar informações de configuração, o que é útil para o gerenciamento de versão da configuração do ambiente. E o conteúdo da configuração pode ser facilmente gerenciado e acessado por meio da ferramenta cliente git.

O que o centro de configuração distribuída Spring Cloud config pode fazer?

Gerenciamento centralizado de arquivos de configuração
Ambientes diferentes, configurações diferentes, atualizações de configuração dinâmica e implantação em ambientes diferentes, como /dev /test /prod /beta /release
ajustam dinamicamente a configuração durante a operação, não é mais necessário gravar em cada máquina de implantação de serviço Configuração arquivo, o serviço irá puxar e configurar suas próprias informações do centro de configuração.
Quando a configuração muda, o serviço pode sentir a mudança de configuração e aplicar a nova configuração sem reiniciar.
Expor as informações de configuração para
spring cloud na forma de uma interface REST .config Centro de configuração distribuído e integração com o GitHub

Já o spring cloud config usa o git para armazenar arquivos de configuração por padrão (existem outras formas, como SVN autossustentável e arquivos locais), mas o git é o mais recomendado, e usa a forma de acesso http/https.

ambiente de configuração springcloud criar configuração
código de registro conta na nuvem https://gitee.com/. Você pode fazer login via qq wechat

Crie um novo warehouse springcloud-config, defina-o como público e selecione java para idioma e modelo. Licença de código aberto GPL-3.0, copie o endereço do túnel SSH do warehouse atual após a criação do warehouse

Crie uma nova pasta no computador, use a ferramenta GitBash para executar o endereço SSH copiado pelo git clone springcloud-config e puxe o conteúdo do warehouse. Após puxar, selecione sim, porque as permissões não existem, você precisa configurar o Git atual

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

1. O primeiro passo é criar um warehouse no git

insira a descrição da imagem aqui

2. Extrair informações do armazém

Comandos comuns

# 显示当前的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]

puxar código

insira a descrição da imagem aqui

Neste ponto, o código remoto foi obtido
insira a descrição da imagem aqui

Crie o arquivo application.ynl e envie-o para o depósito

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

Submetido com sucesso:

insira a descrição da imagem aqui

Estudo de caso de introdução

Crie um novo subprojeto:

insira a descrição da imagem aqui

O arquivo pom fica assim:

<?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 a aula, abra a anotação de configuração do serviço

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("启动成功!!");
    }
}

arquivo de configuração

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

Uma conexão privada requer um nome de usuário e senha

Erro:

A autenticação é necessária, mas nenhum CredentialsProvider foi registrado

acesse da seguinte forma

http://localhost:2233/application-dev.yml

insira a descrição da imagem aqui

http://localhost:2233/application-test.yml

insira a descrição da imagem aqui

Adicione o arquivo de configuração config-cilent.yml no warehouse

O conteúdo é o seguinte:

#启动环境选择的配置
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/

Envie o arquivo para o warehouse remoto

insira a descrição da imagem aqui

O comando git é o seguinte:

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

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

git status 查看状态

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

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

Acho que você gosta

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