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. 搭建MySQL的主从、半同步、主主复制架构

    复制其最终目的是让一台服务器的数据和另外的服务器的数据保持同步,已达到数据冗余或者服务的负载均衡.一台主服务器可以连接多台从服务器,并且从服务器也可以反过来作为主服务器.主从服务器可以位于不同的网络拓 ...

  2. WiFi安全测试工具、蹭网利器–WiFiPhisher(转)

    读后感:看了一下官方介绍,需要2张无线网卡的支持,其中一张应该是用来影响用户和正常热点的连接,即进行dos攻击,而另外一张可以模拟一个假AP等待用户接入,这种攻击将对物联网和智能家居安防等产品造成很大 ...

  3. 【centOS】【xshell】xshell连接虚拟机上的centOS,操作途中突然断开连接,报错:connect closed by foreign host

    如题  xshell连接虚拟机上的centOS,操作途中突然断开连接,报错:connect closed by foreign host 快捷解决方法: 在虚拟机上centOS重新启动网络,即可解决问 ...

  4. 【java】【多线程】等待开启的多个线程都执行完成,再做事情,怎么实现

    今天在controller中写一个接口用来测试模拟多个请求同时到达 下订单的情况, 怎么能有效保证高并发下的库存和销量的一致性呢?[具体实现方法:https://www.cnblogs.com/sxd ...

  5. 【JSP JSTL】<c:if>多个判断条件 + <c:foreach>满足条件跳出循环

    有一个需求,将所拥有的权限存放于session中,现在JSP页面判断这些如果在所有权限中有某一个或者某几个,就显示相对应的页面内容 举一个例子,实现以上的逻辑,<c:if>多个判断条件 + ...

  6. 项目中简单使用ztree,简单数据。

    由于公司架构较旧,使用的jdk版本为1.4,页面上也没有el表达式. 加入 js 文件 <% String context = request.getContextPath(); %> & ...

  7. Anaconda安装Graphviz, mac下Graphviz安装, pcharm中调用pycharm, Graphviz典型例子

    mac下的Graphviz安装及使用 2017年10月13日 13:30:07 阅读数:7495 一.安装 Graphviz http://www.graphviz.org/ mac用户建议直接用ho ...

  8. Windows 7下Maven3.0.3的安装

    1.去Maven官网下载zip的maven3.0.3压缩包 2.将安装包解压到某目录,我在这里解压到D:\Program Files (x86)\apache-maven-3.0.3 3.设置系统变量 ...

  9. 关于TagHelper的那些事情——Microsoft.AspNet.Mvc.TagHelpers介绍

    写在开始 在上一篇文章中,简单介绍了什么是TagHelper,怎么使用它.接下来我会简单介绍一下微软随着ASP.NET5一起发布的TagHelpers.它们分别是: AnchorTagHelper C ...

  10. zigbee 学习笔记

    在德州仪器的站点:http://www.ti.com.cn/tool/cn/z-stack上下载安装zigbee2007协议栈版,我的是ZStack-CC2530-2.3.0-1.4.0. 以下演示一 ...