Feign的雪崩处理

在声明式远程服务调用Feign中,实现服务灾难性雪崩效应处理也是通过Hystrix实现的。而feign启动器spring-cloud-starter-feign中是包含Hystrix相关依赖的。如果只使用服务降级功能不需要做独立依赖。如果需要使用Hystrix其他服务容错能力,需要依赖spring-cloud-starter-hystrix资源。从Dalston版本后,feign默认关闭Hystrix支持。所以必须在全局配置文件中开启feign技术中的Hystrix支持。配置如下:

feign.hystrix.enabled=true

如果不使用Hystrix服务容错功能,在application client端,服务接口只需要继承服务标准api接口即可实现远程服务调用。如果使用了Hystrix,则有不同的编写方式。具体如下。

 

一、接口实现类方式

定义和服务标准api相同的application client服务接口。

并通过@FeignClient注解来描述fallback方法所在类是什么。

这个fallback方法所在类就是接口的实现类,实现的方法就是接中定义方法的fallback方法。

import java.util.List;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.yucong.api.pojo.FeignTestPOJO;

/**
 * 如果在Feign中使用Hystrix,则不能直接继承服务标准接口。
 * 因为继承接口,一般都不会给予实现。会缺少fallback方法。熔断机制链条不完整。
 * 在当前接口中,重复定义服务标准接口中定义的方法。
 * 远程服务调用的时候,是通过@FeignClient实现的。
 * 如果远程服务调用失败,则触发fallback注解属性定义的接口实现类中的对应方法,作为fallback方法。
 * 
 * 在默认的Hystrix配置环境中,使用的是服务降级保护机制。
 * 
 * 服务降级,默认的情况下,包含了请求超时。
 * feign声明式远程服务调用,在启动的时候,初始化过程比较慢。比ribbon要慢很多。
 * 很容易在第一次访问的时候,产生超时。导致返回fallback数据。
 */
@FeignClient(name="test-feign-application-service",
            //fallback=FirstClientFeignServiceImpl.class
            fallbackFactory=FirstClientFeignServiceFallbackFactory.class
        )
public interface FirstClientFeignService{

    @RequestMapping(value="/testFeign", method=RequestMethod.GET)
    public List<String> testFeign();
    
    @RequestMapping(value="/get", method=RequestMethod.GET)
    public FeignTestPOJO getById(@RequestParam(value="id") Long id);
    
    @RequestMapping(value="/get", method=RequestMethod.POST)
    public FeignTestPOJO getByIdWithPOST(@RequestBody Long id);
    
    @RequestMapping(value="/add", method=RequestMethod.GET)
    public FeignTestPOJO add(@RequestParam("id") Long id, @RequestParam("name") String name);
    
    @RequestMapping(value="/addWithGET", method=RequestMethod.GET)
    public FeignTestPOJO add(@RequestBody FeignTestPOJO pojo);
    
    @RequestMapping(value="/addWithPOST", method=RequestMethod.POST)
    public FeignTestPOJO addWithPOST(@RequestBody FeignTestPOJO pojo);
    
}

为接口提供实现类,类中的方法实现就是fallback逻辑。实现类需要spring容器管理,使用@Component注解来描述类型。

package com.yucong.eureka.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Component;

import com.yucong.api.pojo.FeignTestPOJO;
import com.yucong.eureka.service.FirstClientFeignService;

/**
 * 实现类中的每个方法,都是对应的接口方法的fallback。
 * 一定要提供spring相关注解(@Component/@Service/@Repository等)。
 * 注解是为了让当前类型的对象被spring容器管理。
 * fallback是本地方法。
 * 是接口的实现方法。
 */
@Component
public class FirstClientFeignServiceImpl implements FirstClientFeignService {

    @Override
    public List<String> testFeign() {
        List<String> result = new ArrayList<>();
        result.add("this is testFeign method fallback datas");
        return result;
    }

    @Override
    public FeignTestPOJO getById(Long id) {
        return new FeignTestPOJO(-1L, "this is getById method fallback datas");
    }

    @Override
    public FeignTestPOJO getByIdWithPOST(Long id) {
        return new FeignTestPOJO(-1L, "this is getByIdWithPOST method fallback datas");
    }

    @Override
    public FeignTestPOJO add(Long id, String name) {
        return new FeignTestPOJO(-1L, "this is add(id, name) method fallback datas");
    }

    @Override
    public FeignTestPOJO add(FeignTestPOJO pojo) {
        return new FeignTestPOJO(-1L, "this is add(pojo) method fallback datas");
    }

    @Override
    public FeignTestPOJO addWithPOST(FeignTestPOJO pojo) {
        return new FeignTestPOJO(-1L, "this is addWithPOST method fallback datas");
    }

}

 

二、Factory实现方式

在服务接口的@FeignClient注解中,不再使用fallback属性,而是定义fallbackFactory属性。这个属性的类型是Class类型的,用于配置fallback代码所处的Factory

再定义一个Java类,实现接口FallbackFactory,实现其中的create方法。使用匿名内部类的方式,为服务接口定义一个实现类,定义fallback方法实现。

这种实现逻辑的优势是,可以获取远程调用服务的异常信息。为后期异常处理提供参考。

工厂实现方案和实现类的实现方案,没有效率和逻辑上的优缺点对比。只是在远程服务调用异常的处理上有区别。

 

package com.yucong.eureka.service;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.yucong.api.pojo.FeignTestPOJO;

import feign.hystrix.FallbackFactory;

/**
 * 使用Factory方式实现Feign的Hystrix容错处理。
 * 编写的自定义Factory必须实现接口FallbackFactory。
 * FallbackFactory中的方法是
 *  服务接口的类型 create(Throwable 远程服务调用的错误)
 * 
 * 工厂实现方案和服务接口实现类实现方案的区别:
 *  工厂可以提供自定义的异常信息处理逻辑。因为create方法负责传递远程服务调用的异常对象。
 *  实现类可以快速的开发,但是会丢失远程服务调用的异常信息。
 */
@Component
public class FirstClientFeignServiceFallbackFactory implements FallbackFactory<FirstClientFeignService> {

    Logger logger = LoggerFactory.getLogger(FirstClientFeignServiceFallbackFactory.class);
    
    /**
     * create方法 - 就是工厂的生产产品的方法。
     *  当前工厂生产的产品就是服务接口的Fallback处理对象。 就是服务接口的实现类的对象。
     */
    @Override
    public FirstClientFeignService create(final Throwable cause) {
        
        return new FirstClientFeignService() {
            @Override
            public List<String> testFeign() {
                logger.warn("testFeign() - ", cause);
                List<String> result = new ArrayList<>();
                result.add("this is testFeign method fallback datas");
                return result;
            }

            @Override
            public FeignTestPOJO getById(Long id) {
                return new FeignTestPOJO(-1L, "this is getById method fallback datas");
            }

            @Override
            public FeignTestPOJO getByIdWithPOST(Long id) {
                return new FeignTestPOJO(-1L, "this is getByIdWithPOST method fallback datas");
            }

            @Override
            public FeignTestPOJO add(Long id, String name) {
                return new FeignTestPOJO(-1L, "this is add(id, name) method fallback datas");
            }

            @Override
            public FeignTestPOJO add(FeignTestPOJO pojo) {
                return new FeignTestPOJO(-1L, "this is add(pojo) method fallback datas");
            }

            @Override
            public FeignTestPOJO addWithPOST(FeignTestPOJO pojo) {
                return new FeignTestPOJO(-1L, "this is addWithPOST method fallback datas");
            }
        };
    }

}

 

转载于:https://www.cnblogs.com/yucongblog/p/11537457.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值