Spring Cloud学习笔记(六)熔断器Hystrix

背景

在微服务架构中,通常会存在很多层级的调用关系,比如A服务调用B服务,B调用C,C调用D等多层调用完成一个业务请求,那么很显然,如果其中某一个底层服务出现问题,那么调用这个服务的其它服务都在等待请求返回,如果此刻有大量服务请求,势必会造成应用服务器线程资源耗尽,压垮我们的应用服务器,从而导致服务不可用,由于服务和服务之间的相互依赖,故障会一层层向上传播,对系统造成严重后果,这就是服务故障的雪崩效应。

雪崩效应常见场景

  • 硬件故障:如服务器宕机,机房断电,光纤被挖断等。
  • 流量激增:如异常流量,重试加大流量等。
  • 缓存穿透:一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用。
  • 程序BUG:如程序逻辑导致内存泄漏,JVM长时间FullGC等。
  • 同步等待:服务间采用同步调用模式,同步等待造成的资源耗尽。

雪崩效应应对策略

针对造成雪崩效应的不同场景,可以使用不同的应对策略,没有一种通用所有场景的策略,参考如下:

  • 硬件故障:多机房容灾、异地多活等。
  • 流量激增:服务自动扩容、流量控制(限流、关闭重试)等。
  • 缓存穿透:缓存预加载、缓存异步加载等。
  • 程序BUG:修改程序bug、及时释放资源等。
  • 同步等待:资源隔离、MQ解耦、不可用服务调用快速失败等。资源隔离通常指不同服务调用采用不同的线程池;不可用服务调用快速失败一般通过熔断器模式结合超时机制实现。

综上所述,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。 因此,为了构建稳定、可靠的分布式系统,我们的服务应当具有自我保护能力,当依赖服务不可用时,当前服务启动自我保护功能,从而避免发生雪崩效应。

为了解决此类问题,业界提出了熔断模式,Hystrix是Spring Cloud Netflix实现熔断模式的组件。

Hystrix设计目标:

  • 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
  • 阻止故障的连锁反应
  • 快速失败并迅速恢复
  • 回退并优雅降级
  • 提供近实时的监控与告警

Hystrix遵循的设计原则:

  • 防止任何单独的依赖耗尽资源(线程)
  • 过载立即切断并快速失败,防止排队
  • 尽可能提供回退以保护用户免受故障
  • 使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
  • 通过近实时的指标,监控和告警,确保故障被及时发现
  • 通过动态修改配置属性,确保故障及时恢复
  • 防止整个依赖客户端执行失败,而不仅仅是网络通信

(以上关于雪崩效应及Hystrix设计目标及原则内容参考自:https://my.oschina.net/7001/blog/1619842

Hystrix实践

先学习一下Hystrix的主要用法,基于我们之前的项目构建,在Service-Consumer工程里引入Hystrix,当Service-Provider不能提供服务的时候,会返回错误提示,而不是进行等待。

首先Service-Consumer引入Hystrix依赖

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

在启动类上,开启Hystrix

扫描二维码关注公众号,回复: 10241003 查看本文章
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class SpringCloudStudyServiceConsumerApplication {

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

	//注入restTemplate
	@Bean
	@LoadBalanced
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}

}

接下来改造我们的Controller方法,加入Hystrix相关机制

package org.dothwinds.serviceconsumer.controller;


import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.dothwinds.serviceconsumer.serviceinterface.ServiceConsumerInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class ServiceConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ServiceConsumerInterface serviceConsumerInterface;

    @GetMapping("/testLoadBalance")
    @HystrixCommand(fallbackMethod = "error")
    public String serviceCousumer(){
//       return restTemplate.getForObject("http://SERVICE-PROVIDER/service", String.class);
        return serviceConsumerInterface.serviceCousumer();
    }

    public String error(){
        return "Hystrix生效了,没有调用到服务,直接返回错误信息了~~";
    }
}

如上面代码,我们在Feign调用接口上加入了熔断措施,如果发生错误,那么直接调用到error方法返回错误信息了,接下来我们启动服务

如上图,可以看到服务正常启动了。那么我们关闭Service-Provider在看一下,如下图,服务没有等待,直接返回了错误信息。

参考资料:

https://cloud.spring.io/spring-cloud-static/Greenwich.SR5/single/spring-cloud.html#_circuit_breaker_hystrix_clients

https://my.oschina.net/7001/blog/1619842

https://baijiahao.baidu.com/s?id=1623004854011062838&wfr=spider&for=pc

代码:https://gitee.com/dothwinds/Spring-Cloud-Study/tree/master/spring-cloud-study-hystrix

发布了18 篇原创文章 · 获赞 33 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Dothwinds/article/details/105075394
今日推荐