springcloud(未学习完)

代码git地址

一.springcloud简介

在这里插入图片描述
springcloud:多种微服务架构落地技术的集合体;
京东技术架构:
在这里插入图片描述
阿里技术架构
在这里插入图片描述

springcloud涵盖的技术:
在这里插入图片描述

核心技术:
在这里插入图片描述

二.版本选择

1.查询版本
springcloud版本
在这里插入图片描述
在这里插入图片描述

cloud和boot详细的版本对应
在这里插入图片描述
json转换工具查看

{
    "git": {
        "commit": {
            "time": "2020-03-19T13:43:47Z",
            "id": "6a8d5ce"
        },
        "branch": "6a8d5ce9a63e30db3fa1c23c64a6b7cef2072c71"
    },
    "build": {
        "version": "0.0.1-SNAPSHOT",
        "artifact": "start-site",
        "name": "start.spring.io website",
        "versions": {
            "initializr": "0.9.0.BUILD-SNAPSHOT",
            "spring-boot": "2.2.5.RELEASE"
        },
        "group": "io.spring.start",
        "time": "2020-03-19T13:45:29.062Z"
    },
    "bom-ranges": {
        "azure": {
            "2.0.10": "Spring Boot >=2.0.0.RELEASE and <2.1.0.RELEASE",
            "2.1.7": "Spring Boot >=2.1.0.RELEASE and <2.2.0.M1",
            "2.2.0": "Spring Boot >=2.2.0.M1"
        },
        "codecentric-spring-boot-admin": {
            "2.0.6": "Spring Boot >=2.0.0.M1 and <2.1.0.M1",
            "2.1.6": "Spring Boot >=2.1.0.M1 and <2.2.0.M1",
            "2.2.1": "Spring Boot >=2.2.0.M1"
        },
        "spring-cloud": {
            "Finchley.M2": "Spring Boot >=2.0.0.M3 and <2.0.0.M5",
            "Finchley.M3": "Spring Boot >=2.0.0.M5 and <=2.0.0.M5",
            "Finchley.M4": "Spring Boot >=2.0.0.M6 and <=2.0.0.M6",
            "Finchley.M5": "Spring Boot >=2.0.0.M7 and <=2.0.0.M7",
            "Finchley.M6": "Spring Boot >=2.0.0.RC1 and <=2.0.0.RC1",
            "Finchley.M7": "Spring Boot >=2.0.0.RC2 and <=2.0.0.RC2",
            "Finchley.M9": "Spring Boot >=2.0.0.RELEASE and <=2.0.0.RELEASE",
            "Finchley.RC1": "Spring Boot >=2.0.1.RELEASE and <2.0.2.RELEASE",
            "Finchley.RC2": "Spring Boot >=2.0.2.RELEASE and <2.0.3.RELEASE",
            "Finchley.SR4": "Spring Boot >=2.0.3.RELEASE and <2.0.999.BUILD-SNAPSHOT",
            "Finchley.BUILD-SNAPSHOT": "Spring Boot >=2.0.999.BUILD-SNAPSHOT and <2.1.0.M3",
            "Greenwich.M1": "Spring Boot >=2.1.0.M3 and <2.1.0.RELEASE",
            "Greenwich.SR5": "Spring Boot >=2.1.0.RELEASE and <2.1.14.BUILD-SNAPSHOT",
            "Greenwich.BUILD-SNAPSHOT": "Spring Boot >=2.1.14.BUILD-SNAPSHOT and <2.2.0.M4",
            "Hoxton.SR3": "Spring Boot >=2.2.0.M4 and <2.3.0.BUILD-SNAPSHOT",
            "Hoxton.BUILD-SNAPSHOT": "Spring Boot >=2.3.0.BUILD-SNAPSHOT"
        },
        "spring-cloud-alibaba": {
            "2.2.0.RELEASE": "Spring Boot >=2.2.0.RELEASE and <2.3.0.M1"
        },
        "spring-cloud-services": {
            "2.0.3.RELEASE": "Spring Boot >=2.0.0.RELEASE and <2.1.0.RELEASE",
            "2.1.7.RELEASE": "Spring Boot >=2.1.0.RELEASE and <2.2.0.RELEASE",
            "2.2.3.RELEASE": "Spring Boot >=2.2.0.RELEASE and <2.3.0.M1"
        },
        "spring-statemachine": {
            "2.0.0.M4": "Spring Boot >=2.0.0.RC1 and <=2.0.0.RC1",
            "2.0.0.M5": "Spring Boot >=2.0.0.RC2 and <=2.0.0.RC2",
            "2.0.1.RELEASE": "Spring Boot >=2.0.0.RELEASE"
        },
        "vaadin": {
            "10.0.17": "Spring Boot >=2.0.0.M1 and <2.1.0.M1",
            "14.1.20": "Spring Boot >=2.1.0.M1"
        }
    },
    "dependency-ranges": {
        "okta": {
            "1.2.1": "Spring Boot >=2.1.2.RELEASE and <2.2.0.M1",
            "1.4.0": "Spring Boot >=2.2.0.M1"
        },
        "mybatis": {
            "2.0.1": "Spring Boot >=2.0.0.RELEASE and <2.1.0.RELEASE",
            "2.1.2": "Spring Boot >=2.1.0.RELEASE"
        },
        "geode": {
            "1.2.5.RELEASE": "Spring Boot >=2.2.0.M5 and <2.3.0.M1",
            "1.3.0.M2": "Spring Boot >=2.3.0.M1 and <2.3.0.BUILD-SNAPSHOT",
            "1.3.0.BUILD-SNAPSHOT": "Spring Boot >=2.3.0.BUILD-SNAPSHOT"
        },
        "camel": {
            "2.22.4": "Spring Boot >=2.0.0.M1 and <2.1.0.M1",
            "2.24.3": "Spring Boot >=2.1.0.M1 and <2.2.0.M1",
            "3.1.0": "Spring Boot >=2.2.0.M1"
        },
        "solace": {
            "3.1.0": "Spring Boot >=2.1.0.RELEASE and <2.2.0.M1",
            "3.2.0": "Spring Boot >=2.2.0.M1"
        }
    }
}

2.博文选用版本
在这里插入图片描述

三.cloud的停更、升级、替换

在这里插入图片描述
在这里插入图片描述

参考资料
在这里插入图片描述

四.微服务架构编码构建

1.约定》配置》编码
2.新建工程
在这里插入图片描述

在这里插入图片描述
注解生效激活
在这里插入图片描述
编译版本选择
在这里插入图片描述
3.父工程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>

  <groupId>com.cz.springcloud</groupId>
  <artifactId>cloud2020</artifactId>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>cloud-provider-payment8001</module>
  </modules>
  <packaging>pom</packaging>


  <!-- 统一管理jar包版本 -->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <junit.version>4.12</junit.version>
    <log4j.version>1.2.17</log4j.version>
    <lombok.version>1.16.18</lombok.version>
    <mysql.version>5.1.47</mysql.version>
    <druid.version>1.1.16</druid.version>
    <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
  </properties>

  <!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version  -->
  <dependencyManagement>
    <dependencies>
      <!--spring boot 2.2.2-->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.2.2.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <!--spring cloud Hoxton.SR1-->
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR1</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <!--spring cloud alibaba 2.1.0.RELEASE-->
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.1.0.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
      </dependency>
      <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>${druid.version}</version>
      </dependency>
      <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>${mybatis.spring.boot.version}</version>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
      </dependency>
      <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
      </dependency>
      <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
        <optional>true</optional>
      </dependency>
    </dependencies>
  </dependencyManagement>

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

</project>

4.maven中dependencyManagement
通常会在最顶层父项目pom文件中看到 dependencyManagement元素,让所有的子项目引入一个依赖而不用显式的列出版本号。maven会沿着父子项目向上走,找到拥有dependencyManagement元素的项目,使用其中的版本号;
优点在于:实现一处修改,处处修改;且子项目中若引入不同的版本,仅需添加对应的版本号即可;
在这里插入图片描述
5.maven跳过单元测试
在这里插入图片描述

6.rest微服务项目构建
a.建项目
在这里插入图片描述
查看父工程pom文件
在这里插入图片描述
b.改pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.cz.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8001</artifactId>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


    </dependencies>

</project>

c.写yml

server:
  port: 8001


spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://IP地址:端口号/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456

mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.cz.springcloud.entities

d.启动类
在这里插入图片描述
e.业务类
建表

CREATE TABLE `payment` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `serial` varchar(200) DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在这里插入图片描述

@Data
/*全参*/
@AllArgsConstructor
/*空参*/
@NoArgsConstructor
public class Payment  implements Serializable {
    private Long id;
    private String serial;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    private  Integer code;
    private  String message;
    private T data;


    /*数据为空*/
    public CommonResult(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}
/*推荐使用Mapper,少用Repository*/
@Mapper
public interface PaymentDao {
     int create(Payment payment);
     Payment getPaymentById(@Param("id") Long id);

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.cz.springcloud.dao.PaymentDao">
<insert id="create"  parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
    insert into payment (serial) values (#{serial});
</insert>


    <resultMap id="BaseResultMap" type="Payment">
        <id column="id" property="id" jdbcType="BIGINT"></id>
        <id column="serial" property="serial" jdbcType="VARCHAR"></id>
    </resultMap>
    <select id="getPaymentById" parameterType="Long"  resultMap="BaseResultMap">
        select * from payment  where id=#{id};
    </select>


</mapper>
public interface PaymentService {
    int create(Payment payment);
    Payment getPaymentById( Long id);
}
@Service
public class PaymentServiceImpl implements PaymentService {
    @Resource
    private PaymentDao paymentDao;

    @Override
    public int create(Payment payment) {

        return paymentDao.create(payment);
    }

    @Override
    public Payment getPaymentById(Long id) {
        return paymentDao.getPaymentById(id);
    }
}
@RestController
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;
@PostMapping(value = "/payment/create")
    public CommonResult<Payment> create(Payment payment) {

        int result = paymentService.create(payment);
        log.info("插入结果:  "+ result);
        if(result>0){
            return new CommonResult(200,"插入数据成功",result);
        }else {
            return new CommonResult(444,"插入数据失败",null);
        }
    }

@GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id")Long id) {
    Payment payment = paymentService.getPaymentById(id);
    log.info("查询结果:  "+ payment);
    if(payment!=null){
        return new CommonResult(200,"查询数据成功",payment);
    }else {
        return new CommonResult(444,"查询数据失败",null);
    }
}

}

7.热部署
添加依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
   <scope>runtime</scope>
    <optional>true</optional>
</dependency>

在父工程pom文件中添加

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

开启自动构建
在这里插入图片描述
组合键在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重启idea

8.消费者模块
在这里插入图片描述

9.工程重构
重复的部分
在这里插入图片描述
建立公共模块
在这里插入图片描述
MAVEN 执行clean和install操作
在这里插入图片描述

pom文件

<dependency>
    <groupId>com.cz.springcloud</groupId>
    <artifactId>cloud-api-commons</artifactId>
    <version>${project.version}</version>
</dependency>

五.Eureka服务注册与发现

1.服务治理
在传统的rpc远程调用框架中,管理服务与服务之间的依赖关系非常复杂;使用服务治理,实现服务调用,负载均衡,容错等,实现服务注册与发现。
2.服务注册与发现
Eureka采用cs设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册中心。而系统中其他的微服务,使用Eureka的客户端连接到Eureka Server 并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。

在服务注册与发现中,有一个注册中心,当服务器启动时,会把当前服务器的信息,例如通讯地址服务地址等以别名的方式注册到注册中心。另一方面(消费者|服务提供者),以别名的方式去注册中心获取实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架。核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系。在任何RPC远程框架中,都会有一个注册中心(存放服务地址相关信心)

Eureka系统架构
在这里插入图片描述
dubbo系统架构
在这里插入图片描述

在这里插入图片描述

3.单机Eureka构架步骤
新建工程
在这里插入图片描述
引入pom

 <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>com.cz.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

    </dependencies>

yml文件

server:
  port: 7001

eureka:
  instance:
    hostname: localhost  #eureka服务端的实例名字
  client:
    register-with-eureka: false    #表识不向注册中心注册自己
    fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/    #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址

主配置类

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class,args);
    }
}

在这里插入图片描述

注册服务到服务端
8001服务
修改pom文件

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

修改yml
在这里插入图片描述
修改主配置类
在这里插入图片描述
80服务

在这里插入图片描述

4.Eureka集群
集群理论:
在这里插入图片描述
若注册中心只有一个,出现故障,会导致整个服务环境不可用,所以搭建Eureka注册中心集群,实现负载均衡和故障容错。
在这里插入图片描述

集群搭建:
搭建7002服务
在这里插入图片描述
修改映射配置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将订单服务8001微服务发布到eureka集群中
在这里插入图片描述
将80微服务发布到eureka集群中
在这里插入图片描述

8001服务提供者集群
新建8002
在这里插入图片描述

修改controller

@RestController
@Slf4j
public class PaymentController {
    @Value("${server.port}")
    private  String serverPort;
    @Resource
    private PaymentService paymentService;
@PostMapping(value = "/payment/create")
    public CommonResult<Payment> create(@RequestBody Payment payment) {

        int result = paymentService.create(payment);
        log.info("插入结果:  "+ result);
        if(result>0){
            return new CommonResult(200,"插入数据成功,端口号"+serverPort,result);
        }else {
            return new CommonResult(444,"插入数据失败,端口号"+serverPort,null);
        }
    }

@GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
    Payment payment = paymentService.getPaymentById(id);
    log.info("查询结果:  "+ payment);
    if(payment!=null){
        return new CommonResult(200,"查询数据成功,端口号"+serverPort,payment);
    }else {
        return new CommonResult(444,"查询数据失败,端口号"+serverPort,null);
    }
}

}

在这里插入图片描述
80端口访问固定8001端口
在这里插入图片描述
在这里插入图片描述
修改为
在这里插入图片描述

访问在这里插入图片描述
异常在这里插入图片描述
原因:存在多个服务,机器不清楚如何调用

在这里插入图片描述
效果
在这里插入图片描述
在这里插入图片描述
5.actuator微服务信息完善
在这里插入图片描述

主机名称:服务名称修改
在这里插入图片描述
健康检查:
在这里插入图片描述
IP信息显示
在这里插入图片描述

6.服务发现Discovery
对于注册到eureka中的微服务,通过服务发现获取信息;

修改8001
在这里插入图片描述
在这里插入图片描述

 @GetMapping(value = "/payment/discovery")
    public Object discovery() {
        List<String> services = discoveryClient.getServices();
        for (String e : services) {
            log.info(e);
        }
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance s : instances) {
            log.info(s.getServiceId() + "\t" + s.getHost() + "\t" + s.getPort() + "\t" + s.getUri());

        }
        return this.discoveryClient;
    }

7.Eureka自我保护
概述:
保护模式主要是用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其注册列表中的信息,不再删除服务注册表中的数据。
在这里插入图片描述
表示Eureka进入保护模式

在这里插入图片描述
某个时刻某一个微服务不可用,Eureka不会立刻清理,依旧会对微服务的信息进行保存;属于CAP理论中的ap分支

禁止自我保护:(生产环境一般不会禁止)
7001
在这里插入图片描述
启动微服务
在这里插入图片描述

8001
在这里插入图片描述
在这里插入图片描述
关闭8001
在这里插入图片描述
服务超时,没有自我保护机制,服务被剔除
在这里插入图片描述

六.Zookeeper服务注册与发现

1.Eureka停止更新

2.springcloud整合Zookeeper代替Eureka
8004端口

在这里插入图片描述
写pom文件

 <dependencies>

        <dependency>
            <groupId>com.cz.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-zookeeper-discovery -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


    </dependencies>

写yml文件

在这里插入图片描述
写启动类

@SpringBootApplication
/*使用consul或者zookeeper作为注册中心时注册服务*/
@EnableDiscoveryClient
public class PaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8004.class,args);
    }
}

写业务类

@RestController
@Slf4j
public class PaymentController {
    @Value("${server.port}")
    private String serverPort;


    @RequestMapping("/payment/zk")
    public String paymentzk(){
        return "springcloud with zookeeper:"+serverPort+"\t"+ UUID.randomUUID().toString();
    }



}

启动后:
在这里插入图片描述

zookeeper节点为临时节点

80端口
在这里插入图片描述

 <dependencies>

        <dependency>
            <groupId>com.cz.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-zookeeper-discovery -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


    </dependencies>

在这里插入图片描述

@SpringBootApplication
public class OrderZK80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderZK80.class,args);
    }
}
@Configuration
public class ApplicationContextConfig {
    @Bean
    /*赋予RestTemplate负载均衡的能力*/
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

@RestController
@Slf4j
public class OrderController {

   public static final String INVOKE_URL = "http://cloud-provider-payment";


    @Resource
    private RestTemplate restTemplate;

    @GetMapping(value = "/consumer/payment/zk")
    public String paymentInfo() {

       return restTemplate.getForObject(INVOKE_URL+"/payment/zk",String.class);
    }




}

访问
在这里插入图片描述

七.Consul服务注册与发现

1.概述
consul
consul中文

consul分布式服务发现与配置管理系统,GO语言开发
consul提供一种完整的服务网络解决方案
提供微服务系统中的服务治理、配置中心、控制总线…

作用:
服务发现:提供http和dns两种发现方式
健康监测:
kv存储
多数据中心
可视化的web界面

2.安装consul
docker安装consul
3.使用consul
8006端口
在这里插入图片描述
pom

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-consul-discovery -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>com.cz.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>



    </dependencies>

yml
在这里插入图片描述
主启动类

@SpringBootApplication
public class PaymentMain8006 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8006.class,args);
    }
}

业务类

@RestController@Slf4j
public class PaymentController {
    @Value("${server.port}")
    private String serverPort;


    @RequestMapping("/payment/consul")
    public String paymentInfo(){
        return "springcloud with consul:"+serverPort+"\t"+ UUID.randomUUID().toString();
    }
}

访问
在这里插入图片描述
在这里插入图片描述

80端口
在这里插入图片描述
在这里插入图片描述

问题需要解决:
访问在这里插入图片描述
在这里插入图片描述

4.eureka、zookeeper、consul异同
CAP理论
c 强一致性 a 可用性 p 分区容错性

eureka 符合ap
consul、zookeeper 符合cp

八.Ribbon负载均衡服务调度

1.概述
基于Netflix Ribbon实现的一套客户端负载均衡的工具
在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动帮助你基于某种规则(简单轮询、随机连接)去连接这些机器。

ribbon官网
在这里插入图片描述

2.作用:
负载均衡:
将用户的请求分发到多个服务上,达到系统的高可用;
(Nginx 服务器负载均衡,客户端所有请求会交给nginx,由nginx实现转发请求;
Ribbon本地负载均衡,在调用微服务接口时,会在注册中心获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术)
集中式负载均衡:即在服务的消费方和提供方之间使用独立的负载均衡设备(硬件F5 软件nginx),有设施负责把请求通过某种策略转发到服务的提供方
进程内负载均衡:将负载均衡逻辑集成到消费方,消费方通过注册中心获取哪些地址可用,然后从地址中选择一个合适的服务器。(Ribbon)

3.架构说明:
在这里插入图片描述
Ribbon工作时:
第一步 选择Eureka Server,优先选择在同一个区域,负载较少的server
第二步 根据用户指定的策略,从server服务注册列表选取一个地址。
Ribbon提供多种策略,包含轮询、随机、根据响应时间加权

4.使用:

在这里插入图片描述

RestTemplate
api
getForObject() 返回对象为响应体中数据转化成的对象,可理解为Json
getForEntity() 返回对象为ResponseEntity对象,包含响应中的一些重要信息,比如响应头、响应状态码、响应体
postForObject()
postForObject()

在这里插入图片描述
访问
在这里插入图片描述

5.Ribbon核心组件IRule:
IRule:根据特定的算法,从服务列表中选取一个要访问的对象
在这里插入图片描述
RoundRobinRule 轮询
RandomRule 随机
RetryRule 先按照RoundRobinRule 策略获取服务,若失败则在指定的时间内重试
WeightedResponseTimeRule 对RoundRobinRule 进行扩展,响应速度越快的服务选择 权重越大,越容易被选择
BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择并发量最小的服务
AvailabilityFilteringRule 先过滤故障实例,然后选择并发量较小的服务
ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和可用性选择服务器

替换负载均衡算法步骤:
修改80端口
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
需要新建一个包
在这里插入图片描述

@Configuration
public class MySelfRule {

    @Bean
    public IRule myRule(){
        return new RandomRule();//定义为随机
    }
}

在这里插入图片描述

6.Ribbon负载均衡算法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
源码:
RoundRobinRule

public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            log.warn("no load balancer");
            return null;
        } else {
            Server server = null;
            int count = 0;

            while(true) {
                if (server == null && count++ < 10) {
                    List<Server> reachableServers = lb.getReachableServers();
                    List<Server> allServers = lb.getAllServers();
                    int upCount = reachableServers.size();
                    int serverCount = allServers.size();
                    if (upCount != 0 && serverCount != 0) {
                        int nextServerIndex = this.incrementAndGetModulo(serverCount);
                        server = (Server)allServers.get(nextServerIndex);
                        if (server == null) {
                            Thread.yield();
                        } else {
                            if (server.isAlive() && server.isReadyToServe()) {
                                return server;
                            }

                            server = null;
                        }
                        continue;
                    }

                    log.warn("No up servers available from load balancer: " + lb);
                    return null;
                }

                if (count >= 10) {
                    log.warn("No available alive servers after 10 tries from load balancer: " + lb);
                }

                return server;
            }
        }
    }

自定义负载均衡算法:
在这里插入图片描述
在这里插入图片描述


public interface LoadBalancer {
     //收集服务器总共有多少台能够提供服务的机器,并放到list里面
    ServiceInstance instances(List<ServiceInstance> serviceInstances);

}

@Component
public class MyLB implements LoadBalancer {
    private AtomicInteger atomicInteger=new AtomicInteger(0);

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

        return serviceInstances.get(index);
    }

    public final int getAndIncrement(){
        int current;
        int next;
        do{
            current=this.atomicInteger.get();
            next=current>=Integer.MAX_VALUE?0:current+1;
        }
        while (!this.atomicInteger.compareAndSet(current,next));
        System.out.println("访问次数next值:"+next);
        return next;
    }
}
@RestController
@Slf4j
public class OrderController {
   // public static  final String PAYMENT_URL="http://localhost:8001";
   public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";


    @Resource
    private RestTemplate restTemplate;

    @Resource
    private LoadBalancer loadBalancer;
    @Resource
    private DiscoveryClient discoveryClient;

    @GetMapping(value = "/consumer/payment/create")
    public CommonResult<Payment> create( Payment payment) {

       return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
    }

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {

            return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);

    }

    @GetMapping(value = "/consumer/payment/getForEntity/{id}")
    public CommonResult<Payment> getForEntity(@PathVariable("id") Long id) {

        ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
        if(entity.getStatusCode().is2xxSuccessful()){
            return entity.getBody();
        }

        return new CommonResult<>(444,"操作失败");
    }
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB(){
    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    if(instances==null||instances.size()<=0){
        return  null;
    }
    ServiceInstance serviceInstance = loadBalancer.instances(instances);
    URI uri = serviceInstance.getUri();
    return restTemplate.getForObject(uri+"/payment/lb",String.class);
}
}

访问:
在这里插入图片描述
在这里插入图片描述

九.OpenFeign服务接口调用

1.概述
(Feign被弃用)
OpenFeign
在这里插入图片描述
在这里插入图片描述

2.作用
在这里插入图片描述
在这里插入图片描述
总结:
OpenFeign 定义服务绑定接口,添加注解即可实现负载均衡服务调用

3.使用(微服务调用接口+@FeignClient)
在这里插入图片描述
pom

  <!--openfeign-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.cz.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

yml

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

主启动类

@SpringBootApplication
@EnableFeignClients
public class OrderFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignMain80.class,args);
    }
}

业务类

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id);
}

@RestController
public class OrderFeignController {

    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        return paymentFeignService.getPaymentById(id);
    }
}

访问
在这里插入图片描述

4.OpenFeign超时控制
8001写暂停程序

/*暂停程序*/
    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout(){
        try { TimeUnit.SECONDS.sleep(3); }catch (Exception e) {e.printStackTrace();}
        return serverPort;
    }

80端口

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id);

    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout();
}

@RestController
public class OrderFeignController {

    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        return paymentFeignService.getPaymentById(id);
    }
    @GetMapping(value = "/consumer/payment/feign/timeout")
    public String paymentFeignTimeout(){
        /*openfeign-ribbon,客户端默认等待1秒钟*/
        return paymentFeignService.paymentFeignTimeout();
    }
}

访问http://127.0.0.1/consumer/payment/feign/timeout
在这里插入图片描述
在这里插入图片描述

解决方案:
yml中添加

#设置feign客户端超时时间(openfeign默认支持ribbon)
ribbon:
  #建立连接所用的时间,适合网络状况正常的情况下,两端连接所用时间
  ReadTimeout:  5000
  #建立连接后从服务器读取到可用资源的时间
  ConnectTimeout: 5000

在这里插入图片描述
在这里插入图片描述

4.OpenFeign日志打印功能
日志级别:
NONE 默认不显示任何日志
BASIC 仅记录请求方法、url、响应状态码、执行时间
HEADERS 除了BASIC中定义的信息,还有请求和响应的头信息
FULL 除了Headers中定义的信息之外,包含请求和响应的正文和元数据
在这里插入图片描述

使用:
在这里插入图片描述
配置bean

@Configuration
public class FeignConfig {

    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

yml

logging:
  level:
    #监控的接口
    com.cz.springcloud.service.PaymentFeignService: debug

访问
在这里插入图片描述
后台显示:
在这里插入图片描述

十.Hystrix(服务降级,被弃用)

1.概念
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

作用:
服务降级
服务熔断
接近实时的服务监控

Hystrix git项目

停更
在这里插入图片描述

2.重要概念
服务降级 fallback
服务器忙,请稍后再试,不让客户端等待并返回一个友好提示,fallback;
场景: 程序运行异常 超时 服务熔断触发服务降级 线程池/信号量打满导致服务降级

服务熔断 break
类似于保险丝达到最大访问后,直接拒绝访问,拉闸限电,然后调用服务降级中的方法并返回友好提示

服务限流flowlimit
秒杀高并发操作,严禁一窝蜂过来拥挤,排队一秒N个,有序进行

服务降级—服务熔断—恢复调用链路

3.案例
在这里插入图片描述

 <dependencies>
        <!--新增hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>


        <dependency>
            <groupId>com.cz.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>


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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
server:
  port: 8001


eureka:
  client:
    register-with-eureka: true    #表识不向注册中心注册自己
    fetch-registry: true   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
    service-url:
      # defaultZone: http://eureka7002.com:7002/eureka/    #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka/
#  server:
#    enable-self-preservation: false
spring:
  application:
    name: cloud-provider-hystrix-payment
#    eviction-interval-timer-in-ms: 2000
@SpringBootApplication
@EnableEurekaClient
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class,args);
    }
}
@Service
public class PaymentService {

    //成功
    public String paymentInfo_OK(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"   paymentInfo_OK,id:  "+id+"\t"+"正确"  ;
    }

    //失败
    public String paymentInfo_TimeOut(Integer id){
        int timeNumber = 3;
        /*超时*/
        try { TimeUnit.SECONDS.sleep(timeNumber); }catch (Exception e) {e.printStackTrace();}
        return "线程池:"+Thread.currentThread().getName()+"   paymentInfo_TimeOut,id:  "+id+"\t"+"错误"+" 耗时(秒)"+timeNumber;
    }

}
@RestController
@Slf4j
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id){
        String result = paymentService.paymentInfo_OK(id);
        log.info("result:"+result);
        return result;
    }
    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
        String result = paymentService.paymentInfo_TimeOut(id);
        log.info("result:"+result);
        return result;
    }
}

访问
在这里插入图片描述
在这里插入图片描述

演示:正确—错误—降级熔断—恢复

4.高并发测试
JMeter
在这里插入图片描述

访问
在这里插入图片描述
2个访问均响应慢
原因:tomcat的默认的工作线程数被打满了,没有多余的线程来分解压力和处理。

5.高并发 80加入

在这里插入图片描述
在这里插入图片描述

结果:
要么访问处于等待状态,要么消费端报超时错误

原因:在这里插入图片描述

解决方法:
在这里插入图片描述
在这里插入图片描述

6.服务降级
降低配置 注解@HystrixCommand

(1)8001
设置自我调用超时时间的峰值,峰值内可正常运行
超过峰值,需要有兜底的方法处理,做服务降级fallback

业务类中
在这里插入图片描述

主启动类添加注解
在这里插入图片描述

访问
在这里插入图片描述
控制台
在这里插入图片描述
服务降级

(2)80
除了在服务提供端进行服务降级,客户端进行服务降级
yml

feign:
  hystrix:
    enabled: true #如果处理自身的容错就开启。开启方式与生产端不一样。

主配置类
在这里插入图片描述
在这里插入图片描述

访问在这里插入图片描述
在这里插入图片描述

(3)问题
在这里插入图片描述

解决方案:
a.代码膨胀: 全局服务降级
通用和独享各自分开

在这里插入图片描述
程序运行报错、超时、服务熔断触发服务降级、线程池/信号量打满 时,配置@HystrixCommand,则采用就近原则读取fallback方法,当方法上没有配置降级方法,则读取调用类上配置的降级方法。

b.和业务逻辑混淆

为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦

在这里插入图片描述
配置降级,在service层配置@FeignClient属性fallback
在这里插入图片描述

7.服务熔断
(1)概述:
熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路上的某个微服务出错或响应时间太长时,会进行服务降级,进而熔断此节点微服务的调用,快速返回错误的响应信息。当检测到此节点微服务调用正常后,恢复调用链路。

在Spring Cloud框架中,熔断机制通过Hystrix实现,Hystrix会监控微服务间的状况,当失败的调用到一定的阈值,缺省是5秒内20次调用失败,会启动熔断机制,熔断机制的注解@HystrixCommand

熔断神文
在这里插入图片描述
在这里插入图片描述

(2)案例:
8001
在这里插入图片描述

配置的参数的源头:

在这里插入图片描述

在这里插入图片描述

无异常访问 http://127.0.0.1:8001/payment/circuit/1
异常访问 http://127.0.0.1:8001/payment/circuit/-1

在规定时间范围内,请求次数超过规定请求次数,异常访问 失败率达到规定失败率,触发熔断;服务降级
在这里插入图片描述
之后恢复调用链路
在这里插入图片描述

(3)原理:
熔断打开: 请求不再调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设置时钟则进入半熔断状态;
熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则,则认为当前服务恢复正常,关闭熔断
熔断关闭:熔断关闭则不会对服务进行熔断

在这里插入图片描述

在这里插入图片描述
断路器开启或关闭的条件:
当默认时间内请求满足一定的阈值(默认10秒内超过20次请求),当失败率达到一定的时候(默认10秒内超过50%的请求失败),断路器就开启。当开启的时候,所有请求都不会再进行转发。一段时间后(默认为5秒),这个时候断路器处于半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。

断路器打开之后:
再有请求调用的时候,将不会调用主逻辑,而是直接调用fallback或设置在类上的defaultFallback或FeignClient中配置的fallback.通过断路器,实现自动发现错误,并将降级逻辑切换为主逻辑,减少延迟的效果

恢复原来的主逻辑:
当断路器打开,对主逻辑进行熔断后,hystrix会启动一个休眠时间窗,在这个时间窗,降级逻辑成为临时的主逻辑,当休眠时间窗到期,断路器将会进入半开状态,释放一次请求到原来的主逻辑,如果此次请求正常返回,则断路器闭合,主逻辑恢复。若请求出现问题,断路器继续打开,休眠时间窗重新计时。

(4)参数说明:
@HystrixCommand

        // HystrixCommand 命令所属的组的名称:默认注解方法类的名称
            String groupKey() default "";

            // HystrixCommand 命令的key值,默认值为注解方法的名称
            String commandKey() default "";

            // 线程池名称,默认定义为groupKey
            String threadPoolKey() default "";
            // 定义回退方法的名称, 此方法必须和hystrix的执行方法在相同类中
            String fallbackMethod() default "";
            // 配置hystrix命令的参数
            HystrixProperty[] commandProperties() default {};
            // 配置hystrix依赖的线程池的参数
             HystrixProperty[] threadPoolProperties() default {};

            // 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。我们也可以通过此方法定义哪些需要忽略的异常
            Class<? extends Throwable>[] ignoreExceptions() default {};

            // 定义执行hystrix observable的命令的模式,类型详细见ObservableExecutionMode
            ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;

            // 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。此方法定义需要抛出的异常
            HystrixException[] raiseHystrixExceptions() default {};

            // 定义回调方法:但是defaultFallback不能传入参数,返回参数和hystrix的命令兼容
            String defaultFallback() default "";

猜你喜欢

转载自blog.csdn.net/javahelpyou/article/details/104978652
今日推荐