Spring Cloud Hystrix服务容错保护(七)

Hystrix 官方简介:熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与订阅的方式互相依赖。由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,线程资源无法释放,最终导致自身服务的瘫痪,进一步甚至出现故障的蔓延最终导致整个系统的瘫痪。如果这样的架构存在如此严重的隐患,那么相较传统架构就更加的不稳定。为了解决这样的问题,因此产生了断路器等一系列的服务保护机制。

针对上述问题,在Spring Cloud Hystrix中实现了线程隔离、断路器等一系列的服务保护功能。它也是基于Netflix的开源框架 Hystrix实现的,该框架目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备了服务降级、服务熔断、线程隔离、请求缓存、请求合并以及服务监控等强大功能
个人总结:叫断路器容易理解点。类似于物理电路图中的断路器。Feign默认集成了hystrix。
情景描述:(一)正常情况下,当整个服务环境中,某一个服务提供方由于网络原因、数据库原因或者性能原因等,造成响应很慢的话,调用方就有可能短时间内累计大量的请求线程,最终造成调用方down,甚至整个系统崩溃。而加入hystrix之后,如果hystrix发现某个服务的某台机器调用非常缓慢或者多次调用失败,就会短时间内把这条路断掉,所有的请求都不会再发到这台机器上。(二)如果某个服务所有的机器都挂了,hystrix会迅速失败,马上返回,保证被调用方不会有大量的线程堆积。回顾之前有提到,使用eureka时,当一个服务提供方挂掉以后,服务订阅者最长可能30s以后才知道,那这30s就会出现大量的调用失败。如果在系统里面集成了hystrix,就会马上把挂掉的这台服务提供方断路掉,让请求不再转发到这台机器上,大量减少调用失败。hystrix执行断路操作以后,并不表示这条路就永远断了,而是会一定时间间隔内缓慢尝试去请求这条路,如果能请求成功,断路就会恢复。
(三)有一点需要注意的是hystrix在做断路时,默认所有的调用请求都会放在一个的线程池中进行,线程池的作用很明显,有隔离性。比如gateway,集成了5个子业务系统,可能其中一个系统的调用量非常大,而另外四个系统的调用很小,如果没有线程池的话,显然第一个系统的大量调用会影响到后面四个系统的调用性能。hystrix的线程池和java标准线程池一样,可以配置一些参数:coreSize、maximumSize、maxQueueSize、queueSizeRejectionThreshold、allowMaximumSizeToDivergeFromCoreSize、keepAliveTimeMinutes等,如果某一个子系统的调用量突然激增,超过了线程池的容量,也会迅速失败,直接返回,起到降级和保护系统本身的作用。当然hystrix也支持非线程池的方式,在本地请求线程中做调用,即semaphore模式,官方不建议,除非系统qps真的很大。(摘自简书)
新建工程名eureka-consumer-ribbon-hystrix
加入必要的依赖包

@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaConsumerRibbonHystrixApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaConsumerRibbonHystrixApplication.class, args);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

或者直接使用一个注解@SpringCloudApplication注解来修饰应用主类。ctrl点击这个注解会发现这个接口已经包含了上面的三个注解。
这里写图片描述
改造之前的服务消费方式,新增ConsumerService类。

然后将在Controller中的逻辑迁移过去。最后,在为具体执行逻辑的函数上增加@HystrixCommand注解来指定服务降级方法,比如:

@RestController
public class requestController {

    @Resource
    ConsumerService consumerService;

    @GetMapping("doRequest")
    public String doRequest() {
        return consumerService.consumer();
    }
    @Component
    class ConsumerService {
        @Autowired
        RestTemplate restTemplate;

        @HystrixCommand(fallbackMethod = "fallback")
        public String consumer() {
            return restTemplate.getForObject("http://eureka-client/test", String.class);
        }

        public String fallback() {
            return "fallback";
        }
    }

使用IDEA的时候,在使用@Autowired会爆Could not autowire. No beans of … type found。解决方法:error改成warning
这里写图片描述
配置文件application.properties

spring.application.name=eureka-consumer-feign
server.port=21021
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/

先启动之前的eureka-server。再 eureka-client,再启动本工程。访问http://localhost:21021/doRequest
这里写图片描述
成功访问。
测试。在服务提供者eureka-client中的controller请求时让它延迟。以此模仿实际中因网络等情况造成的延迟

try {
            Thread.sleep(5000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

再次访问:
这里写图片描述
这里写图片描述
可以看到服务提供方输出了原本要返回的结果,但是由于返回前延迟了5秒,而服务消费方触发了服务请求超时异常,服务消费者就通过HystrixCommand注解中指定的降级逻辑进行执行,因此该请求的结果返回了fallback。这样的机制,对自身服务起到了基础的保护,同时还为异常情况提供了自动的服务降级切换机制。

猜你喜欢

转载自blog.csdn.net/qq_23303245/article/details/79653312