Spring Cloud 入门之 Hystrix(四) 附源码

Spring Cloud 入门之 Hystrix(四) 附源码

绿林寻猫
2021-12-08 / 0 评论 / 289 阅读 / 正在检测是否收录...

一、前言

在微服务应用中,服务存在一定的依赖关系,如果某个目标服务调用慢或者有大量超时造成服务不可用,间接导致其他的依赖服务不可用,最严重的可能会阻塞整条依赖链,最终导致业务系统崩溃(又称雪崩效应)。

上述的问题将是本篇需要解决的问题。

二、简单介绍

# 2.1 请求熔断

断路器是一种开关设置,当某个服务单元发生故障之后,通过断路器的故障监控,向调用方返回一个符合预期的服务降级处理(fallback),而不是长时间的等待或者抛出调用方无法处理的异常,这样保证了服务调用方的线程不会长时间被占用,从而避免了故障在分布式系统的蔓延乃至崩溃。

# 2.2 服务降级

fallback 相当于是降级操作。对于查询操作, 我们可以实现一个 fallback 方法, 当请求后端服务出现异常的时候, 可以使用 fallback 方法返回的值。 fallback 方法的返回值一般是设置的默认值或者来自缓存,告知后面的请求服务不可用了,不要再请求了。

# 2.3 请求熔断和服务降级区别

相同:

  1. 目标一致:为了防止系统崩溃而实施的一种防御手段

  2. 表现形式一致:当请求目标在一定时间内无响应时,返回或执行默认响应内容

不同:

  1. 触发条件不同:下游服务出现故障触发请求熔断。系统负荷超过阈值触发服务降级。

  2. 管理目标层次不同:请求熔断针对所有微服务。服务降级针对整个系统中的外围服务。

2.4 实现方案

Spring Cloud Hystrix 实现了断路器、线程隔离等一系列服务保护功能。它是基于 Netflix 的开源框架 Hystrix 实现的,该框架的目的在于通过控制访问远程系统、服务和第三方库节点,从而对延迟和故障提供更强大的容错能力。

Hystrix 具备服务熔断、服务降级、线程和信号隔离、请求缓存、请求合并以及服务监控的能力。

本次测试基于之前发表的文章,不清楚请移步Spring Cloud 入门 之 Feign(三)

三、请求熔断实战

3.1在“消费者”中添加依赖:

<!-- hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

3.2设置熔断策略

 方法上加 @HystrixCommand 注解:

@Service
public class UserServiceImpl implements IUserService {
    @Autowired
    private ApiFeign apiFeign;

    @HystrixCommand(fallbackMethod = "defaultSelect")
    @Override
    public User select(Integer uId) {
        return apiFeign.select(uId);
    }

    public User defaultSelect() {
        User user = new User();
        user.setuId(-1);
        user.setuName("没有数据");
        return user;
    }
}

当调用服务超时或出现异常时,Hystrix 会调用 @HystrixCommand 中指定的 fallbackMethod 方法获取返回值或执行异常处理。

注意:fallbackMethod 方法要求与正常方法有相同的入参和回参。

3.3 启动熔断功能

在启动类上添加 @EnableCircuitBreaker 注解:

@EnableFeignClients(basePackages = {"com.web.demo"})
@EnableEurekaClient
@EnableHystrix
@SpringBootApplication
public class DemoApplication {

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

}

3.4 熔断测试

  1. 我们首先演示没有开启熔断的功能,即先把上边的 @EnableCircuitBreaker 注解进行注释。

2.再将 @EnableCircuitBreaker 注解的注释放开

请求一个没有的用户ID

从图中可知,虽然请求了一个  不存在的id,但是调用方(消费者)开启了熔断机制,执行默认方法,从而使接口能正常通信而不是抛出调用方不可处理的异常导致整个系统不能正常运行。

看到这里,或许会有读者产生一个疑问,如果类中定义 N 个方法,是不是意味着同时也要定义 N 个异常处理的方法呢,答案是否定的。

Hystrix 还提供了 @DefaultProperties 统一处理请求熔断,在该注解上设置 defaultFallback 属性值,即熔断开启后要执行的方法。

@DefaultProperties(defaultFallback  = "defaultSelect")
@Service
public class UserServiceImpl implements IUserService {
    @Autowired
    private ApiFeign apiFeign;

    @HystrixCommand
    @Override
    public User select(Integer uId) {
        return apiFeign.select(uId);
    }

    public User defaultSelect() {
        User user = new User();
        user.setuId(-1);
        user.setuName("没有数据");
        return user;
    }
}

注意:defaultFallback 定义的方法必须是无参的。

四、服务降级实战

4.1定义 Fallback

@Component
public class UserClientFallbackFactory implements FallbackFactory<ApiFeign> {
    @Override
    public ApiFeign create(Throwable throwable) {
        return new ApiFeign() {
            @Override
            public User select(Integer uId) {
                System.out.println(uId);
                User user = new User();
                user.setuName("哈哈哈哈哈");
                return user;
            }
        };
    }
}

使用单独的类处理异常逻辑,当与服务端无法正常通信时调用此类中的方法返回结果

4.2修改 Feign 客户端

将上边定义好的 FallbackFactory 设置到 @FeignClient 注解上:

@FeignClient(value = "PROVIDER",fallbackFactory = UserClientFallbackFactory.class)
public interface ApiFeign {

    @RequestMapping(value ="/user/get/" )
    User select(@RequestParam("uId") Integer uId);
}

4.3开启服务降级功能

server:
  port: 80

spring:
  application:
    name: api

eureka:
  client:
#    register-with-eureka: false # 不向注册中心注册自己
    fetch-registry: true        # 是否检索服务
    service-url:
      defaultZone: http://localhost:9000/eureka/  # 注册中心访问地址

feign:
  hystrix:
    enabled: true #开启服务降级功能
  client:
    config:
      default:
        connect-timeout: 10000
        read-timeout: 20000
      service-test:
        connect-timeout: 10000
        read-timeout: 20000

4.4去掉 @HystrixCommand 配置

//@DefaultProperties(defaultFallback  = "defaultSelect")
@Service
public class UserServiceImpl implements IUserService {
    @Autowired
    private ApiFeign apiFeign;

//    @HystrixCommand
    @Override
    public User select(Integer uId) {
        System.out.println(uId);
        return apiFeign.select(uId);
    }

    public User defaultSelect() {
        User user = new User();
        user.setuId(-1);
        user.setuName("没有数据");
        return user;
    }
}

4.5测试

在启动类上加 FallbackFactory 类的包扫描目录

Postman测试:请求一个没有的用户ID

 

 

5.仪表盘

除了服务熔断、降级的功能外,Hystrix 还提供了准及时的调用监控。 Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表和图形方式展示给用户。

5.1 配置被监控方

API项目中:

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

修改 application.yml

management:
  endpoints:
    web:
      exposure:
        include: "*"

5.2 配置监控方

创建一个名为dashboard 的项目,添加依赖

<!-- hystrix-dashboard -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

新建 application.yml

server:
  port: 3333

spring:
  application:
    name: Hystrix-Dashboard

开启监控功能

在启动类上添加 @EnableHystrixDashboard 注解

@EnableHystrixDashboard
@SpringBootApplication
public class DashboardApplication {

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

}

启动,浏览器访问: http://127.0.0.1:3333/hystrix

 

监控设置

# 需要监控的服务地址
http://localhost:80/actuator/hystrix.stream

delay: 请求间隔时间

title: 监控名称

点击 monitor stream

批量访问 order-server 服务的下单接口。

 

刚开始进来如果没有调用接口,界面是这样的:

调用接口之后:

 

六案例源码

demo

 

 

0

评论 (0)

取消