Spring Cloud Zuul的fallback优化

如何在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();
}

我们只要实现该接口,并实现public ClientHttpResponse fallbackResponse();方法,也就是说该方法会让我定义一个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()方法。如果不存在会走hystrixfallback逻辑(有可能直接抛出异常)。

说到这里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中的改进就介绍完了。


money.jpg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/477570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

技术动态 | 「新一代知识图谱关键技术」最新2022进展综述

转载公众号 | 专知链接&#xff1a;https://crad.ict.ac.cn/CN/10.7544/issn1000-1239.20210829近年来&#xff0c;国内外在新一代知识图谱的关键技术和理论方面取得了一定进展&#xff0c;以知识图谱为载体的典型应用也逐渐走进各个行业领域,包括智能问答、推荐系统、个人助手…

LeetCode 397. 整数替换(递归 贪心)

文章目录1. 题目2. 解题2.1 递归2.2 记忆化递归2.3 贪心1. 题目 给定一个正整数 n&#xff0c;你可以做如下操作&#xff1a; 如果 n 是偶数&#xff0c;则用 n / 2替换 n。如果 n 是奇数&#xff0c;则可以用 n 1或n - 1替换 n。 n 变为 1 所需的最小替换次数是多少&#…

搭配对比学习,万能的 prompt 还能做可控文本生成

文 | ZenMoore编 | 小轶可控文本生成&#xff0c;旨在让语言模型的输出带有我们想要的某种属性。比如情感、主题、三元组等。一般我们习惯采用 CTRL[1] 或者 PPLM[2] 等方式。但是&#xff0c;CTRL 是对整个语言模型进行 Finetuning, PPLM 因为需要在生成的过程中迭代更新 hidd…

Eureka Client注册到Eureka Server的秘密

前言 我们知道Eureka分为两部分&#xff0c;Eureka Server和Eureka Client。Eureka Server充当注册中心的角色&#xff0c;Eureka Client相对于Eureka Server来说是客户端&#xff0c;需要将自身信息注册到注册中心。本文主要介绍的就是在Eureka Client注册到Eureka Server时R…

论文浅尝-综述 | 基于强化学习的知识图谱综述

转载公众号 | 人工智能前沿讲习论文来源&#xff1a;https://crad.ict.ac.cn/CN/10.7544/issn1000-1239.20211264摘要&#xff1a;知识图谱是一种用图结构建模事物及事物间联系的数据表示形式&#xff0c;是实现认知智能的重要基础&#xff0c;得到了学术界和工业界的广泛关注.…

AI当下要破局,不能没有知识图谱!

AI或AI赋能已是传统行业智能化升级和转型的基本模式。近年来越来越多的传统行业的核心战略转移到人工智能领域&#xff0c;但随着大数据红利的消失殆尽&#xff0c;以深度学习为代表的感知智能水平日益接近其“天花板”&#xff08;来自肖仰华老师分享&#xff09;。数据驱动的…

LeetCode 495. 提莫攻击

1. 题目 在《英雄联盟》的世界中&#xff0c;有一个叫 “提莫” 的英雄&#xff0c;他的攻击可以让敌方英雄艾希&#xff08;编者注&#xff1a;寒冰射手&#xff09;进入中毒状态。现在&#xff0c;给出提莫对艾希的攻击时间序列和提莫攻击的中毒持续时间&#xff0c;你需要输…

Spring Cloud Config的配置中心获取不到最新配置信息的问题

本篇源于Spring Cloud Config的一个问题&#xff0c;但这个问题并非所有人都会遇到。如果您遇到了&#xff0c;那必须得看看这篇&#xff0c;如果没有遇到您也应该看看&#xff0c;防患于未然&#xff01; 问题描述 之前有朋友提出Spring Cloud Config的配置中心在运行一段时间…

图谱实战 | 京东基于时序知识图谱的问答系统

转载公众号 | DataFunSummit分享嘉宾&#xff1a;商超博士 京东硅谷研究院 研究员编辑整理&#xff1a;张存旺 北航杭州创新研究院出品平台&#xff1a;DataFunTalk导读&#xff1a;本文将分享Temporal Knowledge Graphs方向的一个最新尝试&#xff0c;如何在时序知识图谱上去做…

请不要吸开源的血

文 | 琴梨梨源 | 知乎今天无聊刷GitHub看到一个让我血压上来的项目乍一看&#xff0c;2.4k star&#xff0c;应该不像是什么小项目应该是比较有用的项目&#xff0c;但接下来的事情属实是让我气的很对于开源项目我是不喜欢下载预构建的成品的&#xff0c;我更喜欢自己动手从源代…

LeetCode 357. 计算各个位数不同的数字个数(DP)

1. 题目 给定一个非负整数 n&#xff0c;计算各位数字都不同的数字 x 的个数&#xff0c;其中 0 ≤ x < 10n。 示例: 输入: 2 输出: 91 解释: 答案应为除去 11,22,33,44,55,66,77,88,99 外&#xff0c;在 [0,100) 区间内的所有数字。来源&#xff1a;力扣&#xff08;Lee…

SpringCloud实战小贴士:Zuul的路径匹配

路径匹配 不论是使用传统路由的配置方式还是服务路由的配置方式&#xff0c;我们都需要为每个路由规则定义匹配表达式&#xff0c;也就是上面所说的path参数。在Zuul中&#xff0c;路由匹配的路径表达式采用了Ant风格定义。 Ant风格的路径表达式使用起来非常简单&#xff0c;…

技术动态 | 一文读懂事件知识图谱

转载公众号 | 普适极客文章来源 | 中国科学院网络数据重点实验室【导读】随着事件这类动态知识得到越来越多的关注&#xff0c;学术界涌现出许多事件知识图谱相关的概念。但究竟事件知识图谱是怎么发展而来的&#xff1f;什么是事件知识图谱&#xff1f;它和其他相关概念之间有…

华为开源CTR Benchmark,学术界SOTAs的照妖镜?

文 | 卖萌酱大家好&#xff0c;我是卖萌酱。众所周知&#xff0c;与CV、NLP不同&#xff0c;搜索、广告、推荐领域的学术界paper在很多问题上喜欢各玩各的&#xff0c;缺乏一个统一可比的benchmark。就推荐/广告中核心的CTR预估问题来讲&#xff0c;从传统的LR、FM到Wide&D…

LeetCode 376. 摆动序列(贪心 动态规划)

文章目录1. 题目2. 解题2.1 贪心2.2 动态规划1. 题目 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为摆动序列。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。少于两个元素的序列也是摆动序列。 例如&#xff0c; [1,7,4,9,2…

Spring Cloud实战小贴士:Zuul的饥饿加载(eager-load)使用

上一篇我们介绍了如何使用Ribbon的earger-load配置加速Spring Cloud中对服务接口的第一次调用。可是这样只是解决了内部服务间的调用&#xff0c;另外一个问题依然经常困扰我们&#xff0c;那就是网关到内部服务的访问。由于Spring Cloud Zuul的路由转发也是通过Ribbon实现负载…

论文浅尝 | ESimCSE:无监督句子表示对比学习的增强样本构建方法

笔记整理&#xff1a;高超尘&#xff0c;中国科学院信息工程研究所硕士动机对比学习在学习无监督句向量方面引起了广泛的关注。其中最受关注的无监督方法是unsup-SimCSE&#xff08;Gao et al., EMNLP 2021)。Unsup-SimCSE使用Dropout作为数据增强方法&#xff0c;将相同的输入…

一份北大信科内部流传的 “CS 自救指南”

本文转载自公众号“夕小瑶的卖萌屋”&#xff0c;专业带逛互联网算法圈的神操作 -----》我是传送门 关注后&#xff0c;回复以下口令&#xff1a; 回复【789】 &#xff1a;领取深度学习全栈手册&#xff08;含NLP、CV海量综述、必刷论文解读&#xff09; 回复【入群】&#xf…

LeetCode 678. 有效的括号字符串(栈)

1. 题目 给定一个只包含三种字符的字符串&#xff1a;&#xff08; &#xff0c;&#xff09; 和 *&#xff0c;写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则&#xff1a; 任何左括号 ( 必须有相应的右括号 )。任何右括号 ) 必须有相应的左括号 ( 。…

Spring Cloud实战小贴士:Ribbon的饥饿加载(eager-load)模式

我们在使用Spring Cloud的Ribbon或Feign来实现服务调用的时候&#xff0c;如果我们的机器或网络环境等原因不是很好的话&#xff0c;有时候会发现这样一个问题&#xff1a;我们服务消费方调用服务提供方接口的时候&#xff0c;第一次请求经常会超时&#xff0c;而之后的调用就没…