SpringCloud(Hystrix) 今天药忘吃喽~ 2021-11-19 11:28 382阅读 0赞 ### Hystrix 熔断器 ### * * 1. Hystrix 介绍 * * 1.1 是什么: * 1.2 Hystrix设计原则: * 1.3 Hystrix特性 * 2. 图解 * 3. SpringCloud 集成Hystrix * * 3.1 maven依赖 * 3.2 添加注解 * 3.Hystrix的服务熔断 * 4. Hystrix的服务降级 * 5. Hystrix的异常处理 * * 5.1 未调用远程服务前发生异常 * 5.2 调用远程服务发生异常 * 5.3 忽略异常 * 5.4 自定义Hystrix的服务异常熔断 * * 5.4.1 同步调用 * 5.4.1 异步调用 * 6. Hystrix的仪表盘监控 * * 6.1 添加maven依赖 * 6.2 启动类添加注解 * 6.3 配置文件中配置服务端口号 * 6.4 配置要监控的项目 * * 6.4.1 首先需要引入Hystrix以及Dashboard的依赖 * 6.4.1 修改需要监控的项目配置 ## 1. Hystrix 介绍 ## ### 1.1 是什么: ### 在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。**简单点说**:*就是当被调用方没有响应,向调用方直接返回一个错误响应即可,而不是长时间的等待,这样避免调用时因为等待而线程一直得不到释放。* ### 1.2 Hystrix设计原则: ### * 1.防止单个服务的故障,耗尽整个系统服务的容器(比如tomcat)的线程资源,避免分布式环境里大量级联失败。通过第三方客户端访问(通常是通过网络)依赖服务出现失败、拒绝、超时或短路时执行回退逻辑 * 2.用快速失败代替排队(每个依赖服务维护一个小的线程池或信号量,当线程池满或信号量满,会立即拒绝服务而不会排队等待)和优雅的服务降级;当依赖服务失效后又恢复正常,快速恢复 * 3.提供接近实时的监控和警报,从而能够快速发现故障和修复。监控信息包括请求成功,失败(客户端抛出的异常),超时和线程拒绝。如果访问依赖服务的错误百分比超过阈值,断路器会跳闸,此时服务会在一段时间内停止对特定服务的所有请求 * 4.将所有请求外部系统(或请求依赖服务)封装到HystrixCommand或HystrixObservableCommand对象中,然后这些请求在一个独立的线程中执行。使用隔离技术来限制任何一个依赖的失败对系统的影响。每个依赖服务维护一个小的线程池(或信号量),当线程池满或信号量满,会立即拒绝服务而不会排队等待 ### 1.3 Hystrix特性 ### * 1.请求熔断: 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力. * 2.服务降级:Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。 * 3.依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种):在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.比如说,一个服务调用两外两个服务,你如果调用两个服务都用一个线程池,那么如果一个服务卡在哪里,资源没被释放后面的请求又来了,导致后面的请求都卡在哪里等待,导致你依赖的A服务把你卡在哪里,耗尽了资源,也导致了你另外一个B服务也不可用了。这时如果依赖隔离,某一个服务调用A B两个服务,如果这时我有100个线程可用,我给A服务分配50个,给B服务分配50个,这样就算A服务挂了,我的B服务依然可以用。 * 4.请求缓存:比如一个请求过来请求我userId=1的数据,你后面的请求也过来请求同样的数据,这时我不会继续走原来的那条请求链路了,而是把第一次请求缓存过了,把第一次的请求结果返回给后面的请求。 * 5.请求合并:我依赖于某一个服务,我要调用N次,比如说查数据库的时候,我发了N条请求发了N条SQL然后拿到一堆结果,这时候我们可以把多个请求合并成一个请求,发送一个查询多条数据的SQL的请求,这样我们只需查询一次数据库,提升了效率。 ## 2. 图解 ## 以下数据、图来自官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.3.5.RELEASE/single/spring-cloud-netflix.html#_circuit_breaker_hystrix_clients Netfilix创建了一个名为Hystrix的库,实现了熔断器模式。在微服务架构中,它通常有多个服务调用层。 > 微服务图 > ![微服务图][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70] > Hystrix回退以防止连锁故障 > ![Hystrix回退以防止连锁故障][Hystrix] > 一个底层服务的故障会引发直至用户交互层的连锁故障。在一个设定时长为“metrics.rollingStats.timeInMilliseconds”(默认为十秒)的滚动窗口内,对一个特定服务的请求数大于“circuitBreaker.requestVolumeThreshold”(默认为20个),并且故障率大于“circuitBreaker.errorThresholdPercentage”(默认大于百分之五十)的时候,启用熔断机制以使请求失效。在熔断和报错的情况下,开发者可以启用回退机制。 > 启用熔断机制能防止连锁故障的情况,给故障服务提供时间以恢复正常。回退操作可以是另一个Hystrix受保护的调用、静态数据或是一个恰当的空值。回退操作可能是成串的,所以第一个回退操作会做一些其他的业务请求,让故障回退到预设的值。 ## 3. SpringCloud 集成Hystrix ## ### 3.1 maven依赖 ### > 注意:添加maven依赖时,注意查看自己的SpringBoot 项目是什么版本的,因为 ServerPropertiesAutoConfiguration 在SpringBoot 2.x.x 移除了。如果你的SpringBoot 版本是2.x.x版本就不要引入这个依赖 <!--旧版本使用的--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>1.4.7.RELEASE</version> </dependency> > 注意:应该引入以下这个版本。(别问我为什么知道?因为我就引错了。。。启动报错:org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class \[com.kinglong.springcloud.ComsumerApplication\]; nested exception is java.io.FileNotFoundException: class path resource \[org/springframework/boot/autoconfigure/web/ServerPropertiesAutoConfiguration.class\] cannot be opened because it does not exist > at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:596) ~\[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE\]。 > 这个问题看官方文档的话,应该可以避免,见下图:) > ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70 1] <!--正确版本,应该是netflix的--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.1.2.RELEASE</version> </dependency> ### 3.2 添加注解 ### > Boot app 样例: **启动类** /** * @SpringBootApplication * @EnableEurekaClient//eureka客户端支持 * @EnableCircuitBreaker//开启熔断器 * 这三个注解在SpringCloud里可以合并为一个注解:@SpringCloudApplication,效果等同于这三个注解 */ @SpringCloudApplication public class ComsumerApplication { public static void main(String[] args) { SpringApplication.run(ComsumerApplication.class, args); } } **解释**:为什么可以这样呢?进入这个注解@SpringCloudApplication内部看可以看到: @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootApplication @EnableDiscoveryClient //此注解作用和@EnableEurekaClient一样,但是还将可以主持其他服务注册器 @EnableCircuitBreaker public @interface SpringCloudApplication { } ### 3.Hystrix的服务熔断 ### /** * web api * * @author haojinlong */ @RestController @RequestMapping("/api/webs") public class WebController { @Autowired private RestTemplate restTemplate; /** * @HystrixCommand由Netflix contrib library提供,被称作“javanica” * Spring Cloud会自动将包含该注释的Spring bean封装在连接到Hystrix熔断器的代理中 * 熔断器会计算何时启用或关闭熔断机制,并决定在故障时该做什么。 * 在需要考虑熔断的方法上加上该注解即可,fallbackMethod 为回退时的指定操作方法; * commandProperties:指定超时熔断时间; * * @return */ @RequestMapping("/hello") @HystrixCommand(fallbackMethod = "error",commandProperties = {@HystrixProperty (name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})//1.5秒超时 public String hello() { return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello", String.class).getBody(); } /** * 熔断的回调方法,也就是降级方法 * @return */ public String error(){ //访问远程服务失败,处理逻辑写在这里即可 return "error"; } } ## 4. Hystrix的服务降级 ## 前文提到过:Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。这种做法,虽然不能得到正确的返回结果,但至少保证了服务的可用性,比直接抛出错误或服务不可用要好很多,可以根据业务场景自行选择。 ## 5. Hystrix的异常处理 ## 我们在调用服务提供者时,我们自己也有可能会抛出异常,默认情况下方法抛出了异常会自动进行服务降级,交给服务降级中的方法去处理。当我们自己发生异常后,只需要在服务降级方法中添加一个Throwable类型的参数就能够获取抛出的异常的类型。 ### 5.1 未调用远程服务前发生异常 ### 我们在上文的代码中模拟一个异常 /** * @HystrixCommand由Netflix contrib library提供,被称作“javanica” * Spring Cloud会自动将包含该注释的Spring bean封装在连接到Hystrix熔断器的代理中 * 熔断器会计算何时启用或关闭熔断机制,并决定在故障时该做什么。 * * @return */ @RequestMapping("/hello") @HystrixCommand(fallbackMethod = "error", commandProperties = {@HystrixProperty (name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})//1.5秒超时 public String hello() { int i= 10/0; return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello", String.class).getBody(); } /** * 熔断的回调方法,也就是降级方法 * @return */ public String error(){ //访问远程服务失败,处理逻辑写在这里即可 return "error"; } 测试显示,未调用前发生异常也会触发熔断,调用服务是不会触发的,直接抛出运行时异常,并且可以在降级方法里获取到这个异常。 ### 5.2 调用远程服务发生异常 ### 将某个远程服务加入异常代码。测试显示,效果如上,可以在降级方法里获取到这个异常。 ### 5.3 忽略异常 ### ignoreExceptions = RuntimeException.class 忽略异常,这样可以避免调用降级方法,根据业务场景选择 /** * web api * * @author haojinlong */ @RestController @RequestMapping("/api/webs") public class WebController { @Autowired private RestTemplate restTemplate; /** * @HystrixCommand由Netflix contrib library提供,被称作“javanica” * Spring Cloud会自动将包含该注释的Spring bean封装在连接到Hystrix熔断器的代理中 * 熔断器会计算何时启用或关闭熔断机制,并决定在故障时该做什么。 * 在需要考虑熔断的方法上加上该注解即可,fallbackMethod 为回退时的指定操作方法; * commandProperties:指定超时熔断时间; * ignoreExceptions = RuntimeException.class 忽略异常,这样可以避免调用降级方法,根据业务场景选择 * * @return */ @RequestMapping("/hello") @HystrixCommand(fallbackMethod = "error",ignoreExceptions = RuntimeException.class, commandProperties = {@HystrixProperty (name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})//1.5秒超时 public String hello() { return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello", String.class).getBody(); } /** * 熔断的回调方法,也就是降级方法 * @return */ public String error(){ //访问远程服务失败,处理逻辑写在这里即可 return "error"; } } ### 5.4 自定义Hystrix的服务异常熔断 ### 自定义类继承HystrixCommand类来实现自定义的Hystrix的请求,在getFallback方法中调用getExecutionException()方法获取服务抛出异常。 #### 5.4.1 同步调用 #### /** * web api * * @author haojinlong */ @RestController @RequestMapping("/api/webs") public class WebController { @Autowired private RestTemplate restTemplate; /** * com.netflix.hystrix.HystrixCommand用全路径引用类是防止和@HystrixCommand这个注解混淆 * MyHystrixCommand自定义熔断器 * execute()调用是同步调用,会一直等待返回结果 * * @return */ @RequestMapping("/hystrix") public String hystrix() { return new MyHystrixCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")), restTemplate, "http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello").execute(); } } #### 5.4.1 异步调用 #### /** * web api * * @author haojinlong */ @RestController @RequestMapping("/api/webs") public class WebController { @Autowired private RestTemplate restTemplate; /** * com.netflix.hystrix.HystrixCommand用全路径引用类是防止和@HystrixCommand这个注解混淆 * MyHystrixCommand自定义熔断器 * execute()调用是同步调用,会一直等待返回结果 * * @return */ @RequestMapping("/hystrix") public String hystrix() { Future<String> queue = new MyHystrixCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")), restTemplate, "http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello").queue(); String data = queue.get(20000, TimeUnit.MILLISECONDS); return data; } } 自定义熔断器 package com.kinglong.springcloud.hystrix; import com.netflix.hystrix.HystrixCommand; import org.springframework.web.client.RestTemplate; /** * 自定义的Hystrix * * @author haojinlong */ public class MyHystrixCommand extends HystrixCommand<String> { private RestTemplate restTemplate; private String url; public MyHystrixCommand (Setter setter, RestTemplate restTemplate){ super(setter); this.restTemplate = restTemplate; } public MyHystrixCommand (Setter setter, RestTemplate restTemplate, String url){ super(setter); this.restTemplate = restTemplate; this.url = url; } @Override protected String run() throws Exception { //调用远程的服务 return restTemplate.getForEntity(url, String.class).getBody(); } /** * 当远程服务超时、异常、不可用时,调用该方法 * * @return */ @Override protected String getFallback() { //实现服务熔断、降级处理 return "error"; } } ## 6. Hystrix的仪表盘监控 ## 在微服务架构中为例保证程序的可用性,防止程序出错导致网络阻塞,出现了断路器模型。断路器的状况反应了一个程序的可用性和健壮性,它是一个重要指标。Hystrix Dashboard是作为断路器状态的一个组件,提供了数据监控和友好的图形化界面。通过监控该面板,可以很直观的看到每一个服务请求在短时间内(10s)的请求量,以及成功率,失败率,耗时等信息,可以给后期的系统优化提供依据。 > 这个服务搭建十分快速,使用SpringBoot搭建三步走即可(我是新建的一个项目) ### 6.1 添加maven依赖 ### maven依赖最新版本即可 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> <version>2.1.2.RELEASE</version> </dependency> ### 6.2 启动类添加注解 ### @SpringBootApplication @EnableHystrixDashboard//打开仪表盘功能 public class DashBoardApplication { public static void main(String[] args) { SpringApplication.run(DashBoardApplication.class, args); } } ### 6.3 配置文件中配置服务端口号 ### server.port=3721 大功告成,然后起服即可(访问路径为:[http://localhost:3721/hystrix][http_localhost_3721_hystrix] ,记得加上 **/hystrix** 路径),页面如下图所示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70 2] ### 6.4 配置要监控的项目 ### #### 6.4.1 首先需要引入Hystrix以及Dashboard的依赖 #### <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.1.2.RELEASE</version> </dependency> <!--springboot提供的一个健康检查监控的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> #### 6.4.1 修改需要监控的项目配置 #### #用来暴露endpoints的,由于endpoints包含很多敏感信息,除了health、info两个支持直接访问外,其他的默认不支持直接访问,可以指定某个端点访问,如下 #management.endpoints.web.exposure.include=hystrix.stream #现在做测试,所以用通配符,可以访问所有端点 management.endpoints.web.exposure.include=* **至此,就配置好了** 剩下的就是在先前的web页面里添加这个路径即可:[http://localhost:8081/actuator/hystrix.stream][http_localhost_8081_actuator_hystrix.stream] ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70 3] 配置后,点击监控即可。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70 4] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70]: /images/20211119/1d509c66d5e34f5ca6a6433e1465da10.png [Hystrix]: /images/20211119/15ed8a43f0c147deaa5e02daa46912cb.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70 1]: /images/20211119/922a0a94bb534368958aa64c9416aa17.png [http_localhost_3721_hystrix]: http://localhost:3721/hystrix [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70 2]: /images/20211119/fd384b57ffeb4de09a806d15107066ed.png [http_localhost_8081_actuator_hystrix.stream]: http://localhost:8081/actuator/hystrix.stream [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70 3]: /images/20211119/b3eca0a34bad40d8939cbf1c811f92da.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hqbDAyMQ_size_16_color_FFFFFF_t_70 4]: /images/20211119/2aafb75a700243ac918e8f4f612c0c6f.png
还没有评论,来说两句吧...