94-java-springcloud(07)-服务降级-Hystrix/Hystrix Dashboard

Hystrix

在这里插入图片描述

一.简介

1.官网

参考官网: https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.2.3.RELEASE/reference/html/#circuit-breaker-spring-cloud-circuit-breaker-with-hystrix

2.分布式微服务面临的问题?
  • 服务雪崩
    某个或者某些服务出现故障,导致调用本服务的其他服务调用缓慢,或者调用失败,发生级联反应,从而导致多个服务不能使用,发生服务雪崩不能使用.

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

3.Hystrix的作用

在微服务之间作为断路器,保险丝使用,避免发生级联错误,从而保护服务,避免服务雪崩.

(1)服务降级(出现错误怎么办?)

#服务器忙,请稍候再试,不让客户端等待并立刻返回一个友好提示,fallback.
可能出现服务降级的原因:

  • 程序运行异常
  • 超时
  • 服务熔断触发服务降级
  • 线程池/信号量打满也会导致服务降级
(2)服务熔断(错误过多怎么办?)

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

总结:
就是单位时间内出现多少次错误;或者访问的错误比率达到多少就对外不提供服务;等过一段时间(时间窗口期)再次尝试提供服务.

(3) 服务限流

#秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行

二.代码使用

1.基础使用
1) 建module

2) 改pom
		<!--新增hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
3) 改yml
  • 生产者
    则不需要配置什么,可能需要配置的就是暴露监控断点给hystrix dashboard.
# 在被监控服务上添加暴露端点
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream
  • 消费者
    #如果消费者使用feign作为调用客户端的话,则需要开启hystrix;如果使用的是RestTemplate调用的话,以下yml配置不用配置.
feign:
  hystrix:
    enabled: true #如果处理自身的容错就开启。开启方式与生产端不一样。
4) 主启动

@EnableHystrix注解和@EnableCircuitBreaker随便使用一个就可以了.

@SpringBootApplication
@EnableFeignClients
//以下两个注解随便使用一个就可以
@EnableHystrix 
//@EnableCircuitBreaker  //启动服务熔断,使注解 @HystrixCommand生效
public class PaymentHystrixMain80 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain80.class,args);
    }
}

@EnableHystrix注解
#@EnableHystrix注解就是@EnableCircuitBreaker的子类,并且和他一模一样
在这里插入图片描述
所以,以后我们使用@EnableHystrix就好.

5) 业务类

(1) 单独使用Hystrix(生产者和消费者均可)
在任何方法上都可以,一般是在controller类或者service类中使用.

  • [1] 单独配置方法的熔断方法

优点:
精确控制每个方法的服务降级
缺点:
1.每个方法都需要编写,服务降级方法,麻烦
2.服务降级方法和业务方法在一个类中,糅杂.

//服务熔断
    /**
     * 当id为正数的时候,访问正常
     * 当id为负数的时候,进行服务降级.
     *      当请求的次数超过10次,并且请求的降级率为60%,则开启服务熔断.
     *      过一段时间,服务会再次尝试开启请求,检查是否能通过
     */
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {  //fallbackMethod表示出现服务熔断调用的方法
            @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();

        return Thread.currentThread().getName()+"\t"+"调用成功,流水号:"+serialNumber;
    }

    /**
     * 这是服务熔断之后,调用的方法
     */
    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
        return "id 不能负数,请稍候再试,(┬_┬)/~~     id: " +id;
    }
  • [2] 给整个类配置熔断方法
    类上用注解@DefaultProperties指明本类的默认熔断方法;
    方法上用注解 @HystrixCommand 标明本方法需要开启服务降级.

优点:
减少代码的编写
缺点:
业务代码和服务降级方法糅杂在一起,在一个类中.

@RestController
@Slf4j
//这是Hystrix的注解,指定本类的默认的熔断执行方法是哪个.
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderHystrixController {

   ....
    /**
     * 服务降级的fallBackMethod方法调用的优先级:
     * 1.@HystrixCommand加上方法上指明fallbackMethod调用的fallback方法.
     * 2.@HystrixCommand只配置了本注解,使用类上@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")配置的方法
     * 3.@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
     * 使用feign接口上配置的fallback类中对应的方法
     */
   @HystrixCommand  //没有fallbackMethod这个属性,就表示使用全局服务降级方法,
   @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        log.info("*******result:"+result);
        return result;
    }

    //下面是全局fallback方法
    public String payment_Global_FallbackMethod(){
        return "Global异常处理信息,请稍后再试,(┬_┬)";
    }
}

(2) openFeign + Hystrix
openFeign即可使用上述的两种方式,也可在feign客户端调用api接口的时候,使用服务降级.

优点:
面向接口编程,服务降级方法和业务方法分离.

  • 第一步:feign调用interface类
    feign调用的interface类,指明使用哪个类作为服务降级类.
@Component
//fallback标明,feign调用这个服务的时候,如果服务出现异常的服务降级类是哪个
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
public interface PaymentHystrixService {
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id);

}
  • 第二步:Hystrix服务降级实现类
/**
 * @author gl
 * @time 2020-06-18 22:26
 * @function :Openfeign调用的服务降级类.
 * @step :
 */
@Component
//需要实现feign调用的接口interface
public class PaymentFallbackService implements PaymentHystrixService{

    //对应feign调用方法中的paymentInfo_OK这个方法的降级方法.
    @Override
    public String paymentInfo_OK(Integer id) {
        return "-------PaymentFallbackService.paymentInfo_OK-----对方服务已宕机,请稍后重试";
    }

    //对应feign调用方法中的paymentInfo_TimeOut这个方法的降级方法.
    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "-------PaymentFallbackService.paymentInfo_TimeOut-----对方服务已宕机,请稍后重试";
    }
}
2.服务降级(程序规定时间获取不到结果,怎么办?)

服务降级可能发生的地方

  • 程序运行异常
  • 超时
  • 服务熔断触发服务降级
  • 线程池/信号量打满也会导致服务降级

其余代码省略,列举服务降级可能发生的地方.

@Service
public class PaymentService {

    /**
     * 成功的方法
     */
    public String paymentInfo_OK(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"   paymentInfo_OK,id:  "+id+"\t"+"哈哈哈"  ;
    }


    /**
     * 服务降级 --出现错误
     */
    @HystrixCommand(fallbackMethod = "paymentInfo_handler" ,commandProperties = {  //这个表示服务如果出现异常,执行哪个方法
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")  //3秒钟以内就是正常的业务逻辑
    })
    public String paymentInfo_Exception(Integer id){

        //测试出现错误
        int i= 10/0;
        return "线程池:"+Thread.currentThread().getName()+"   paymentInfo_TimeOut,id:  "+id+"\t"+"呜呜呜"+" 耗时(秒)";
    }


    /**
     * 服务降级--超时
     */
    @HystrixCommand(fallbackMethod = "paymentInfo_handler" ,commandProperties = {  //这个表示服务如果出现异常,执行哪个方法
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1000")  //3秒钟以内就是正常的业务逻辑
    })
    public String paymentInfo_TimeOut(Integer id){
        //测试超时
        int timeNumber = 2;
        try {
            TimeUnit.SECONDS.sleep(timeNumber);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return "线程池:"+Thread.currentThread().getName()+"   paymentInfo_TimeOut,id:  "+id+"\t"+"呜呜呜"+" 耗时(秒)"+timeNumber;
    }

    /**
     * 这是hystrix服务降级的回调方法.
     * @param id
     * @return
     */
    public String paymentInfo_handler(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"   paymentInfo_handler,当前方法超时或者出现错误,请稍后尝试id:  "+id+"\t"+"呜呜呜"+" 耗时(秒)";
    }
   
    .....  
}

3.服务熔断(程序错误过多,怎么办?)
  • 一定时间周期内,错误效应次数达到多少次,则熔断即不再调用该服务,经过一定时间窗口期,再尝试去请求服务.
  • 一定时间周期内,当请求次数达到多少,错误比例达到多少,则熔断即不再调用该服务,经过一定时间窗口期,再次尝试去请求服务.
//================服务熔断
    //服务熔断
    /**
     * 当id为正数的时候,访问正常
     * 当id为负数的时候,进行服务降级.
     *      当请求的次数超过10次,并且请求的降级率为60%,则开启服务熔断.
     *      过一段时间,服务会再次尝试开启请求,检查是否能通过
     */
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {  //fallbackMethod表示出现服务熔断调用的方法
            @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();
        return Thread.currentThread().getName()+"\t"+"调用成功,流水号:"+serialNumber;
    }

    /**
     * 这是服务熔断之后,调用的方法
     */
    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
        return "id 不能负数,请稍候再试,(┬_┬)/~~     id: " +id;
    }
4.@HystrixCommand 注解详解

这个注解是Hystrix最重要的注解,关于这个注解的属性可以参考官网.
参考文章: https://github.com/Netflix/Hystrix/wiki/Configuration

/**
 * This annotation used to specify some methods which should be processes as hystrix commands.
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {

    
    String groupKey() default "";

    String commandKey() default "";

    String threadPoolKey() default "";

    String fallbackMethod() default "";
	//定义熔断相关的属性配置.具体的属性参考官网
    HystrixProperty[] commandProperties() default {};
	//hystrix的线程池的配置,具体属性参考官网
    HystrixProperty[] threadPoolProperties() default {};
	//异常忽略
    Class<? extends Throwable>[] ignoreExceptions() default {};

    ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;

    HystrixException[] raiseHystrixExceptions() default {};

    String defaultFallback() default "";
}

Hystrix Dashboard

因为Hystrix Dashboard也是一个微服务,所以也需要搭建一个微服务模块,其实就有点类似于Eureka的server端一样的.

1.dashboard的搭建

(1) 建module

(2) 改pom

		<!--新增hystrix dashboard,这个会自动依赖导入web模块-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

(3) 写yml

#配置端口号即可
server:
  port: 9001

(4) 主启动
@EnableHystrixDashboard //启动HystrixDashboard

@SpringBootApplication
//启动HystrixDashboard
@EnableHystrixDashboard
public class HystrixDashboardMain9001 {
    
     public static void main(String[] args) {
            SpringApplication.run(HystrixDashboardMain9001.class,args);
        }
}

(5) 测试页面
根据你项目的端口号.访问如下路劲,出现如下页面即成功
http://localhost:9001/hystrix
在这里插入图片描述

2.监控具体的项目

(1).被监控的微服务都必须引入依赖

		<!--新增hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--健康检查-->
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
 

(2) 被监控的微服务必须暴露监控断点

# 在被监控服务上添加暴露端点
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream

(3) 在监控面板填写监控地址
在这里插入图片描述

(4) 如果出现Unable to connect to Command Metric Stream
则在被监控的微服务中注入如下bean

 /**
     * 这是为了hystri dashboard监控仪表盘,而配置的bean
     * @return
     */
    @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;
    }
3.监控面板说明

总体就是7色,一线,一圈.

  • 7色:成功数/熔断数/错误请求/超时数/线程拒绝数/异常失败数/错误百分比
  • 1线:表示请求的变化图
  • 1圈:圈越大,qps越大,并发越大,颜色绿色表示正常运行,红色表示错误比例大.

在这里插入图片描述

4.Turbine(监控多个微服务)

上面的监控,我们只能监控单个微服务,我们可以利用turbine整合多个监控流,一次性监控多个微服务.
具体略.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值