Edgware.RC1中ZuulFallbackProvider的改进
作者:ligang 原文:http://www.spring4all.com/article/158
如何在Zuul中使用fallback功能
我们在项目中使用Spring cloud zuul的时候,有一种这样的需求,就是当我们的zuul进行路由分发时,如果后端服务没有启动,或者调用超时,这时候我们希望Zuul提供一种降级功能,而不是将异常暴露出来。
在Dalston版本中,Spring cloud zuul提供这种降级功能,操作步骤如下:
- 在主函数上添加
@EnbaleZuulProxy
注解。 - 实现
ZuulFallbackProvider
接口。
对应 ZuulFallbackProvider
源码如下:
public interface ZuulFallbackProvider {
/**
* The route this fallback will be used for.
* @return The route the fallback will be used for.
*/
public String getRoute();
/**
* Provides a fallback response.
* @return The fallback response.
*/
public ClientHttpResponse fallbackResponse();
}
我们只要实现该接口,并实现 publicClientHttpResponsefallbackResponse();
方法,也就是说该方法会让我定义一个 ClientHttpResponse
作为当异常出现时的返回内容。
通过源码我们可知,Zuul提供三个配置文件,每一个配置文件代表用不同种方式进行请求的转发:
RestClientRibbonConfiguration
OkHttpRibbonConfiguration
-
HttpClientRibbonConfiguration
(默认情况)HttpClientRibbonConfiguration
源码如下(只体现涉及fallback模块):
@Configuration
@ConditionalOnRibbonHttpClient
protected static class HttpClientRibbonConfiguration {
@Autowired(required = false)
private Set<ZuulFallbackProvider> zuulFallbackProviders = Collections.emptySet();
@Bean
@ConditionalOnMissingBean
public RibbonCommandFactory<?> ribbonCommandFactory(
SpringClientFactory clientFactory, ZuulProperties zuulProperties
)
{
return new HttpClientRibbonCommandFactory(
clientFactory,
zuulProperties,
zuulFallbackProviders
);
}
}
通过源码我们可以了解,Zuul将你自定义的fallbackprovider保存在一个Set集合中,并作为 HttpClientRibbonCommandFactory
构造器的参数。
当zuul在转发请求时最终会利用 AbstractRibbonCommand
进行处理。通过源码我们知道 AbstractRibbonCommand
继承了 HystrixCommand
,所以真正转发请求的业务逻辑是在重写 HystrixCommand
类的 run
方法中进行的。
具体源码如下:
@Override
protected ClientHttpResponse run() throws Exception {
final RequestContext context = RequestContext.getCurrentContext();
RQ request = createRequest();
RS response = this.client.executeWithLoadBalancer(request, config);
context.set("ribbonResponse", response);
// Explicitly close the HttpResponse if the Hystrix command timed out to
// release the underlying HTTP connection held by the response.
//
if (this.isResponseTimedOut()) {
if (response != null) {
response.close();
}
}
return new RibbonHttpResponse(response);
}
我们知道 HystrixCommand
提供 getFallback()
方法,这个方法的作用是当 run()
方法执行出现异常时,会自动调用 getFallback()
方法,从而完成降级功能。( HystrixCommand
是Hystrix的知识,有兴趣的同学可以参照官方git文档)。
由于 AbstractRibbonCommand
继承了 HystrixCommand
,它不仅重写了 run()
方法,而且重写了 getFallback()
方法,具体源码如下:
@Override
protected ClientHttpResponse getFallback() {
if(zuulFallbackProvider != null) {
return zuulFallbackProvider.fallbackResponse();
}
return super.getFallback();
}
通过源码我们知道,首先会去判断是否存在自定义的zuulFallbackProvider,如果有,那么直接回调你自定义实现类的 fallbackResponse()
方法。如果不存在会走 hystrix
的 fallback
逻辑(有可能直接抛出异常)。 说到这里Zuul的降级原理大致就说完了,细心的朋友可以发现这样的一个问题,就是虽然Zuul提供了降级的回调方法 fallbackResponse()
,但是这个方法是无参的,也就是说此时虽然你能够给调用端返回一个消息,但是此时你并不知道发生了什么样的异常(也就是说在这里你是获取不到异常信息的)。
Edgware.RC1版本的改进
在Edgware.RC1版本中Spring cloud zuul针对于降级进行了升级,升级的内容主要是解决上面说到的当降级出现时,怎样在降级方法中获取具体的异常信息。 增加了一个接口 FallbackProvider
,这个接口继承了现有的 ZuulFallbackProvider
接口,源码如下:
public interface FallbackProvider extends ZuulFallbackProvider {
/**
* Provides a fallback response based on the cause of the failed execution.
*
* @param cause cause of the main method failure
* @return the fallback response
*/
ClientHttpResponse fallbackResponse(Throwable cause);
可以看到这个接口有一个方法,这个方法的参数是 Throwable
,也就是说此时是用能力获取异常信息的。 接下来改造的内容在 AbstractRibbonCommand
类中,主要是对原有的 getFallback()
进行改造,同时增加了一个 getFallbackResponse()
方法。下面通过源码具体了解下:
@Override
protected ClientHttpResponse getFallback() {
if(zuulFallbackProvider != null) {
return getFallbackResponse();
}
return super.getFallback();
}
可以看到从原来调用 zuulFallbackProvider.fallbackResponse();
转而调用内部方法 getFallbackResponse()
。 getFallbackResponse()
源码如下:
protected ClientHttpResponse getFallbackResponse() {
if (zuulFallbackProvider instanceof FallbackProvider) {
Throwable cause = getFailedExecutionException();
cause = cause == null ? getExecutionException() : cause;
if (cause == null) {
zuulFallbackProvider.fallbackResponse();
} else {
return ((FallbackProvider) zuulFallbackProvider).fallbackResponse(cause);
}
}
return zuulFallbackProvider.fallbackResponse();
}
通过源码可知,此时会根据 Throwable
是否存在来决定走哪种类型的降级方法(原来的还是带有参数的)。
到此Zuul的实现降级的原理以及Edgware.RC1中的改进就介绍完了。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 02.视频播放器整体结构
- Spring中@Component和@Bean
- HTTP对接方式
- 使用ShardingSphere 过程中遇到的关于spring boot 版本的问题
- 腾讯云TKE-Pod案例: 容器内crontab问题
- iOS音视频接入 - TRTC多人视频会议
- Spring系列 SpringMVC的请求与数据响应
- codeforces 1349A(数学)
- leetcode之找不同
- 太强了,这居然是19年双非本科开发一年的Android面筋!开发几年的老程序员自叹不如
- Kotlin Vocabulary | Reified: 类型擦除后再生计划
- WorkManager 在 Kotlin 中的实践
- ElasticSearch 集群分片内部原理
- 360webscan防注入脚本全面绕过
- JQuery 入门学习(完结)