springcloud feign远程调用熔断详解

最近学习springcloud搭建微服务,各个模块单元之间要互相进行调用。博主原有是通过httpclient的方式进行调用,但是不得不每次都需要暴露url进行调用,feign提供本地调用的方式,不需要暴露url,t提供类似本地调用实现,并且配合hystrix熔断策略进行使用。

1.maven添加包引用

        <!--添加feign 提供服务调用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <!-- ApacheHttpClient 实现这个类,替换httpclient线程池-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>9.5.0</version>
        </dependency>

        <!-- 添加熔断器,提供服务熔断操作 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
2.配置文件需要填写eureka等相关配置文件
<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
spring-cloud的版本有 Brixton.RELEASE和Dalston.RELEASE,现在创建的新项目应该是引用Dalston.RELEASE这个版本,该版本下默认hystrix是关闭的,所以需要在属性文件中进行打开,如果没有设置为true,在后面的调试过程会发现熔断机制不生效

#开启hystrix熔断机制
feign.hystrix.enabled=true


feign简单调用,如以下实例,假如现在在同一个eureka下有一个项目A需要调用项目message-api项目,而message-api项目有一个接口为/example/hello,那么在A项目做以下配置:

1.建立远程调用客户端

@FeignClient(value = "message-api")
public interface MessageApiFeignClient {

    @RequestMapping(value = "/example/hello",method = RequestMethod.GET)
    public String getMessage(@RequestParam("name") String name);
}

本地方法直接调用该接口

    @RequestMapping(value="/hello3",method = RequestMethod.GET)
    public void hello3(String name){
        String result = messageApiFeignClient.getMessage("zhangsan");
        System.out.println(result);
    }

运行起来会发现成功调用。

通常feign和hystrix一起配合使用的,什么是hystrix,hystrix是分布式系统互相调用超时处理和容错的机制。例如著名的雪崩,通常A->B->C互相依次调用,但是很可能C项目出现问题,流量过大或者报错等,导致线程一直进行等待,导致拖垮整个链路层,线程资源耗尽。

工作原理:

1.隔离机制:

线程隔离:hystrix为每个依赖调用分配一个小的线程池,如果线程池已满调用将被立即拒绝,默认不采用排队,加速判定时间

信号隔离:信号隔离也可以限制并发访问,防止阻塞扩散,与线程隔离最大不同在于执行依赖代码的线程依然是请求线程(该线程需要通过信号申请,如果客户端是可信的且可以快速返回,可以使用信号隔离),springcloud zuul就是采用的是信号隔离的方式

2.熔断:

如果某个目标服务调用慢或者大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用


以下通过代码的方式进行详细讲解

hystrix通过设置fallback和fallbackFactory属性触发请求容灾降级

1.fallback

首先设置接口服务方一个简单的方法

@RestController
@RequestMapping("/example")
public class ExampleController {

    public static final Logger logger = LoggerFactory.getLogger(ExampleController.class);
    
    @RequestMapping(value = "/hello")
    @ResponseBody
    public String helloFeign(String name) throws Exception {
        logger.info("进入服务端:"+name);
        if("zhangsan".equals(name)){
            int i = 1/0;
        }else if("lisi".equals(name)){
            throw new Exception("服务端报错");
        }else{

        }
        return "hello!"+name;
    }
}
在feignclient上添加fallback

@FeignClient(value = "message-api",fallback = MessageApiFailBack.class)
public interface MessageApiFeignClient {

    @RequestMapping(value = "/example/hello",method = RequestMethod.GET)
    public String getMessage(@RequestParam("name") String name);
}
定义MessageApiFeignClient类
@Component
public class MessageApiFailBack implements MessageApiFeignClient{
    @Override
    public String getMessage(String name) {
        return "出错啦!";
    }
}
调用方进行本地调用

messageApiFeignClient.getMessage("zhangsan");
运行后
服务调用方打印:出错啦!

服务提供方打印:java.lang.ArithmeticException: / by zero
2.fallbackFactory与fallback不同的是可以打印详细的错误信息

将原来的fallback替换成fallbackFactory

@FeignClient(value = "message-api",fallbackFactory = MessageApiFailFactory.class)
public interface MessageApiFeignClient {

    @RequestMapping(value = "/example/hello",method = RequestMethod.GET)
    public String getMessage(@RequestParam("name") String name);
}
public interface MessageApiFeignFallBackFactoryClient extends MessageApiFeignClient{
}
@Component
public class MessageApiFailFactory implements FallbackFactory<MessageApiFeignClient> {

    public static final Logger logger = LoggerFactory.getLogger(MessageApiFailFactory.class);
    @Override
    public MessageApiFeignClient create(Throwable throwable) {
        logger.info("fallback; reason was: {}",throwable.getMessage());
        return new MessageApiFeignFallBackFactoryClient(){

            @Override
            public String getMessage(String name) {
                return "错误原因:"+throwable.getMessage();
            }
        };
    }
}
同样进行本地调用

messageApiFeignClient.getMessage("zhangsan");
运行后服务调用方打印:
错误原因:status 500 reading MessageApiFeignClient#getMessage(String); content:
{"timestamp":1508681203932,"status":500,"error":"Internal Server Error","exception":"java.lang.ArithmeticException","message":"/ by zero","path":"/example/hello"}

另外配置文件下可以设置hystrix服务超时机制

#开启hystrix请求超时机制   也可以设置成永久不超时hystrix.command.default.execution.timeout.enabled=false
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值