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

关于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添加依赖


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

该依赖加在我的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 getOrderInGoods(Integer orderId) {
        OrderGoods o = new OrderGoods();
        o.setOrderId(orderId);
        QueryWrapper queryWrapper = new QueryWrapper(o);
        List ogs = orderGoodsDao.selectList(queryWrapper);
        List goodses = new ArrayList<>();
        for (OrderGoods og: ogs) {
            Goods goods = goodsFeignClient.getGoodsById(og.getGoodsId());
            goodses.add(goods);
        }
        return goodses;
    }

  //请求的方法发生错误/请求超时调取该方法
    public List getOrderInGoodsHystrix(Integer orderId){
        List 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使用讲解)