Hystrix服务熔断与服务降级的实现

在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。

Hystrix 的异常处理中,有5种出错的情况下会被 fallback 所截获,从而触发 fallback,这些情况是:

FAILURE:执行失败,抛出异常。
TIMEOUT:执行超时。
SHORT_CIRCUITED:断路器打开。
THREAD_POOL_REJECTED:线程池拒绝。
SEMAPHORE_REJECTED:信号量拒绝。
服务熔断:

当某个服务单元发生故障之后,通过断路器的故障监控,某个异常条件被触发,直接熔断整个服务。向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出吊牌用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。服务熔断是配置于服务端的防范机制。

我们创建一个带有熔断机制的provider服务:

在这里插入图片描述
所需依赖:

 <!-- openfeign -->
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <!-- eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

配置文件:

server:
  port: 8003

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: cn.kgc.zhx.pojo
spring:
  application:
    name: springcloud-provider001
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/springcloudtest?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimeZone=UTC
    driver-class-name: org.gjt.mm.mysql.Driver
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
#=================================eureka===================================
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/

info:
  name: ZhangHaoxiang's Provider-8003
  service: About Dept

添加主启动类注解@EnableHystrix:

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix//开启熔断机制
public class ProviderHystrixMain8003 {
    public static void main(String[] args) {
        SpringApplication.run(ProviderHystrixMain8003.class,args);
    }
}

provider服务的dao层和service层与熔断无关,我就不再演示。

编写controller层,核心注解 @HystrixCommand:

@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;

	//正常的功能方法
    @GetMapping("/dept/select/{id}")
    //这个注解的作用就是,在触发熔断机制时,去找备选响应
    @HystrixCommand(fallbackMethod = "hystrixSelect")
    public CommonResult selectById(@PathVariable int id){
        CommonResult<Dept> commonResult=new CommonResult<Dept>();
        Dept dept = deptService.selectById(id);
        if (dept!=null){
            commonResult.setData(dept);
            commonResult.setMessage("8003查询成功!");
            commonResult.setCode(200);
            return commonResult;
        }else {
        	//通过抛出异常触发熔断机制
            throw new RuntimeException("没有相关信息,dept==null");
        }
    }
	//备选响应
    public CommonResult hystrixSelect(@PathVariable int id){
        return new CommonResult(444,"hystrix返回:没有查询到相关信息");
    }

运行服务并测试:

首先我们查询一个数据库存在的dept
在这里插入图片描述
然后查询一个数据库不存在的dept
在这里插入图片描述
可以看出这里触发熔断机制,调用了备选服务。

服务降级:

服务降级处理是在客户端实现完成的,与服务端没有关系,整体资源快不够了,忍痛将某些服务单元先关掉,关闭后还要返回一些可处理的备选方法,待渡过难关,再开启回来。

我们创建一个带有服务降级机制的consumer客户端:
在这里插入图片描述所需依赖:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <!--hystrix(openfeign整合了hystrix,所以这个依赖可以不添加) -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <!-- eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

配置文件:

server:
  port: 8080

#======================eureka========================
eureka:
  client:
    register-with-eureka: false
    service-url:
      #注册中心地址
      defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/


#====================hystrix============================
feign:
  hystrix:
    #开启服务降级
    enabled: true

主启动类添加@EnableFeignClients注解。

@SpringBootApplication
@EnableFeignClients //开启Feign
public class ConsumerFeignMain {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeignMain.class,args);
    }
}

然后我们需要编写一个服务降级时调用的fallback服务工厂。

这里的实现需要基于feign,不了解feign的可以看一下我之前的博客

在这里插入图片描述
这里需要继承FallbackFactory接口,并返回我们所需要降级的整个服务的备选方案。也就是DeptFeignService的实现。当客户端在注册中心调用此服务,发现服务已经被关闭时,将会执行此备选服务。

@Component
public class DeptFallBackFactory implements FallbackFactory {
    @Override
    public Object create(Throwable throwable) {
        return new DeptFeignService() {
            @Override
            public CommonResult selectById(int id) {
                return new CommonResult(444,"服务已关闭,触发服务降级");
            }
            @Override
            public CommonResult add(Dept dept) {
                return new CommonResult(444,"服务已关闭,触发服务降级");
            }
        };
    }
}

编写完成后,进行测试。

provider服务开启的情况下:

在这里插入图片描述
关闭provider服务:
在这里插入图片描述
在这里插入图片描述
触发服务降级。

有很多小伙伴弄不懂为啥说服务熔断是作用于服务端,服务降级是作用于客户端。其实很好理解。服务熔断的触发条件是客户端的请求已经到达了provider服务,但provider服务端由于某种原因触发了熔断机制,执行备选服务,返回给客户端一个结果,所以说熔断机制是在服务端触发的。但服务降级是服务端已经完全关闭服务,不可能再执行任何操作,由于客户端根本找不到服务端提供的服务,自己给自己生成的一套备选返回方案,所以是在客户端本身触发的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值