spring cloud 断路器的作用是什么_react router 路由守卫

文章目录 Spring Cloud入门系列汇总 摘要 Hystrix 简介 创建一个hystrix-service模块 在pom.xml中添加相关依赖 在application.yml进行配置 在启动类上添加@EnableCircuitBreaker来开启Hystrix的断路器功能 创建UserHystrixController接口用于调用user-service服务 服务降级演示

项目使用的Spring Cloud为Hoxton版本,Spring Boot为2.2.2.RELEASE版本

Spring Cloud入门系列汇总

序号 内容 链接地址
1 Spring Cloud入门-十分钟了解Spring Cloud https://blog.csdn.net/ThinkWon/article/details/103715146
2 Spring Cloud入门-Eureka服务注册与发现(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103726655
3 Spring Cloud入门-Ribbon服务消费者(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103729080
4 Spring Cloud入门-Hystrix断路器(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103732497
5 Spring Cloud入门-Hystrix Dashboard与Turbine断路器监控(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103734664
6 Spring Cloud入门-OpenFeign服务消费者(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103735751
7 Spring Cloud入门-Zuul服务网关(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103738851
8 Spring Cloud入门-Config分布式配置中心(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103739628
9 Spring Cloud入门-Bus消息总线(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103753372
10 Spring Cloud入门-Sleuth服务链路跟踪(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103753896
11 Spring Cloud入门-Consul服务注册发现与配置中心(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103756139
12 Spring Cloud入门-Gateway服务网关(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103757927
13 Spring Cloud入门-Admin服务监控中心(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103758697
14 Spring Cloud入门-Oauth2授权的使用(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103761687
15 Spring Cloud入门-Oauth2授权之JWT集成(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103763364
16 Spring Cloud入门-Oauth2授权之基于JWT完成单点登录(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103766368
17 Spring Cloud入门-Nacos实现注册和配置中心(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103769680
18 Spring Cloud入门-Sentinel实现服务限流、熔断与降级(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103770879
19 Spring Cloud入门-Seata处理分布式事务问题(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103786102
20 Spring Cloud入门-汇总篇(Hoxton版本) https://blog.csdn.net/ThinkWon/article/details/103786588

摘要

Spring Cloud Netflix Hystrix 是Spring Cloud Netflix 子项目的核心组件之一,具有服务容错及线程隔离等一系列服务保护功能,本文将对其用法进行详细介绍。

Hystrix 简介

在微服务架构中,服务与服务之间通过远程调用的方式进行通信,一旦某个被调用的服务发生了故障,其依赖服务也会发生故障,此时就会发生故障的蔓延,最终导致系统瘫痪。Hystrix实现了断路器模式,当某个服务发生故障时,通过断路器的监控,给调用方返回一个错误响应,而不是长时间的等待,这样就不会使得调用方由于长时间得不到响应而占用线程,从而防止故障的蔓延。Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。

创建一个hystrix-service模块

这里我们创建一个hystrix-service模块来演示hystrix的常用功能。

在pom.xml中添加相关依赖

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId></dependency><dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>

在application.yml进行配置

主要是配置了端口、注册中心地址及user-service的调用路径。

server:  port: 8401spring:  application:    

name: hystrix-service

eureka: client: register-with-eureka: true fetch-registry: true service-url:

defaultZone: http://localhost:8001/eureka/

service-url:

user-service: http://user-service/

在启动类上添加@EnableCircuitBreaker来开启Hystrix的断路器功能

@EnableCircuitBreaker@EnableDiscoveryClient@SpringBootApplicationpublic class HystrixServiceApplication {    public static void main(String[] args) {        SpringApplication.run(HystrixServiceApplication.class, args);    }}

创建UserHystrixController接口用于调用user-service服务

此处省略了创建用户类User和统一返回前端的响应类Result,RestTemplate配置,UserService接口的创建,具体的可以参考项目源码

@RestController@RequestMapping("/user")public class UserHystrixController {    @Autowired    private UserService userService;    @GetMapping("/testFallback/{id}")    public Result testFallback(@PathVariable Long id) {        return userService.getUser(id);    }    @GetMapping("/testException/{id}")    public Result testException(@PathVariable Long id) {        return userService.getUserException(id);    }    @GetMapping("/testCommand/{id}")    public Result getUserCommand(@PathVariable Long id) {        return userService.getUserCommand(id);    }    @GetMapping("/testCache/{id}")    public Result testCache(@PathVariable Long id) {        userService.getUserCache(id);        userService.getUserCache(id);        userService.getUserCache(id);        return new Result("操作成功", 200);    }    @GetMapping("/testRemoveCache/{id}")    public Result testRemoveCache(@PathVariable Long id) {        userService.getUserCache(id);        userService.removeCache(id);        userService.getUserCache(id);        return new Result("操作成功", 200);    }    @GetMapping("/testCollapser")    public Result testCollapser() throws ExecutionException, InterruptedException {        Future<User> future1 = userService.getUserFuture(1L);        Future<User> future2 = userService.getUserFuture(2L);        future1.get();        future2.get();        ThreadUtil.safeSleep(200);        Future<User> future3 = userService.getUserFuture(3L);        future3.get();        return new Result("操作成功", 200);    }}

服务降级演示

在UserHystrixController中添加用于测试服务降级的接口:

@GetMapping("/testFallback/{id}")public Result testFallback(@PathVariable Long id) {return userService.getUser(id);}

在UserService中添加调用方法与服务降级方法,方法上需要添加@HystrixCommand注解:

@HystrixCommand(fallbackMethod = "fallbackMethod1")public Result getUser(Long id) {return restTemplate.getForObject(userServiceUrl + "/user/{1}", Result.class, id);}/** * 声明的参数需要包含controller的声明参数 * * @param id * @return */public Result fallbackMethod1(@PathVariable Long id) {return new Result("服务调用失败", 500);}

启动eureka-server、user-service、hystrix-service服务

在这里插入图片描述

调用接口进行测试:http://localhost:8401/user/testFallback/1

在这里插入图片描述

关闭user-service服务重新测试该接口,发现已经发生了服务降级:

在这里插入图片描述

@HystrixCommand详解

@HystrixCommand中的常用参数

  • fallbackMethod:指定服务降级处理方法;
  • ignoreExceptions:忽略某些异常,不发生服务降级;
  • commandKey:命令名称,用于区分不同的命令;
  • groupKey:分组名称,Hystrix会根据不同的分组来统计命令的告警及仪表盘信息;
  • threadPoolKey:线程池名称,用于划分线程池。

设置命令、分组及线程池名称

在UserHystrixController中添加测试接口:

@GetMapping("/testCommand/{id}")public Result getUserCommand(@PathVariable Long id) {return userService.getUserCommand(id);}

在UserService中添加方式实现功能:

@HystrixCommand(fallbackMethod = "fallbackMethod1",            commandKey = "getUserCommand",            groupKey = "getUserGroup",            threadPoolKey = "getUserThreadPool")public Result getUserCommand(Long id) {    return restTemplate.getForObject(userServiceUrl + "/user/{1}", Result.class, id);}

使用ignoreExceptions忽略某些异常降级

在UserHystrixController中添加测试接口:

@GetMapping("/testException/{id}")public Result testException(@PathVariable Long id) {return userService.getUserException(id);}

在UserService中添加实现方法,这里忽略了NullPointerException,当id为1时抛出IndexOutOfBoundsException,id为2时抛出NullPointerException:

@HystrixCommand(fallbackMethod = "fallbackMethod2", ignoreExceptions = {NullPointerException.class})public Result getUserException(Long id) {if (id == 1) {throw new IndexOutOfBoundsException();} else if (id == 2) {throw new NullPointerException();}return restTemplate.getForObject(userServiceUrl + "/user/{1}", Result.class, id);}public Result fallbackMethod2(@PathVariable Long id, Throwable e) {LOGGER.error("id {},throwable class:{}", id, e.getClass());return new Result("服务调用失败", 500);}

调用接口进行测试:http://localhost:8401/user/tesException/1

在这里插入图片描述

调用接口进行测试:http://localhost:8401/user/tesException/2

在这里插入图片描述

Hystrix的请求缓存

当系统并发量越来越大时,我们需要使用缓存来优化系统,达到减轻并发请求线程数,提供响应速度的效果。

相关注解

  • @CacheResult:开启缓存,默认所有参数作为缓存的key,cacheKeyMethod可以通过返回String类型的方法指定key;
  • @CacheKey:指定缓存的key,可以指定参数或指定参数中的属性值为缓存key,cacheKeyMethod还可以通过返回String类型的方法指定;
  • @CacheRemove:移除缓存,需要指定commandKey。

测试使用缓存

在UserHystrixController中添加使用缓存的测试接口,直接调用三次getUserCache方法:

@GetMapping("/testCache/{id}")public Result testCache(@PathVariable Long id) {userService.getUserCache(id);userService.getUserCache(id);userService.getUserCache(id);return new Result("操作成功", 200);}

在UserService中添加具有缓存功能的getUserCache方法:

@CacheResult(cacheKeyMethod = "getCacheKey")@HystrixCommand(fallbackMethod = "fallbackMethod1", commandKey = "getUserCache")public Result getUserCache(Long id) {LOGGER.info("getUserCache id:{}", id);return restTemplate.getForObject(userServiceUrl + "/user/{1}", Result.class, id);}/** * 为缓存生成key的方法 * * @return */public String getCacheKey(Long id) {return String.valueOf(id);}

调用接口测试http://localhost:8401/user/testCache/1,这个接口中调用了三次getUserCache方法,但是只打印了一次日志,说明有两次走的是缓存:

在这里插入图片描述

测试移除缓存

在UserHystrixController中添加移除缓存的测试接口,调用一次removeCache方法:

@GetMapping("/testRemoveCache/{id}")public Result testRemoveCache(@PathVariable Long id) {userService.getUserCache(id);userService.removeCache(id);userService.getUserCache(id);return new Result("操作成功", 200);}

在UserService中添加具有移除缓存功能的removeCache方法:

@HystrixCommand@CacheRemove(commandKey = "getUserCache", cacheKeyMethod = "getCacheKey")public Result removeCache(Long id) {LOGGER.info("removeCache id:{}", id);return restTemplate.postForObject(userServiceUrl + "/user/delete/{1}", null, Result.class, id);}

调用接口测试http://localhost:8401/user/testRemoveCache/1,可以发现有两次查询都走的是接口:

在这里插入图片描述

缓存使用过程中的问题

在缓存使用过程中,我们需要在每次使用缓存的请求前后对HystrixRequestContext进行初始化和关闭,否则会出现如下异常:

java.lang.IllegalStateException: Request caching is not available. Maybe you need to initialize the HystrixRequestContext?at com.netflix.hystrix.HystrixRequestCache.get(HystrixRequestCache.java:104) ~[hystrix-core-1.5.18.jar:1.5.18]at com.netflix.hystrix.AbstractCommand$7.call(AbstractCommand.java:478) ~[hystrix-core-1.5.18.jar:1.5.18]at com.netflix.hystrix.AbstractCommand$7.call(AbstractCommand.java:454) ~[hystrix-core-1.5.18.jar:1.5.18]

这里我们通过使用过滤器,在每个请求前后初始化和关闭HystrixRequestContext来解决该问题:

@Component@WebFilter(urlPatterns = "/*", asyncSupported = true)public class HystrixRequestContextFilter implements Filter {    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        HystrixRequestContext context = HystrixRequestContext.initializeContext();        try {            filterChain.doFilter(servletRequest, servletResponse);        } finally {            context.close();        }    }}

请求合并

微服务系统中的服务间通信,需要通过远程调用来实现,随着调用次数越来越多,占用线程资源也会越来越多。Hystrix中提供了@HystrixCollapser用于合并请求,从而达到减少通信消耗及线程数量的效果。

@HystrixCollapser的常用属性

  • batchMethod:用于设置请求合并的方法;
  • collapserProperties:请求合并属性,用于控制实例属性,有很多;
  • timerDelayInMilliseconds:collapserProperties中的属性,用于控制每隔多少时间合并一次请求;

功能演示

在UserHystrixController中添加testCollapser方法,这里我们先进行两次服务调用,再间隔200ms以后进行第三次服务调用:

@GetMapping("/testCollapser")public Result testCollapser() throws ExecutionException, InterruptedException {Future<User> future1 = userService.getUserFuture(1L);Future<User> future2 = userService.getUserFuture(2L);future1.get();future2.get();ThreadUtil.safeSleep(200);Future<User> future3 = userService.getUserFuture(3L);future3.get();return new Result("操作成功", 200);}

使用@HystrixCollapser实现请求合并,所有对getUserFuture的的多次调用都会转化为对getUserByIds的单次调用:

@HystrixCollapser(batchMethod = "listUsersByIds",collapserProperties = {@HystrixProperty(name = "timerDelayInMilliseconds",value = "100")})public Future<User> getUserFuture(Long id) {return new AsyncResult<User>() {@Overridepublic User invoke() {Result result = restTemplate.getForObject(userServiceUrl + "/user/{1}", Result.class, id);Map data = (Map) result.getData();User user = BeanUtil.mapToBean(data, User.class, true);LOGGER.info("getUserById username:{}",user.getUsername());return user;}};}@HystrixCommandpublic List<User> listUsersByIds(List<Long> ids) {LOGGER.info("listUsersByIds:{}",ids);Result result = restTemplate.getForObject(userServiceUrl + "/user/listUsersByIds?ids={1}", Result.class, CollUtil.join(ids, ","));return (List<User>)result.getData();}

注意:测试之前需要重启user-service服务,因为刚才测试请求缓存把数据删了一个,不然会报错

访问接口测试http://localhost:8401/user/testCollapser,由于我们设置了100毫秒进行一次请求合并,前两次被合并,最后一次自己单独合并了。

在这里插入图片描述

Hystrix的常用配置

全局配置

hystrix:  command: #用于控制HystrixCommand的行为    default:      execution:        isolation:          strategy: THREAD #控制HystrixCommand的隔离策略,THREAD->线程池隔离策略(默认),SEMAPHORE->信号量隔离策略          thread:            timeoutInMilliseconds: 1000 #配置HystrixCommand执行的超时时间,执行超过该时间会进行服务降级处理            interruptOnTimeout: true #配置HystrixCommand执行超时的时候是否要中断            interruptOnCancel: true #配置HystrixCommand执行被取消的时候是否要中断          timeout:            enabled: true #配置HystrixCommand的执行是否启用超时时间          semaphore:            maxConcurrentRequests: 10 #当使用信号量隔离策略时,用来控制并发量的大小,超过该并发量的请求会被拒绝      fallback:        enabled: true #用于控制是否启用服务降级      circuitBreaker: #用于控制HystrixCircuitBreaker的行为        enabled: true #用于控制断路器是否跟踪健康状况以及熔断请求        requestVolumeThreshold: 20 #超过该请求数的请求会被拒绝        forceOpen: false #强制打开断路器,拒绝所有请求        forceClosed: false #强制关闭断路器,接收所有请求      requestCache:        enabled: true #用于控制是否开启请求缓存  collapser: #用于控制HystrixCollapser的执行行为    default:      maxRequestsInBatch: 100 #控制一次合并请求合并的最大请求数      timerDelayinMilliseconds: 10 #控制多少毫秒内的请求会被合并成一个      requestCache:        enabled: true #控制合并请求是否开启缓存  threadpool: #用于控制HystrixCommand执行所在线程池的行为    default:      coreSize: 10 #线程池的核心线程数      maximumSize: 10 #线程池的最大线程数,超过该线程数的请求会被拒绝      maxQueueSize: -1 #用于设置线程池的最大队列大小,-1采用SynchronousQueue,其他正数采用LinkedBlockingQueue      queueSizeRejectionThreshold: 5 #用于设置线程池队列的拒绝阀值,由于LinkedBlockingQueue不能动态改版大小,使用时需要用该参数来控制线程数

实例配置

实例配置只需要将全局配置中的default换成与之对应的key即可。

hystrix:  command:    HystrixComandKey: #将default换成HystrixComrnandKey      execution:        isolation:          

strategy: THREAD

collapser: HystrixCollapserKey: #将default换成HystrixCollapserKey maxRequestsInBatch: 100 threadpool: HystrixThreadPoolKey: #将default换成HystrixThreadPoolKey coreSize: 10

配置文件中相关key的说明

  • HystrixComandKey对应@HystrixCommand中的commandKey属性;
  • HystrixCollapserKey对应@HystrixCollapser注解中的collapserKey属性;
  • HystrixThreadPoolKey对应@HystrixCommand中的threadPoolKey属性。

使用到的模块

springcloud-learning

├── eureka-server -- eureka注册中心

├── user-service -- 提供User对象CRUD接口的服务

└── hystrix-service -- hystrix服务调用测试服务

项目源码地址

GitHub项目源码地址

知秋君
上一篇 2024-07-03 15:30
下一篇 2024-07-03 15:30

相关推荐