SpringCloud Feign整合Hystrix实现服务熔断服务降级彻底解耦

 

个人博客网:www.lfuping.cn    (你想要这里多有)

 

Feign Hystrix整合&服务熔断服务降级彻底解耦

@HystrixCommand fallbackMethod的方式不是很好,因为和业务代码耦合度太高,不利于维护,所以需要解耦,就Feign Hystrix整合。

一、springcloud-common项目:
添加FallbackClientFactory类

package com.li.springcloud.common.feign;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import com.li.springcloud.common.model.Student;
import feign.hystrix.FallbackFactory;
/**
 * 解耦服务熔断服务降级
 * 
 * @author Administrator
 *
 */
@Component
public class FallbackClientFactory implements
        FallbackFactory<FeignClientService> {
    public FeignClientService create(Throwable cause) {
        // TODO Auto-generated method stub
        return new FeignClientService() {
            public List<Student> listHystrix() {
                List<Student> list = new ArrayList<Student>();
                Student stu = new Student();
                stu.setName("系统繁忙,请稍后重试....服务提供者------1");
                stu.setId(500);
                list.add(stu);
                return list;
            }
            public List<Student> list() {
                // TODO Auto-generated method stub
                return null;
            }
        };
    }
}

FeignClientService类:

package com.li.springcloud.common.feign;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import com.li.springcloud.common.model.Student;
/**
 * Feign接口客户端
 * 
 * @author Administrator
 *
 */
@FeignClient(value = "PROVIDER",fallbackFactory=FallbackClientFactory.class)
public interface FeignClientService {
    /**
     * 查询用户信息
     * 
     * @return
     */
    @GetMapping(value = "/provider/list")
    public List<Student> list();
    /**
     *  Hystrix的方式
     * @return
     */
    @GetMapping(value="/provider/listHystrix")
    public List<Student> listHystrix();
}

二、在服务生产者springcloud-provider-1,springcloud-provider-2添加如下方法:
StudentService:

/**
     * 获取信息
     * @return
     */
    public List<Student> getInfo();

StudentServiceImpl:

 @Override
    public List<Student> getInfo() {
        List<Student> list = new ArrayList<Student>();
        Student stu = new Student();
        //如果是第二个服务就写成  2, 测试时方便观察
        stu.setName("业务数据xxxxxxxxxxxxxxxxx....服务提供者------1");
        stu.setId(200);
        list.add(stu);
        return list;
    }

ProviderController类:

package com.li.spingcloud.provider.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.li.spingcloud.provider.service.StudentService;
import com.li.springcloud.common.model.Student;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@RestController
public class ProviderController {
    @Autowired
    private StudentService studentService;
    /**
     * 查询
     *
     * @return
     */
    @RequestMapping(value = "/provider/list", produces = "application/json; charset=utf-8", method = {
            RequestMethod.POST, RequestMethod.GET })
    public List<Student> list() {
        System.out.println("ProviderController----我是生产者1");
        return studentService.list();
    }
    /**
     * 查询 Hystrix的方式
     * 
     * @return
     * @throws InterruptedException
     */
    // 加上@HystrixCommand注解 以及 fallbackMethod
    // 表明这个方法再没有异常以及没有超时(hystrix默认1秒算超时)的情况,才返回正常的业务数据;
    //@HystrixCommand(fallbackMethod = "getInfoFallback")
    @RequestMapping(value = "/provider/listHystrix", produces = "application/json; charset=utf-8", method = {
            RequestMethod.POST, RequestMethod.GET })
    public List<Student> listHystrix() throws InterruptedException {
        //模拟调用延迟
        Thread.sleep(1000);
        System.out.println("ProviderController----我是生产者1");
        // 模拟调用服务超时
        // 然后采取 Hystrix进行服务降级,进而熔断该节点的服务调用,快速返回自定义的错误影响页面信息。
        return studentService.getInfo();
    }
}

三、springcloud-consumer-feign-1消费者项目:
修改配置如下:

server:
  port: 8080
  context-path: /
eureka:
  client:
    register-with-eureka: false 
    service-url: 
      defaultZone: http://localhost:7001/eureka/
      #集群模式  defaultZone: http://lifuping.eureka3.com:6001/eureka/,http://lifuping.eureka2.com:5001/eureka/,http://lifuping.eureka1.com:7001/eureka/
feign: 
  hystrix: 
    enabled: true 
#hystrix超时时间配置 (如果不配置的话默认是1000毫秒超时)
hystrix: 
  command: 
    default: 
      execution: 
        isolation: 
          thread: 
            timeoutInMilliseconds: 5000

修改ConsumerFeignApplication启动类:

package com.li.spingcloud.consumerfeign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class })
@EnableEurekaClient
@ComponentScan(basePackages = { "com.li.spingcloud.consumerfeign",
        "com.li.springcloud.common.feign" })
@EnableFeignClients({ "com.li.springcloud.common.feign" })
public class ConsumerFeignApplication {
    /**
     * 程序启动
     * 
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeignApplication.class, args);
    }
}

四、测试启动顺序:

  1. 先启动eureka单机或者集群;
  2. 在启动服务生产者集群;
  3. 启动消费者;
    如果在启动消费者项目springcloud-consumer-feign-1报如下错误:

 

无法加载到 No fallbackFactory instance of type class com.li.springcloud.common.feign.FallbackClientFactory found for feign client PROVIDER;

 

要在FallbackClientFactory类加上@Component注解,并且在消费者项目加上

@ComponentScan(basePackages = { "com.li.spingcloud.consumerfeign",
     "com.li.springcloud.common.feign" })
  1. 打开浏览器输入地址:http://localhost:8080/consumer/listHystrix
    测试:

    返回正常信息;超过1秒的话,就返回错误提示;

之前在生产者项目配置Hystrix的超时时间配置就无效了;所以Hystrix默认还是1秒钟,要把这段配置写到springcloud-consumer-feign-1消费者项目;并且因为还有一个 feign 也有一个超时时间的设置,当然feign底层是ribbon的封装,所以直接配置ribbon,ribbon默认超时也是1秒。所以这里都是强制要求,ribbon的超时时间要大于hystrix的超时时间,否则 hystrix自定义的超时时间毫无意义。

完整配置:

 

server:
  port: 8080
  context-path: /
eureka:
  client:
    register-with-eureka: false 
    service-url: 
      defaultZone: http://localhost:7001/eureka/
      #集群模式  defaultZone: http://lifuping.eureka3.com:6001/eureka/,http://lifuping.eureka2.com:5001/eureka/,http://lifuping.eureka1.com:7001/eureka/
feign: 
  hystrix: 
    enabled: true 
#hystrix超时时间配置 (如果不配置的话默认是1000毫秒超时)
hystrix: 
  command: 
    default: 
      execution: 
        isolation: 
          thread: 
            timeoutInMilliseconds: 5000 
ribbon: 
  ReadTimeout: 10000
  ConnectTimeout: 9000

五、关于Ribbon核心组件之IRule
在springcloud-consumer-feign-1消费者项目的config包下SpringCloudConfig类:

 /**
     * 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,
     然后选择一个并发量最小的服务
     * 
     * @return
     */
    @Bean
    public IRule myRule() {
        return new BestAvailableRule();
    }

我测试用的BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。

它默认出厂自带了7种算法。

第一种是:RoundRobinRule 轮询

第二种是:RandomRule 随机

第三种是:AvailabilityFilteringRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,

还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问。

第四种是:WeightedResponseTimeRule 根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule。

第五种是:RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务。

第六种是:BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。

第七种是:ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器。

 

源码下载链接: https://pan.baidu.com/s/1KVaGrvv9p9rYacmS_KnXsA 

提取码: tcv3

                                                   

                                                     欢迎关注我的微信公众号:平川大叔

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值