1. 回顾

  上文讲解了使用注解@HystrixCommand的fallbackMethod属性实现回退。然而,Feign是以接口形式工作的,

它没有方法体,前文讲解的方式显然不适用与Feign。

  事实上,Spring Cloud默认已为Feign整合了Hystrix,只要Hystrix在项目的classpath中,Feign默认就会用

断路器包裹所有方法。

2. 为Feign添加回退

  > 复制项目 microservice-consumer-movie-feign ,将 ArtifactId 修改为 microservice-consumer-movie-feign-hystrix-fallback

  > 将之前编写的Feign接口修改为如下内容:

package com.itmuch.cloud.microserviceconsumermoviefeignhystrixfallback.feign;

import com.itmuch.cloud.microserviceconsumermoviefeignhystrixfallback.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; /**
* Feign的fallback测试类
* 使用@FeignClient的fallback属性指定回退类
*/
@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class)
public interface UserFeignClient { @GetMapping(value = "/{id}")
User findById(@PathVariable("id") Long id); } /**
* 回退类FeignClientFallback需实现Feign Client接口
* FeignClientFallback也可以是public class,没有区别
*/
@Component
class FeignClientFallback implements UserFeignClient { @Override
public User findById(Long id) {
User user = new User();
user.setId(-1L);
user.setUsername("默认用户");
return user;
}
}

  > 修改 application.yml 文件,声明 Feign 的 Hystrix 支持

feign:
hystrix:
enabled: true

  > 启动 microservice-discovery-eureka

  > 启动 microservice-provider-user

  > 启动 microservice-consumer-movie-feign-hystrix-fallback

  > 访问 http://localhost:8010/user/1 ,可正常获取结果

  > 停止 microservice-provider-user

  > 访问 http://localhost:8010/user/1 ,可获取回退方法里返回的结果

3. 通过Fallback Factory检查回退原因

  > 复制项目 microservice-consumer-movie-feign,将 ArtifactId 修改为 microservice-consumer-movie-feign-hystrix-fallback-factory

  > 修改 UserFeignClient.java 为如下内容

package com.itmuch.cloud.microserviceconsumermoviefeignhystrixfallbackfactory.feign;

import com.itmuch.cloud.microserviceconsumermoviefeignhystrixfallbackfactory.pojo.User;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; @FeignClient(name = "microservice-provider-user", fallbackFactory = FeignClientFallbackFactory.class)
public interface UserFeignClient { @GetMapping(value = "/{id}")
User findById(@PathVariable("id") Long id); } /**
* UserFeignClient的fallbackFactory类,该类需要实现FallbackFactory接口,并覆写create方法
*/
@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> { private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class); @Override
public UserFeignClient create(Throwable throwable) {
// 下方匿名方法的Lambda表达式。>= JDK8
return (id) -> {
// 日志最好放在各个fallback方法中,而不要直接放在create方法中。
// 否则在引用启动时,就会打印该日志
FeignClientFallbackFactory.LOGGER.info("fallback; reason was: ", throwable);
User user = new User();
user.setId(-1L);
user.setUsername("默认用户");
return user;
}; /* return new UserFeignClient() {
@Override
public User findById(Long id) {
// 日志最好放在各个fallback方法中,而不要直接放在create方法中。
// 否则在引用启动时,就会打印该日志
FeignClientFallbackFactory.LOGGER.info("fallback; reason was: ", throwable);
User user = new User();
user.setId(-1L);
user.setUsername("默认用户");
return user;
}
};*/
} }

  > 修改 application.yml 文件,声明 Feign 的 Hystrix 支持

feign:
hystrix:
enabled: true

  > 跟上方测试方法一样。此次调用回退方法时,控制台会打出错误日志

2018-06-07 13:55:31.716  INFO 5188 --- [provider-user-1] c.i.c.m.f.FeignClientFallbackFactory     : fallback; reason was: 

java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: microservice-provider-user
at org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:71) ~[spring-cloud-openfeign-core-2.0.0.M1.jar:2.0.0.M1]
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:97) ~[feign-core-9.5.1.jar:na]
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76) ~[feign-core-9.5.1.jar:na]
at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:108) ~[feign-hystrix-9.5.1.jar:na]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302) ~[hystrix-core-1.5.12.jar:1.5.12]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298) ~[hystrix-core-1.5.12.jar:1.5.12]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.6.jar:1.3.6]
at rx.Observable.unsafeSubscribe(Observable.java:10256) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.3.6.jar:1.3.6]
at rx.Observable.unsafeSubscribe(Observable.java:10256) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.6.jar:1.3.6]
at rx.Observable.unsafeSubscribe(Observable.java:10256) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100) [rxjava-1.3.6.jar:1.3.6]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56) [hystrix-core-1.5.12.jar:1.5.12]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47) [hystrix-core-1.5.12.jar:1.5.12]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69) [hystrix-core-1.5.12.jar:1.5.12]
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) [rxjava-1.3.6.jar:1.3.6]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_161]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_161]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_161]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_161]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]
Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: microservice-provider-user
at com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483) ~[ribbon-loadbalancer-2.2.4.jar:2.2.4]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184) ~[ribbon-loadbalancer-2.2.4.jar:2.2.4]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.2.4.jar:2.2.4]
at rx.Observable.unsafeSubscribe(Observable.java:10256) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42) ~[rxjava-1.3.6.jar:1.3.6]
at rx.Observable.unsafeSubscribe(Observable.java:10256) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:127) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:73) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:52) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:79) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276) ~[rxjava-1.3.6.jar:1.3.6]
at rx.Subscriber.setProducer(Subscriber.java:209) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:138) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129) ~[rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) [rxjava-1.3.6.jar:1.3.6]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) [rxjava-1.3.6.jar:1.3.6]
at rx.Observable.subscribe(Observable.java:10352) [rxjava-1.3.6.jar:1.3.6]
at rx.Observable.subscribe(Observable.java:10319) [rxjava-1.3.6.jar:1.3.6]
at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:443) ~[rxjava-1.3.6.jar:1.3.6]
at rx.observables.BlockingObservable.single(BlockingObservable.java:340) ~[rxjava-1.3.6.jar:1.3.6]
at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:112) ~[ribbon-loadbalancer-2.2.4.jar:2.2.4]
at org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:63) ~[spring-cloud-openfeign-core-2.0.0.M1.jar:2.0.0.M1]
... 32 common frames omitted 2018-06-07 14:00:17.616 INFO 5188 --- [trap-executor-0] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration

 4. 为Feign禁用Hystrix

  上面说过,在Spring Cloud中,只要Hystrix在项目的classpath中,Feign就会使用断路器包裹Feign客户端的所有方法。这样虽然方便,但是很多场景下并不需要该功能。

  全局禁用Hystrix,只须在 application.yml 中配置 feign.hystrix.enabled=false 即可

  借助Feign的自定义配置,可轻松为指定名称的Feign客户端禁用Hystrix。

  > 创建配置类

package com.itmuch.cloud.microserviceconsumermoviefeignhystrixfallbackfactory.config;

import feign.Feign;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope; @Configuration
public class FeignDisableHystrixConfiguration { @Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
} }

  > 在想要禁用Hystrix的@FeignClient引用该配置类即可

@FeignClient(name = "microservice-provider-user", configuration = FeignDisableHystrixConfiguration.class)
public interface UserFeignClient { }

5. 总结

  本文讲了Feign使用Hystrix的各种知识。包括使用、检查回退原因、禁用Hystrix等。

  下文将讲解Hystrix的监控。敬请期待~~~

6. 参考

  周立 --- 《Spring Cloud与Docker微服务架构与实战》

SpringCloud系列十六:Feign使用Hystrix的更多相关文章

  1. SpringCloud系列十五:使用Hystrix实现容错

    1. 回顾 上文讲解了容错的重要性,以及容错需要实现的功能. 本文来讲解使用Hystrix实现容错. 2. Hystrix简介 Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程系 ...

  2. S3C2416裸机开发系列十六_sd卡驱动实现

    S3C2416裸机开发系列十六 sd卡驱动实现 象棋小子    1048272975 SD卡(Secure Digital Memory Card)具有体积小.容量大.传输数据快.可插拔.安全性好等长 ...

  3. 跟我学SpringCloud | 第十六篇:微服务利剑之APM平台(二)Pinpoint

    目录 SpringCloud系列教程 | 第十六篇:微服务利剑之APM平台(二)Pinpoint 1. Pinpoint概述 2. Pinpoint主要特性 3. Pinpoint优势 4. Pinp ...

  4. 学习ASP.NET Core Razor 编程系列十六——排序

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  5. 小D课堂 - 新版本微服务springcloud+Docker教程_5-04 feign结合hystrix断路器开发实战下

    笔记 4.Feign结合Hystrix断路器开发实战<下>     简介:讲解SpringCloud整合断路器的使用,用户服务异常情况     1.feign结合Hystrix       ...

  6. 小D课堂 - 新版本微服务springcloud+Docker教程_5-03 feign结合hystrix断路器开发实战上

    笔记 3.Feign结合Hystrix断路器开发实战<上>     简介:讲解SpringCloud整合断路器的使用,用户服务异常情况 1.加入依赖          注意:网上新旧版本问 ...

  7. 为什么不让用join?《死磕MySQL系列 十六》

    大家好,我是咔咔 不期速成,日拱一卒 在平时开发工作中join的使用频率是非常高的,很多SQL优化博文也让把子查询改为join从而提升性能,但部分公司的DBA又不让用,那么使用join到底有什么问题呢 ...

  8. SpringCloud系列十二:手动创建Feign

    1. 回顾 上文讲解了自定义Feign.但是在某些场景下,前文自定义Feign的方式满足不了需求,此时可使用Feign Builder API手动创建Feign. 本文围绕以下场景,为大家讲解如何手动 ...

  9. SpringCloud系列十:使用Feign实现声明式REST调用

    1. 回顾 前文的示例中是使用RestTemplate实现REST API调用的,代码大致如下: @GetMapping("/user/{id}") public User fin ...

随机推荐

  1. Eclipse运行Maven的SpringMVC项目Run on Server时出现错误:Error configuring application listener of class org.springframework.web.context.ContextLoaderListener的问题解决

    错误: 严重: Error configuring application listener of class org.springframework.web.context.ContextLoade ...

  2. java自带的jvm分析工具

    http://domark.iteye.com/blog/1924302   这段时间觉得很有必要对java的内存分析工具进行熟悉,这样以后出现机器负载较高,或者反应很慢的时候,我就可以查找原因了.上 ...

  3. Eclipse环境安装C/C++插件CDT和Eclipse安装的插件卸载(删除)

    http://blog.csdn.net/typa01_kk/article/details/49252513

  4. What happens when a SQL Query runs?

    Posted by Padma Chitturi in Uncategorized. Leave a Comment Hi Folks, It has been such a long time th ...

  5. DN安卓2014版(5-9)

    DN安卓2014版(5-9) 联系2g32@sina.com

  6. 十四.spring-boot使用mybatis

    在springMVC+spring中使用mybatis已经非常非常的灵活,但是需要配置很多的信息 一.创建maven web project 二.创建数据库表 三.在application.prope ...

  7. xss bypass

    重要的4个规则: 1 &符号不应该出现在HTML的大部分节点中. 2 尖括号<>是不应该出现在标签内的,除非为引号引用. 3 在text节点里面,<左尖括号有很大的危害. 4 ...

  8. Git系列六之标签管理

    1.Git标签管理 当版本仓库内的数据有个大的改善或者功能更新,我们经常会打一个类似于软件版本号的标签,这样通过标签就可以将版本库中的某个历史版本给记录下来,方便我们随时将特定历史时期的数据取出来用, ...

  9. 你以为border-radius只是圆角吗?【各种角度】

    border-radius,国内翻译成圆角,你可能以为这个属性就是用来画圆角,没错,但是除此之外,它还可以做点别的事情. radius其实指的是边框所在圆的半径,这个CSS3属性不仅能够创建圆角,还可 ...

  10. java 图片文字识别 ocr

    最近在开发的时候需要识别图片中的一些文字,网上找了相关资料之后,发现google有一个离线的工具,以下为java使用的demo 在此之前,使用这个工具需要在本地安装OCR工具: 下面一个是一定要安装的 ...