SpringCloud实战---第十四篇-Ⅱ:Hystrix熔断及服务监控

举报
老司机张师傅 发表于 2022/07/26 23:24:16 2022/07/26
【摘要】 系列文章目录SpringCloud快速入门到精通各组件原理专栏传送门@TOC 前言续上篇:SpringCloud实战—第十四篇-Ⅰ:Hystrix概念及快速上手试想一下,如果我们一个微服务接口就对应一个降级方法,然后降级方法又放在同一个Controller中,那必然会出现代码的膨胀(10实际的接口,我们就需要翻一倍成20个),也会导致代码十分拥挤导致不可读,这不符合我们优雅编程的理念。Hy...

系列文章目录

SpringCloud快速入门到精通各组件原理
专栏传送门


@TOC


前言

续上篇:SpringCloud实战—第十四篇-Ⅰ:Hystrix概念及快速上手

试想一下,如果我们一个微服务接口就对应一个降级方法,然后降级方法又放在同一个Controller中,那必然会出现代码的膨胀(10实际的接口,我们就需要翻一倍成20个),也会导致代码十分拥挤导致不可读,这不符合我们优雅编程的理念。
Hystrix设计上可以让我们配置通用的服务降级方法(就是没有特殊定制的,出现错误时都走统一的一个方法),有需要特殊定制的走他自己的。

我们学习新的技术,不要只学习应用层面,理解他的原理才是我们的主要目的,应用层面(框架)可能会有很多种,随时间更替,但他的核心原理及设计里面基本不变,我们理解了设计理念可以更好的应用,也有助于我们对系统的设计。


一、解决代码膨胀问题

配置全局通用的FallbackMethod
在这里插入图片描述
在80的Controller上添加@DefaultProperties配置

@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")

添加默认降级方法payment_Global_FallbackMethod

public String payment_Global_FallbackMethod(){
    return "80端默认降级:8001支付服务繁忙,请10秒后重试,如未解决请联系开发人员排查自身异常。。。";
}

关闭接口配置的自定义的降级方法,只配置降级注解

@GetMapping("/consumer/payment/hystrix/timeout/{id}")
// 方法出异常时会找fallbackMethod配置的方法
//@HystrixCommand(fallbackMethod = "paymentInfoTimeOutFallbackMethod",commandProperties = {
//        @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500") // 表示这个线程的超时时间时3秒钟,下面我们线程睡了5秒,他一定会超时
//})
@HystrixCommand
public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
    int a= 10/0; // 强制报错
    return paymentHystrixService.paymentInfo_TimeOut(id);
}

在这里插入图片描述
启动测试,访问

http://localhost/consumer/payment/hystrix/timeout/1

在这里插入图片描述

二、解决代码耦合度高

将降级方法提取出来,不和代码耦合在一起
我们Controller调用的是Service层,Service是使用OpenFeign调用的远端服务,理论上我们给Service添加一个统一的类做降级就可以解决代码耦合度高的问题。

1. 新建PaymentHystrixService的实现类PaymentFallbackService

在这里插入图片描述

package com.atguigu.springcloud.service;

/**
 * @Author: Daisen.Z
 * @Date: 2021/12/27 17:59
 * @Version: 1.0
 * @Description:
 */
 @Component
public class PaymentFallbackService implements PaymentHystrixService {
    @Override
    public String paymentInfo_OK(Integer id) {
        return "********** PaymentFallbackService paymentInfo_OK fall back,/(ㄒoㄒ)/~~";
    }

    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "********** PaymentFallbackService paymentInfo_TimeOut fall back,/(ㄒoㄒ)/~~";
    }
}

2. 配置文件开启hystrix

在这里插入图片描述
给FeignClient添加fallback类,表示的是调用的cloud-provider-hystrix-payment微服务方法,降级处理类是PaymentFallbackService
因为本来PaymentFallbackService就是PaymentHystrixService的实现类,所以他们的方法是一一对应的
在这里插入图片描述

@FeignClient(value = "cloud-provider-hystrix-payment",fallback = PaymentFallbackService.class)

3. 测试

启动7001、hystrix-8001、hystrix-80服务
访问80的ok接口

http://localhost/consumer/payment/hystrix/ok/1

显示正常
在这里插入图片描述
接下来我们把8001关掉(模拟服务宕机)
再次访问ok接口
成功降级

在这里插入图片描述

代码优雅且高效起来了呢~~

服务降级总结

服务降级是指系统出现宕机、超时等程序异常时进行的处理措施,调用降级方法返回一个可处理的结构体。

三、服务熔断

与服务降级不同,服务熔断是指类似于电上的保险丝,当电量出现高压或起火,为了防止灾情扩散或烧毁家电,保险丝会紧急断开,直接不让通电。
类似于是一种保险措施,当服务流量超过某个阈值时进行熔断,不再处理请求而是直接调用降级方法返回结果,服务降级是已经出现异常了,然后进行降级处理。
而Hystrix比较厉害的一点是熔断后会检测接口服务情况,当请求低于阈值或服务恢复正常了之后关闭熔断,继续正常调用服务(有一些简单的自我恢复方法)。
熔断的原理:

微服务贡献者大神马丁富勒(Martin Fowler)提出的原理:
https://translate.google.cn/?sl=auto&tl=zh-CN&text=Martin Fowler&op=translate
当服务超过阈值打到服务上,服务处理不过来时(如20秒出现了500次请求失败)开启熔断,然后过了一会流量降下来了(原来500次每秒,直接开启熔断了,然后过会编程了10次每秒请求流量级别降下来了),这时Hystrix会尝试开始进行恢复,有少量的请求去测试(半开熔断),当出现几次尝试都能承受(处理),就关闭熔断让服务正常调用。

在这里插入图片描述

四、实操

1. 改造hystrix-8001的PaymentService

在这里插入图片描述
主要还是通过@HystrixCommand来配置熔断
是否使用断路器: true使用,false不使用
以下配置表示的意思时10000毫秒的时间里10次请求有百分之60(6次)失败,熔断器将会处于打开状态
当我们传的id是个正数时正常,传的id是个负数时会报错(用于测试)

//=====服务熔断
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
        @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否开启断路器
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失败率达到多少后跳闸
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{
    if(id < 0)
    {
        throw new RuntimeException("******id 不能负数");
    }
    String serialNumber = IdUtil.simpleUUID(); // 生成一个随机的UUID,hutool工具类封装了一下

    return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber;
}
// 服务降级的方法
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id)
{
    return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " +id;
}

2. 改造hystrix-8001的PaymentController

    //====服务熔断
    @GetMapping("/payment/circuit/{id}")
    public String paymentCircuitBreaker(@PathVariable("id") Integer id)
    {
        String result = paymentService.paymentCircuitBreaker(id);
        log.info("****result: "+result);
        return result;
    }

在这里插入图片描述

3. 测试

启动7001和8001
访问以下地址,多刷新几次,除了流水号改变其他都正常

http://localhost:8001/payment/circuit/31

访问id为负数的

http://localhost:8001/payment/circuit/-31

调用了降级方法
在这里插入图片描述
我们狂点id为负数的刷新,让他多报几次错误(10秒10次错误出现6次以上失败触发打开熔断器)
在这里插入图片描述
然后再访问id为正数的,即不会报异常的

http://localhost:8001/payment/circuit/31

会发现也报错,这就是熔断器打开了熔断防止我们资源爆满,所有请求直接走降级方法。
在这里插入图片描述
隔一小会,你再访问正确的,他又会自己变正常了(半开到关闭状态)
在这里插入图片描述

五、服务限流

服务限流后续使用alibaba的Sentinel进行讲解(因为Hystrix虽然很优秀,但是他毕竟已经停止开源维护了,我们就不给他花费过多的时间)

六、Hystrix服务监控

1. 创建9001监控模块

在这里插入图片描述
模块名

cloud-consumer-hystrix-dashboard9001

pom.xml: 其中spring-boot-starter-actuator代表图形化依赖,所有通过web展示图形化界面的都需要依赖他

<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-hystrix-dashboard9001</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</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>
</project>

application.yml

server:
  port: 9001

基础包

com.atguigu.springcloud

主启动类

HystrixDashboardMain9001
package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

/**
 * @Author: Daisen.Z
 * @Date: 2021/12/28 9:51
 * @Version: 1.0
 * @Description:
 */
@SpringBootApplication
@EnableHystrixDashboard // 开启图形化
public class HystrixDashboardMain9001 {

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

}

2. 启动检查

启动创建好的9001模块,访问

http://localhost:9001/hystrix

看到我们的豪猪哥,证明可视化模块创建成功
在这里插入图片描述

3. 监控微服务hystrix-8001

我们测试通过9001监控hystrix-8001也就是我们创建的带熔断的微服务
首先,在8001工程上添加可视化的依赖(我们之前已经添加过)

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

然后,在8001的主启动类里添加一个Bean配置,这个配置是为了解决SpringCloud升级自带的坑

    /**
     *此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
     *ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
     *只要在自己的项目里配置上下面的servlet就可以了
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

在这里插入图片描述

4. 测试监控微服务

启动7001和9001工程
在豪猪哥的页面上输入下面地址,代表监控8001

http://localhost:8001/hystrix.stream

在这里插入图片描述
启动8001,先检查下接口是否正常
正确的状态

http://localhost:8001/payment/circuit/31

我们模拟的接口异常的状态

http://localhost:8001/payment/circuit/-31

正常之后,开启豪猪哥对8001的监控
在这里插入图片描述
各个颜色代表不通的请求(正确的、错误请求、服务器处理错误等等)
在这里插入图片描述
多刷新访问几次8001上的接口,让熔断器处于不同的状态,自己看一下。后边使用阿里微服务框架就不需要我们再自己搭建这个9001模块了。
在这里插入图片描述


总结

  • 熔断打开:请求不再进行调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态。
  • 熔断关闭:熔断关闭不会对服务进行熔断。
  • 熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断。
  • 四个重要参数:
    circuitBreaker.enabled: 是否启用熔断器
    circuitBreaker.requestVolumeThreshold: 请求次数
    circuitBreaker.sleepWindowInMilliseconds:时间窗口(毫秒)
    circuitBreaker.errorThresholdPercentage:失败率(100之内的数字)
  • 当在时间窗口内配置的请求次数失败率达到配置的失败率时开启熔断,注意请求次数可以理解成时基本条件,达到请求次数后才会进行是否开启熔断的判断。
  • 熔断会进行调用链路恢复,熔断器打开后,过段时间流量降下来之后会进入半开状态,继续放行请求,发现成功率上来了,会再进行关闭。
  • 豪猪哥可以监控服务状态及流量状态。
  • 我们学习新的技术,不要只学习应用层面,理解他的原理才是我们的主要目的,应用层面(框架)可能会有很多种,随时间更替,但他的核心原理及设计里面基本不变,我们理解了设计理念可以更好的应用,也有助于我们对系统的设计。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。