Hystrix详解与实例

引言

        首先,之所以谈这个话题呢,是发现现在很多人对微服务的设计缺乏认识,所以写一篇扫盲文。当然,考虑到目前大多微服务的文章都是口水文,烟哥争取将实现方式讲透,点清楚,让大家有所收获!
        OK,我要先说明一下,我有很长一段时间将服务降级服务熔断混在一起,认为是一回事!
为什么我会有这样的误解呢?
针对下面的情形,如图所示:

Hystrix详解与实例_第1张图片

        当Service A调用Service B,失败多次达到一定阀值,Service A不会再去调Service B,而会去执行本地的降级方法!
对于这么一套机制:在Spring cloud中结合Hystrix,将其称为熔断降级!

       所以我当时就以为是一回事了,毕竟熔断和降级是一起发生的,而且这二者的概念太相近了!后面接触了多了,发现自己理解的还是太狭隘了,因此本文中带着点我自己的见解,大家如果有不同意见,请轻喷!毕竟还有很多人认为两者是一致的!

正文

服务雪崩

OK,我们从服务雪崩开始讲起!假设存在如下调用链:

Hystrix详解与实例_第2张图片

        而此时,Service A的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A能扛得住请求,Service BService C未必能扛得住这突发的请求。
        此时,如果Service C因为抗不住请求,变得不可用。那么Service B的请求也会阻塞,慢慢耗尽Service B的线程资源,Service B就会变得不可用。紧接着,Service A也会不可用,这一过程如下图所示

如上图所示,一个服务失败,导致整条链路的服务都失败的情形,我们称之为服务雪崩。

那么,服务熔断服务降级就可以视为解决服务雪崩的手段之一。

服务熔断

        服务熔断:当下游的服务因为某种原因突然变得不可用或响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。Hystrix默认的超时时间为1s,请求时间超过1s,熔断次数加1。

熔断器机制:

  • closed:请求正常时,不使用熔断器;
  • open:统计请求的失败比例,达到阀值时,打开熔断器,请求被降级处理;延时一段时候后(默认休眠时间是5S)会进入halfopen状态;默认失败比例阀值是50%,请求次数最少不低于20次,例如:一段时间内请求30次,有20失败,熔断器将会打开,默认5s内的请求都会失败,直接返回。
  • halfopen:在进入该状态后会放入部分请求;判断请求是否成功,不成功,进入open状态,重新计时,进入halfopen状态;成功,进入closed状态,

Hystrix详解与实例_第3张图片

参数修改:

Hystrix详解与实例_第4张图片

  熔断参数的 key,value

Hystrix详解与实例_第5张图片

 服务降级

        服务降级是从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback(退路)错误处理信息。这样,虽然提供的是一个有损的服务,但却保证了整个系统的稳定性和可用性。

熔断VS降级

相同点:

  • 目标一致 都是从可用性和可靠性出发,为了防止系统崩溃;
  • 用户体验类似 最终都让用户体验到的是某些功能暂时不可用;

不同点:

  • 触发原因不同 服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;

入门实例

1、Maven依赖:



    org.springframework.cloud
    spring-cloud-starter-eureka




    org.springframework.cloud
    spring-cloud-starter-feign




    org.springframework.cloud
    spring-cloud-starter-hystrix

2、修改启动类

在启动类上增加@EnableCircuitBreaker(客户端)注解:

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

       这里我们在启动类中又增加了@EnableCircuitBreaker注解,用来开启断路器功能。如果你觉得启动类上的注解个数有点多的话,可以使用一个@SpringCloudApplication 注解来代替@SpringBootApplication(或者@EnableEurekaServer)、@EnableDiscoveryClient、@EnableCircuitBreaker这三个注解。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

3、Controller:

接下来,我们为接口增加断路器功能,修改部分代码如下:

	@GetMapping("/msg/get")
	@HystrixCommand(fallbackMethod = "getMsgFallback")
	public Object getMsg() {
		String msg = messageService.getMsg();
		return msg;
	}
 
	public Object getMsgFallback() {
		return "祝您 2019 猪年大吉,'猪'事如意!";
	}

        先启动Eureka,再启动一个8771端口的message-service服务,最后启动message-center。待启动完成之后,Eureka注册中心实例注册信息如下:

此时,访问 http://localhost:8781/api/v1/center/msg/get ,返回如下结果表明服务调用成功:

然后,停掉message-service服务,再次请求 http://localhost:8781/api/v1/center/msg/get ,返回结果如下:

可以看出fallback中的信息被直接返回了,表明Hystrix断路器调用成功。

注意:fallback方法的签名需要和原方法保持一致。

Feign结合Hystrix

上述例子耦合性太强。

以MessageService的Feign客户端为例,为其添加Hystrix断路器功能。

1、修改Feign客户端

通过配置@FeignClient注解的fallback属性来位MessageServiceClient指定一个自定义的fallback处理类(MessageServiceFallback)。

@FeignClient(name = "message-service", fallback = MessageServiceFallback.class)
public interface MessageServiceClient {
 
	@GetMapping("/api/v1/msg/get")
	public String getMsg();
}

2、创建Fallback处理类

 MessageServiceFallback需要实现MessageServiceClient接口,并且在Spring容器中必须存在一个该类型的有效Bean。在这里,我们使用@Component注解将其注入到Spring容器中。

@Component // 不要忘记添加,不要忘记添加
public class MessageServiceFallback implements FallbackFactory{
	@Override
	public MessageServiceClient create(Throwable throwable){
		return new DeptClientService() {
			@Override
			public String getMsg(long id){
				return new String("消息接口繁忙,请稍后重试!");
			}
		};
	}
}

3、修改配置

在新版本的Springcloud中,Feign默认关闭了对Hystrix的支持,需要在application.yml进行配置:

feign:
  hystrix:
    enabled: true

当message-service服务不可用时,请求 http://localhost:8781/api/v1/center/msg/get,返回结果如下:

监控Hystrix

        使用Hystrix一个最大的好处就是它会为我们自动收集每一个HystrixCommand的信息,并利用Hystrix-Dashboard通过一种高效的方式对每一个断路器的健康状态进行展示。

        值得注意的是,在使用HystrixCommand对RibbonClient进行包装的时候,你需要确保你配置的Hystrix超时时间要比Ribbon的超时时间长,包括由它们引起的重试时间,举个例子:如果你的Ribbon连接超时时间是1秒,并且Ribbon会连续重试请求3次,那么你的Hystrix连接超时时间需要配置成稍大于3秒。

1、引入Hystrix-Dashboard依赖

在 pom.xml 文件中引入Hystrix-Dashboard依赖:

		
			org.springframework.cloud
			spring-cloud-starter-hystrix
		
		
			org.springframework.cloud
			spring-cloud-starter-hystrix-dashboard
		

2、修改启动类

在MessageCenterApplication启动类上增加@EnableHystrixDashboard注解:

@EnableFeignClients
@SpringCloudApplication
@EnableHystrixDashboard
public class MessageCenterApplication {
 
	public static void main(String[] args) {
		new SpringApplicationBuilder(MessageCenterApplication.class).web(WebApplicationType.SERVLET).run(args);
	}
 
}

仪表盘界面

启动应用,访问 http://localhost:8781/hystrix ,打开Hystrix-Dashboard监控首页。

Hystrix详解与实例_第6张图片

在这里配置好需要监控的Hystrix流地址 http://localhost:8781/actuator/hystrix.stream ,开始监控。

Hystrix详解与实例_第7张图片

参考文章:

https://blog.csdn.net/pengjunlee/article/details/86688858

https://github.com/netflix/hystrix

你可能感兴趣的:(【微服务】)