美文网首页
spring cloud调用方法异常怎么办--Hystrix使用

spring cloud调用方法异常怎么办--Hystrix使用

作者: 毛于晏 | 来源:发表于2018-12-12 11:21 被阅读67次

    关于spring cloud的组件前面已经介绍两个了, 学习的过程也是循序渐进的, 如果前面写的关于Eureka和Feign两个组件还没有看的同学,可以点击以下链接进行学习;
    spring cloud之Eureka--服务治理
    spring cloud使用过Eureka怎么进行服务间相互访问--Feign
    下面是我自己在github上的spring cloud的demo
    spring_cloud_demo
    下面进入正题;

    1.Hystrix

    Hystrix

    Hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,这与Hystrix本身的功能不谋而合,因此Netflix团队将该框架命名为Hystrix,并使用了对应的卡通形象做作为logo

    1.1什么是Hystrix

    在一个分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,这个就是Hystrix需要做的事情。Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。

    1.2为什么使用Hystrix

    在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC) 。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

    如下图所示:A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。

    雪崩效应

    1.3Hystrix是如何实现

    (1)通过HystrixCommand或者HystrixObservableCommand来封装对外部依赖的访问请求,这个访问请求一般会运行在独立的线程中,资源隔离
    (2)对于超出我们设定阈值的服务调用,直接进行超时,不允许其耗费过长时间阻塞住。这个超时时间默认是99.5%的访问时间,但是一般我们可以自己设置一下
    (3)为每一个依赖服务维护一个独立的线程池,或者是semaphore,当线程池已满时,直接拒绝对这个服务的调用
    (4)对依赖服务的调用的成功次数,失败次数,拒绝次数,超时次数,进行统计
    (5)如果对一个依赖服务的调用失败次数超过了一定的阈值,自动进行熔断,在一定时间内对该服务的调用直接降级,一段时间后再自动尝试恢复
    (6)当一个服务调用出现失败,被拒绝,超时,短路等异常情况时,自动调用fallback降级机制
    (7)对属性和配置的修改提供近实时的支持

    2.项目中使用Hystrix

    2.1添加依赖

    <!--添加熔断器依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-hystrix</artifactId>
            </dependency>
    

    该依赖加在我的demo中的父项目中

    2.2添加注解

    在spring boot的启动类上添加注解@EnableHystrix

    package cn.cooplan.order;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.feign.EnableFeignClients;
    import org.springframework.cloud.netflix.hystrix.EnableHystrix;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    @EnableHystrix //开启熔断器
    @EnableFeignClients
    @EnableEurekaClient //开启Eureka客户端服务
    @SpringBootApplication
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
         //Feigx依赖的请求对象
        @Bean
        RestTemplate restTemplate (){
            return new RestTemplate();
        }
    }
    

    2.3测试+解释

    需要在你请求的方法上添加 @HystrixCommand("发生异常时访问的方法名") 在同一个类中编写异常时进行的方法处理, 具体实现如下:

    package cn.cooplan.order.service.impl;
    
    import cn.cooplan.order.feign.GoodsFeignClient;
    import cn.cooplan.order.service.OrderService;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import dao.OrderDao;
    import dao.OrderGoodsDao;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    import pojo.Goods;
    import pojo.Order;
    import pojo.OrderGoods;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Author MaoLG
     * @Date 2018/12/7  14:03
     */
    @Service
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public class OrderServiceImpl implements OrderService {
    
        @Autowired
        private OrderDao orderDao;
    
        @Autowired
        private OrderGoodsDao orderGoodsDao;
    
        @Autowired
        private GoodsFeignClient goodsFeignClient;
    
      /*在你请求的方法上添加@HystrixCommand注解, 参数指定发生错误时调取的方法
        该方法要保持参数列表相同, 返回值相同, 抛出异常相同, 非静态方法;
        总结的说就是除了方法名不一样,其他都一样;
    */
        @HystrixCommand(fallbackMethod = "getOrderInGoodsHystrix")
        @Override
        public List<Goods> getOrderInGoods(Integer orderId) {
            OrderGoods o = new OrderGoods();
            o.setOrderId(orderId);
            QueryWrapper queryWrapper = new QueryWrapper(o);
            List<OrderGoods> ogs = orderGoodsDao.selectList(queryWrapper);
            List<Goods> goodses = new ArrayList<>();
            for (OrderGoods og: ogs) {
                Goods goods = goodsFeignClient.getGoodsById(og.getGoodsId());
                goodses.add(goods);
            }
            return goodses;
        }
    
      //请求的方法发生错误/请求超时调取该方法
        public List<Goods> getOrderInGoodsHystrix(Integer orderId){
            List<Goods> goodses = new ArrayList<>();
            Goods goods = new Goods();
            goods.setName("商品错误");
            goodses.add(goods);
            return goodses;
        }
    }
    

    Hystrix成功后:
    无异常情况

    无异常.jpg
    异常情况
    进入的方法:
    进入方法.jpg
    异常效果
    有错误.jpg

    详细请见github上的spring cloud的demo
    spring_cloud_demo
    欢迎大家在下面留言讨论;

    相关文章

      网友评论

          本文标题:spring cloud调用方法异常怎么办--Hystrix使用

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