zoukankan      html  css  js  c++  java
  • SpringCloud入门(四): Hystrix简介与使用

    服务雪崩  

      微服务架构中,系统通常包括多个服务层。微服务之间通过网络进行通信,从而支撑起整个应用系统,因此,服务间的依赖就难免会存在。而每个微服务都不能保证自己时时刻刻百分百可用。当一个微服务挂掉之后,其他微服务调用这个挂掉微服务的都不可用了。把这种基础服务故障导致级联故障的现象称为雪崩效应。

      简单点来说就是服务A 调用服务B ,而服务B又去调用服务C,服务D(这样的调用过程就是服务扇出)。而在某条扇出的服务调用链路中有一个服务,由于响应时间过程或者抛出异常,导致服务调用者被占用越来越多资源,从而导致整个系统奔溃。

    解决方案

    要想防止雪崩效应,就要一个强大的容错机制。容错机制一般需要实现以下两点。

    为网络请求设置超时:为每个网络请求设置超时时间,超时不再等待,让资源尽快释放。

    使用断路器模式:断路器就相当于家里的自动跳闸的。当请求错误失败数较多,或者有大量超时的请求,就会自动停止对该微服务的请求。

    Hystrix简介

      Hystrix是一个容错管理工具,设计目的是将应用中的远程系统访问、服务调用、第三方依赖包的调用入口,通过资源控制的方式隔离开,避免了在分布式系统中失败的级联塌方式传递,提升系统的弹性和健壮性。

    Hystrix 容错机制

    包裹请求: 使用HystrixCommand注解包裹对依赖的调用逻辑,每个命令都在独立的线程中执行(命令模式)。
    跳闸机制: 当某服务的错误率超过了一定的阈值,Hystrix可以自动或者手动跳闸,停止对该服务的访问。
    资源隔离: Hystrix为每个历来都维护了一个小型的线程池。如果该线程池已满,发往该依赖的请求就会被拒绝,而不是排队等候。从而加速失败的判定。
    监控:   Hystrix可以实时的监控运行指标和配置的变化。
    回退机制: 当请求失败、超时、被拒绝时,或者当断路器被打开时执行回退的逻辑,回退的逻辑可以自己提供。
    自我修复: 断路器打开一段时间后,会自动进入半开状态。

    Hystrix入门

    <!--1. 配置pom文件,引入spring-cloud-starter-netflix-hystrix包-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
    <!- 2. 在服务消费方继承HystrixCommand,实现Hystrix的服务降级->
    public class OrderHystrixCommand extends HystrixCommand<List<OrderVo>> {
    
        private String userId;
    
        private RestTemplate restTemplate;
    
        public OrderHystrixCommand(String commandGroupKey, RestTemplate restTemplate, String userId) {
            super(HystrixCommandGroupKey.Factory.asKey(commandGroupKey));
            this.restTemplate = restTemplate;
            this.userId = userId;
        }
    
        @Override
        protected List<OrderVo> run() throws Exception {
            ResponseEntity<List> responseEntity  =  restTemplate.getForEntity("http://MS-PROVIDER-ORDER/order/queryOrderByUserId/"+userId, List.class);
            List<OrderVo> orderVoList = responseEntity.getBody();
            return orderVoList;
        }
    
        @Override
        protected List<OrderVo> getFallback() {
            OrderVo orderVo = new OrderVo();
            orderVo.setOrderId(-1);
            orderVo.setUserId(-1);
            orderVo.setOrderMoney(new BigDecimal(0));
    
            List<OrderVo> orderVos = new ArrayList<>();
            orderVos.add(orderVo);
            return orderVos;
        }
    }
    
    
    <!- 3. 在服务消费方调用 ->
    OrderHystrixCommand ohc =  new OrderHystrixCommand("orderGroupKey", restTemplate, userId);
    List<OrderVo> orderVoList = ohc.execute();

     备注:我们可以做几个简单的测试,来对Hystrix有的服务降级有一个初步的了解:

      宕机跳闸:关闭一个MS-PROVIDER-ORDER服务提供者,尝试看会出现什么结果,能不能调用我们的getFallback方法;

      超时跳闸:在服务提供方的被调用方法中设置线程睡眠时间,同时我们通过ribbon参数将服务消费者的超时,让超时时间小于睡眠时间,尝试看会出现什么结果。

      异常跳闸:查询一个不存在的订单模拟抛出异常,尝试看会出现什么结果。

    超时跳闸时一些常用配置

    #设置全局的超时时间
    ribbon.ReadTimeout=1000
    ribbon.ConnectTimeout=1000
    
    #出现异常的时候 ,当前实例进行重试
    ribbon.MaxAutoRetries=1
    #切换实例重试的次数
    ribbon.MaxAutoRetriesNextServer=1
    
    #对有所的的操作进行重试(all是对有所方法进行重试,true对有所的重试,false对get重试)
    #如果为True需要保证接口的幂等性
    ribbon.OkToRetryOnAllOperations=true
    
    #开启重试机制(默认是开启的)
    spring.cloud.loadbalancer.retry.enabled=true
    
    #局部配置
    微服务实例名称.ribbon.ConnectTimeout=1000
    微服务实例名称.ribbon.ReadTimeout=1000
    微服务实例名称.ribbon.OkToRetryOnAllOperations=true
    微服务实例名称.ribbon.MaxAutoRetriesNextServer=1
    微服务实例名称.ribbon.MaxAutoRetries=1

    通过 @HystrixCommand实现服务降级

    fallbackMethod方法需要和主方法有一样的入参,不然会报错。一般来说只对调用频率高的接口配置服务降级。
    @HystrixCommand 虽然比继承HystrixCommand要方便,但在实际中用的并不多,因为配置的过多会带来难以维护的问题。

    @HystrixCommand(fallbackMethod="queryOrderFallBack")
    @RequestMapping("testFallback/{userId}")
    public EmployeeInfo testHystrixFallback(@PathVariable("userId") String userId){
        Employee employee = employeeService.findEmployeeById(userId);
    
        ResponseEntity<List> responseEntity;
        responseEntity = restTemplate.getForEntity("http://MS-PROVIDER-ORDER/order/queryOrderbyUserId/" + userId, List.class);
    
        List<OrderVo> orderVoList = responseEntity.getBody();
    
        EmployeeInfo employeeInfo = new EmployeeInfo();
        employeeInfo.setEmployeeName(employee.getName());
        employeeInfo.setOrderVoList(orderVoList);
        return employeeInfo;
    }
    
    protected EmployeeInfo queryOrderFallBack(String userId) {
        EmployeeInfo employeeInfo = new EmployeeInfo();
        employeeInfo.setEmployeeName("FallBack");
        employeeInfo.setOrderVoList(null);
        return employeeInfo;
    }

    Hystrix整合Feign

    <!--1. 配置pom文件,引入jar包 -->
    <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    <!-- 2. 配置属性文件 -->
    #开启feign对hystrix的支持,默认是关闭的。
    feign.hystrix.enabled=true
    
    
    <!-- 3. 在Spring的启动入口添加@EnableFeignClients注解 -->
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class HystrixProvider8006Application {
    
        public static void main(String[] args) {
            SpringApplication.run(HystrixApplication.class, args);
        }
    }
    
    <!-- 4. 定义Feign的接口类,通过FeignClient中的fallback属性实现Hystrix的服务降级 -->
    @FeignClient(name = "ms-provider-order", fallback = CustomFeignOrderApiFallBack.class, path = "/order")
    public interface CustomFeignOrderApi {
        @RequestMapping("/queryOrdersByUserId/{userId}")
        List<OrderVo> queryOrdersByUserId(@PathVariable("userId") String userId);
    
        @RequestMapping("/getRegisterInfo")
        String getRegisterInfo();
    }
    
    @Component
    public class CustomFeignOrderApiFallBack implements MsCustomFeignOrderApi {
        @Override
        public List<OrderVo> queryOrdersByUserId(String userId) {
            List<OrderVo> orderVoList = new ArrayList<>();
            OrderVo orderVo = new OrderVo();
            orderVo.setUserId(userId);
            orderVo.setOrderId(-1);
    
            orderVoList.add(orderVo);
            return orderVoList;
        }
    
        @Override
        public String getRegisterInfo() {
            return "服务异常";
        }
    }

    备注:我们可以同上实验一下

     Hystrix的一些常用配置

    1. 关闭Hystrix对feign的支持
    全局关闭:feign.hystrix.enabled=false(默认是关闭的)
    局部关闭:
    写一个配置类,在配置类中写一个FeignBulider的类:
    public class CustomeFeignApiWithoutHystrixConfg {
        @Scope("prototype")
        @Bean
        public Feign.Builder feignBuilder() {
            return Feign.builder();
        }
    }
    
    在FeignClient中指配置文件
    @FeignClient(name = "MS-PROVIDER-ORDER",configuration = MsCustomeFeignApiWithoutHystrixConfg.class, path = "/order")
    
    2. 关闭熔断
    全局关闭:hystrix.command.default.circuitBreaker.enabled=false
    局部关闭:hystrix.command.<HystrixCommandKey>.circuitBreaker.enabled: false
            其中的HystrixCommandKey是个变量,可以打开服务的hystrix.stream端点即可看到,也可在Hystrix Dashboard中查看。
    
    3. 设置超时
    全局超时:hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 1000
    局部关闭:hystrix.command.<HystrixCommandKey>.execution.isolation.thread.timeoutInMilliseconds: 1000
    
    4. 关闭超时
    全局关闭:hystrix.command.default.execution.timeout.enabled: false
    局部关闭:hystrix.command.<HystrixCommandKey>.execution.timeout.enabled: false
  • 相关阅读:
    Python OpenCV
    Model忽略模型,不生成表创建语句
    GZSales.Electron生成记录
    Electron-Build打包成安装包错误,下载依赖,下载不来winCodeSign,或者下载很慢
    electron npm install缓存
    electrron npm install报错
    VS 自定义生成 Directory.Build.props Directory.Build.targets
    我的物联网项目(二十二) 微服务分库查询优化
    我的物联网项目专题移到网站:http://51jdk.com
    我的物联网项目(十四) 分布式事务
  • 原文地址:https://www.cnblogs.com/jiangyaxiong1990/p/12392781.html
Copyright © 2011-2022 走看看