美文网首页
SpringCloud(十):Hystrix服务熔断

SpringCloud(十):Hystrix服务熔断

作者: 因你而在_caiyq | 来源:发表于2019-02-01 11:15 被阅读0次

    原创文章,转载请注明原文章地址,谢谢!

    分布式系统面临的问题

    复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。

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

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

    Hystrix

    Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
    “断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

    服务熔断

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

    首先,参考cloud-provider-user-8001项目,创建安cloud-provider-user-8001-hystrix项目,并在其pom文件中添加hystrix的依赖。

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

    接着在其applicayion.yml配置中修改eureka的instance-id,为的是区别于8001提供者,表示此次提供者是hystrix8001。

    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
      instance:
        instance-id: cloud-user8001-hystrix
    

    当我们再调用服务提供方的服务时,一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法。所以在Controller中准备好这些方法。

    @RestController
    public class ProviderUserController {
        @Autowired
        private UserService userService;
    
        @GetMapping("/user/get/{id}")
        @HystrixCommand(fallbackMethod = "getHystrixHandle")
        public User get(@PathVariable("id") Long id) {
            User user = userService.get(id);
            if (user == null) {
                throw new RuntimeException("该id下没有对应的用户信息!");
            }
            return user;
        }
    
        public User getHystrixHandle(Long id) {
            User user = new User();
            user.setId(id);
            user.setName("该id下没有对应的名称信息!");
            user.setDataSource("该id下没有对应的数据库信息!");
            return user;
        }
    }
    

    最后别忘了在主启动类上添加注解@EnableCircuitBreaker。接下来就测试一下,启动三个eureka服务,启动hystrix8001提供方,启动80消费者。访问eureka7001.com:7001

    可以看到,我们的服务提供者已经注册到注册中心了。接下来我们访问数据库已经存在的数据,localhost/consumer/user/get/1 已经正常查询除了user的内容,然后我们来访问一下数据库中不存在的数据,localhost/consumer/user/get/6 此时可以看到,首先明确一点,服务还是可以正常调用的,只是给我们反馈的是fallback方法的信息,这是因为我们正常调用get方法的时候,没有查询到user的内容,本是抛出一个异常,这是hystrix的熔断机制,将此服务节点熔断,执行fallback指定的方法,一旦hystrix发现user数据存在,那么此时get服务又会恢复正常。
    服务降级

    整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。服务降级处理是在客户端实现完成的,与服务端没有关系。

    首先根据已经有的UserClientService接口新建一个实现了FallbackFactory接口的类UserClientServiceFallbackFactory。

    @Component
    public class UserClientServiceFallbackFactory implements FallbackFactory<UserClientService> {
    
        @Override
        public UserClientService create(Throwable throwable) {
            return new UserClientService() {
                @Override
                public User get(Long id) {
                    User user = new User();
                    user.setId(id);
                    user.setName("该id下没有对应名称,Consumer客户端提供的服务降级信息,此刻Provider提供方已经关闭!");
                    user.setDataSource("该id下没有对应的数据库信息!");
                    return user;
                }
    
                @Override
                public List<User> list() {
                    return null;
                }
            };
        }
    }
    

    在UserClientService接口在注解@FeignClient中加fallbackFactory属性值。

    @FeignClient(value = "CLOUD-USER", fallbackFactory = UserClientServiceFallbackFactory.class)
    public interface UserClientService {
        @GetMapping("/user/get/{id}")
        User get(@PathVariable("id") Long id);
    
        @GetMapping("/user/list")
        List<User> list();
    }
    

    关键的一点是,需要在80feign模块中开启hystrix。

    feign:
      hystrix:
        enabled: true
    
    接下来,我们测试一下,启动三个eureka服务端,服务提供者8001和消费者80feign,访问localhost/consumer/user/get/1 正常访问查询出了user的信息,此时我们故意关闭服务提供方8001,访问localhost/consumer/user/get/2,理论上应该会报错找不到服务。 客户端自己调用提示,此时服务端provider已经down了,但是我们做了服务降级处理,让客户端在服务端不可用时也会获得提示信息而不会挂起耗死服务器。

    博客内容仅供自已学习以及学习过程的记录,如有侵权,请联系我删除,谢谢!

    相关文章

      网友评论

          本文标题:SpringCloud(十):Hystrix服务熔断

          本文链接:https://www.haomeiwen.com/subject/iqvkdqtx.html