Spring Cloud 配置Hystrix服务熔断与降级

Spring Cloud 配置Hystrix服务熔断与降级

熔断器
熔断器(Circuit Breaker)一词来源物理学中的电路知识,它的作用是当线路出现故障时,迅速切断电源以保护电路的安全。
在微服务领域,熔断器最早是由 Martin Fowler 在他发表的 《Circuit Breaker》一文中提出。与物理学中的熔断器作用相似,微服务架构中的熔断器能够在某个服务发生故障后,向服务调用方返回一个符合预期的、可处理的降级响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常。*这样就保证了服务调用方的线程不会被长时间、不必要地占用,*避免故障在微服务系统中的蔓延,防止系统雪崩效应的发生。
Spring Cloud Hystrix
Spring Cloud Hystrix 是一款优秀的服务容错与保护组件,也是 Spring Cloud 中最重要的组件之一。
Spring Cloud Hystrix 是基于 Netflix 公司的开源组件 Hystrix 实现的,它提供了熔断器功能,能够有效地阻止分布式微服务系统中出现联动故障,以提高微服务系统的弹性。Spring Cloud Hystrix 具有服务降级、服务熔断、线程隔离、请求缓存、请求合并以及实时故障监控等强大功能。

在微服务系统中,Hystrix 能够帮助我们实现以下目标:
1.保护线程资源:防止单个服务的故障耗尽系统中的所有线程资源。
2.快速失败机制:当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败。
3.提供降级(FallBack)方案:在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法。
4.防止故障扩散:使用熔断机制,防止故障扩散到其他服务。
5.监控功能:提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态。
Hystrix 服务降级
Hystrix 提供了服务降级功能,能够保证当前服务不受其他服务故障的影响,提高服务的健壮性。

服务降级的使用场景有以下 2 种:
在服务器压力剧增时,根据实际业务情况及流量,对一些不重要、不紧急的服务进行有策略地不处理或简单处理,从而释放服务器资源以保证核心服务正常运作。
当某些服务不可用时,为了避免长时间等待造成服务卡顿或雪崩效应,而主动执行备用的降级逻辑立刻返回一个友好的提示,以保障主体业务不受影响。
我们可以通过重写 HystrixCommand 的 getFallBack() 方法或 HystrixObservableCommand 的 resumeWithFallback() 方法,使服务支持服务降级。
Hystrix 服务降级 FallBack 既可以放在服务端进行,也可以放在客户端进行。
Hystrix 会在以下场景下进行服务降级处理:
程序运行异常
服务超时
熔断器处于打开状态
线程池资源耗尽
服务端服务降级案例

  1. 在主工程 spring-cloud-demo2 下创建一个名为 micro-service-cloud-provider-dept-hystrix-8001 的服务提供者,并在其 pom.xml 中添加以下依赖。
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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>
        <!--添加 Spring Boot 的监控模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- eureka 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--hystrix 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>
  1. 在类路径(即 /resources 目录)下添加一个配置文件 application.yml,配置内容如下。
spring:
  application:
    name: cloud-provider-gystrix-payment  #微服务名称,对外暴漏的微服务名称,十分重要
server:
  port: 8001
########################################### Spring cloud 自定义服务名称和 ip 地址###############################################
eureka:
  client: #将客户端注册到 eureka 服务列表内
  register-with-eureka: true
  fetch-registry: true
    service-url:
      #defaultZone: http://eureka7001:7001/eureka  #这个地址是 7001注册中心在 application.yml 中暴露出来额注册地址 (单机版)
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/  #将服务注册到 Eureka 集群
  instance:
    instance-id: spring-cloud-provider-8004 #自定义服务名称信息
    prefer-ip-address: true  #显示访问路径的 ip 地址
#####################spring cloud 使用 Spring Boot actuator 监控完善信息###########################################
# Spring Boot 2.50对 actuator 监控屏蔽了大多数的节点,只暴露了 heath 节点,本段配置(*)就是为了开启所有的节点
management:
  endpoints:
    web:
      exposure:
        include: "*"   # * 在yaml 文件属于关键字,所以需要加引号
info:
  app.name: micro-service-cloud-provider-dept-hystrix
  company.name: c.biancheng.net
  build.aetifactId: @project.artifactId@
  build.version: @project.version@
  1. 在 net.biancheng.c.service 包下创建一个名为 DeptService 的接口,代码如下。
package net.biancheng.c.service;
public interface DeptService {
    // hystrix 熔断器示例 ok
    public String deptInfo_Ok(Integer id);
    //hystrix 熔断器超时案例
    public String deptInfo_Timeout(Integer id);
}
  1. 在 net.biancheng.c.service.impl 包下,创建 DeptService 接口的实现类 DeptServiceImpl,代码如下。
package net.biancheng.c.service.impl;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import net.biancheng.c.service.DeptService;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service("deptService")
public class DeptServiceImpl implements DeptService {
    @Override
    public String deptInfo_Ok(Integer id) {
        return "线程池:" + Thread.currentThread().getName() + "  deptInfo_Ok,id:   " + id;
    }
    //一旦该方法失败并抛出了异常信息后,会自动调用  @HystrixCommand 注解标注的 fallbackMethod 指定的方法  参数 fallbackMethod 属性用于指定降级方法,参数 execution.isolation.thread.timeoutInMilliseconds 用于设置自身调用超时时间的峰值,峰值内可以正常运行,否则执行降级方法
    @HystrixCommand(fallbackMethod = "dept_TimeoutHandler",
            commandProperties =
                    //规定 5 秒钟以内就不报错,正常运行,超过 5 秒就报错,调用指定的方法
                    {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")})
    @Override
    public String deptInfo_Timeout(Integer id) {
        int outTime = 6;
        try {
            TimeUnit.SECONDS.sleep(outTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程池:" + Thread.currentThread().getName() + "  deptInfo_Timeout,id:   " + id + "  耗时: " + outTime;
    }
    // 当服务出现故障后,调用该方法给出友好提示
    public String dept_TimeoutHandler(Integer id) {
       return  "C语言中文网提醒您,系统繁忙请稍后再试!"+"线程池:" + Thread.currentThread().getName() + "  deptInfo_Timeout,id:   " + id;
    }
}
  1. 在 net.biancheng.c.controller 包下创建一个名为 DeptController 的 Controller 类,代码如下
package net.biancheng.c.controller;
import lombok.extern.slf4j.Slf4j;
import net.biancheng.c.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
@RestController
@Slf4j
public class DeptController {
    @Autowired
    private DeptService deptService;
    @Value("${server.port}")
    private String serverPort;
    @RequestMapping(value = "/dept/hystrix/ok/{id}")
    public String deptInfo_Ok(@PathVariable("id") Integer id) {
        String result = deptService.deptInfo_Ok(id);
        log.info("端口号:" + serverPort + " result:" + result);
        return result + ",   端口号:" + serverPort;
    }
    // Hystrix 服务超时降级
    @RequestMapping(value = "/dept/hystrix/timeout/{id}")
    public String deptInfo_Timeout(@PathVariable("id") Integer id) {
        String result = deptService.deptInfo_Timeout(id);
        log.info("端口号:" + serverPort + " result:" + result);
        return result + ",   端口号:" + serverPort;
    }
}

6.在micro-service-cloud-provider-dept-hystrix-8001 的主启动类上,使用 @EnableCircuitBreaker 注解开启熔断器功能,代码如下:

package net.biancheng.c;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient //开启 Eureka 客户端功能
@EnableDiscoveryClient //服务发现 
// @EnableCircuitBreaker //激活熔断器功能
public class MicroServiceCloudProviderDeptHystrix8004Application {
    public static void main(String[] args) {
        SpringApplication.run(MicroServiceCloudProviderDeptHystrix8004Application.class, args);
    }
}

可以采用Jmeter进行高并发测试

服务降级

服务降级处理是在客户端实现完成的,与服务端没有关系.
解耦降级逻辑
不管是业务方法指定的降级方法还是全局降级方法,它们都必须和业务方法在同一个类中才能生效,业务逻辑与降级逻辑耦合度极高

  1. 在 micro-service-cloud-consumer-dept-feign 的 net.biancheng.c.service 包下,新建 DeptHystrixService 接口的实现类 DeptHystrixFallBackService,统一为 DeptHystrixService 中的方法提供服务降级处理 ,
    注意:该类必须以组件的形式添加 Spring 容器中才能生效,最常用的方式就是在类上标注 @Component 注解
    代码如下:
package net.biancheng.c.service;
import org.springframework.stereotype.Component;
/**
* Hystrix 服务降级
* 解耦回退逻辑
*/
@Component  // 一定要加
public class DeptHystrixFallBackService implements DeptHystrixService {
    @Override
   public String deptInfo_Ok(Integer id) {
        return "--------------------C语言中文网提醒您,系统繁忙,请稍后重试!(解耦回退方法触发)-----------------------";
    }
   @Override
   public String deptInfo_Timeout(Integer id) {
      return "--------------------C语言中文网提醒您,系统繁忙,请稍后重试!(解耦回退方法触发)-----------------------";
}

下列写法可以主动创建熔断

package net.biancheng.c.service;
import org.springframework.stereotype.Component;
/**
* Hystrix 服务降级
* 解耦回退逻辑
*/
@Component  // 一定要加
public class DeptHystrixFallBackService implements FallbackFactory<DeptHystrixService> {
//  create方法针对DeptHystrixService创造熔断
@Override
public DeptHystrixService create(Throwable throwable){
return new DeptHystrixService(){
  @Override
   public String deptInfo_Ok(Integer id) {
       return "--------------------C语言中文网提醒您,系统繁忙,请稍后重试!(解耦回退方法触发)-----------------------";    }
    @Override
  public String deptInfo_Timeout(Integer id) {
       return "--------------------C语言中文网提醒您,系统繁忙,请稍后重试!(解耦回退方法触发)-----------------------";
   }
}
}
  1. 在服务绑定接口 DeptHystrixService 标注的 @FeignClient 注解中添加 fallback 属性,属性值为 DeptHystrixFallBackService.class,代码如下:
package net.biancheng.c.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Component
@FeignClient(value = "MICROSERVICECLOUDPROVIDERDEPTHYSTRIX", fallback = DeptHystrixFallBackService.class)
public interface DeptHystrixService {
    @RequestMapping(value = "/dept/hystrix/ok/{id}")
    public String deptInfo_Ok(@PathVariable("id") Integer id);
    @RequestMapping(value = "/dept/hystrix/timeout/{id}")
    public String deptInfo_Timeout(@PathVariable("id") Integer id);
}

3.yml配置添加一下内容:

feign:
	hystrix:
		enabled: true  #在feign开启hystrix

// ======服务熔断

@HystrixCommand(fallbackMethod = "paymetCiruitBreaker_Fallback",commandPrpperties = {
@HystrixProperty(name = "circuitBreaker.enable",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("不能为负数")
}
//  IdUtil.simpleUUID(); 等价于 UUID.randomUUID().toString();
String seriableNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName()+"\t"+"调用成功,流水号"+seriableNumber ;
}
public String paymetCiruitBreaker_Fallback(@PathVariable("id") Integer id){
	return "id 不能为负数,稍后再试";
}

服务监控 Hystrix Dashboard

Hystrix 还提供了准实时的调用监控(Hystrix Dashboard)功能,Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表的形式展示给用户,包括每秒执行请求的数量、成功请求的数量和失败请求的数量等。

  1. 在父工程下新建一个名为 micro-service-cloud-consumer-dept-hystrix-dashboard-9001 的子模块,并在其 pom.xml 中添加以下依赖。
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--Spring Boot 测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--hystrix-dashboard 监控的依赖-->
            <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-hystrix-dashboard</artifactId>
        </dependency>
        <!--添加 Spring Boot 的监控模块,所有provide微服务提供类都需要-->
                <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>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

  1. application.yml 中添加以下配置
server:
  port: 9002  #端口号
#http://eureka7001.com:9002/hystrix 熔断器监控页面
# localhost:8004//actuator/hystrix.stream 监控地址
hystrix:
  dashboard:
    proxy-stream-allow-list:
      - "localhost"
  1. 在 micro-service-cloud-consumer-dept-hystrix-dashboard-9002 的主启动类上添加 @EnableHystrixDashboard 注解,开启 Hystrix 监控功能,代码如下。
package net.biancheng.c;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class MicroServiceCloudConsumerDeptHystrixDashboard9002Application {
    public static void main(String[] args) {
        SpringApplication.run(MicroServiceCloudConsumerDeptHystrixDashboard9002Application.class, args);
    }
}
  1. 在 micro-service-cloud-provider-dept-hystrix-8004 的 net.biancheng.c.config 包下,创建一个名为 HystrixDashboardConfig 的配置类,代码如下:
package net.biancheng.c.config;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HystrixDashboardConfig {
    /**
     *  Hystrix dashboard 监控界面必须配置
     * @return
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");//访问路径
        registrationBean.setName("hystrix.stream");
        return registrationBean;
    }
}

pom文件添加依赖
         <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>

6.启动类中添加

/**
此配置微课服务监控而配置,与服务容错本身无关,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;
}
9001 监控8001 监控地址为 http://localhost:8001//hystrix.stream
  1. 启动 micro-service-cloud-consumer-dept-hystrix-dashboard-9002,使用浏览器访问“http://eureka7001.com:9002/hystrix”,结果如下图。在这里插入图片描述
  2. 重启 micro-service-cloud-provider-dept-hystrix-8004,并将以下信息填到 Hystrix 监控页面中,如下图。
    在这里插入图片描述
  3. 点击下方的 Monitor Stream 按钮,跳转到 Hystrix 对 micro-service-cloud-provider-dept-hystrix-8004 的监控页面,如下图
    在这里插入图片描述
  4. 使用浏览器多次访问“http://eureka7001.com:8004/dept/hystrix/circuit/1”和 “http://eureka7001.com:8004/dept/hystrix/circuit/-1”,查看 Hystrix 监控页面,如下图
    在这里插入图片描述

全局降级处理

controller添加注解@DefaultProperties(defaultFallback = "降级方法名称")

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值