SpringCloud-hystrix实战01--服务熔断

Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。Hystrix主要通过以下几点实现延迟和容错。

*跳闸机制:当某服务的错误率超过一定阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间。

*资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判定。

*回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。

*包裹请求:使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用到了设计模式中的“命令模式”。

*监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。

Feign默认已经整合了Hystrix,本节详细探讨Feign使用Hystrix的具体细节(项目中很少有单独使用Hystrix的)

服务雪崩

多个微服务之间调用的时候,假设微服务A调用微服务B何微服务C,微服务B何微服务C又调用其他的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃。

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。

Hystrix

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要的占用,从而避免了公章在分布式系统中的蔓延,乃至雪崩。

功能

1.服务降级
2.服务熔断
3.服务限流
4.接近实时的监控
。。。。

服务熔断

熔断机制是应对雪崩效应的一种微服务链路保护机制。

一般是某个服务股找那个或者异常引起,类似现实世界中的“保险丝”,当某个异常条件被触发,直接熔断整个服务,而不是一直等到此服务超时。

当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回“错误”的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand

实战

pom中的依赖



    org.springframework.cloud
    spring-cloud-starter-netflix-hystrix
    2.1.2.RELEASE

properties中的修改

#-----服务端口号修改了----
server.port=18084
spring.application.name=springboot-mybatis-provider-001
# 指定eureka server通信地址,注意/eureka/不能少
eureka.client.service-url.defaultZone=http://eureka10002.com:10002/eureka/,http://eureka10003.com:10003/eureka/,http://eureka10004.com:10004/eureka/
# 是否注册IP到eureka server,如不指定或设为false,那就会注册主机名到eureka server
eureka.instance.prefer-ip-address=true
#修改服务名称-------实例名称修改了------
eureka.instance.instance-id=springboot-mybatis-provider-hystrix001-18084
#配置actuator监控信息
info.app.name=springboot-mybatis-provider-hystrix001-18084
info.company.name=www.zjhc.com
info.build.artifactId=$project.artifactId$
info.build.version=$project.version$

启动类中的修改

SpringCloud-hystrix实战01--服务熔断_第1张图片

controller中的修改

package com.hc.controller;

import com.hc.model.User;
import com.hc.service.UserService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 */
@Controller
public class UserController {

    private Logger logger = Logger.getLogger(UserController.class);

    @Autowired
    private UserService userService;

    @RequestMapping("/getRealUserInfo/{id}")
    @ResponseBody
    @HystrixCommand(fallbackMethod = "getRealUserInfo_Hystrix")
    public User getRealUserInfo(@PathVariable Integer id) {
        User user = new User();
//        try {
            user = userService.getRealUserInfo(id);
            if (user == null) {
                logger.info("-----user信息未获取到-----");
                throw new RuntimeException("haha,就是故意让你报错滴 ^_^ ");
            }
//        }catch (Exception e){
//            e.printStackTrace();
//        }
        return user;
    }

    public User getRealUserInfo_Hystrix(@PathVariable Integer id) {
        User user = new User();
        user.setName("该ID:"+id+" 没有对应的信息,null-@HystrixCommand");
        return user;
    }
}

测试结果如下(背景条件:数据库中没有id为200的数据):

SpringCloud-hystrix实战01--服务熔断_第2张图片
id=1的时候是有数据的

SpringCloud-hystrix实战01--服务熔断_第3张图片
由于没有id=200的数据,我们故意手动抛出异常,来测试熔断

你可能感兴趣的:(SpringCloud-hystrix实战01--服务熔断)