文档章节

聊聊spring cloud gateway的RetryGatewayFilter

go4it
 go4it
发布于 06/19 23:07
字数 747
阅读 21
收藏 1
点赞 0
评论 0

本文主要研究一下spring cloud gateway的RetryGatewayFilter

GatewayAutoConfiguration

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

@Configuration
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)
@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
    //......
	@Bean
	public RetryGatewayFilterFactory retryGatewayFilterFactory() {
		return new RetryGatewayFilterFactory();
	}
    //......
}

默认启用了RetryGatewayFilterFactory

RetryGatewayFilterFactory

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java

public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory<RetryGatewayFilterFactory.RetryConfig> {
	private static final Log log = LogFactory.getLog(RetryGatewayFilterFactory.class);

	public RetryGatewayFilterFactory() {
		super(RetryConfig.class);
	}

	@Override
	public GatewayFilter apply(RetryConfig retryConfig) {
		retryConfig.validate();

		Predicate<? super RepeatContext<ServerWebExchange>> predicate = context -> {
			ServerWebExchange exchange = context.applicationContext();
			if (exceedsMaxIterations(exchange, retryConfig)) {
				return false;
			}

			HttpStatus statusCode = exchange.getResponse().getStatusCode();
			HttpMethod httpMethod = exchange.getRequest().getMethod();

			boolean retryableStatusCode = retryConfig.getStatuses().contains(statusCode);

			if (!retryableStatusCode && statusCode != null) { // null status code might mean a network exception?
				// try the series
				retryableStatusCode = retryConfig.getSeries().stream()
						.anyMatch(series -> statusCode.series().equals(series));
			}

			boolean retryableMethod = retryConfig.getMethods().contains(httpMethod);
			return retryableMethod && retryableStatusCode;
		};

		Repeat<ServerWebExchange> repeat = Repeat.onlyIf(predicate)
				.doOnRepeat(context -> reset(context.applicationContext()));

		//TODO: support timeout, backoff, jitter, etc... in Builder

		Predicate<RetryContext<ServerWebExchange>> retryContextPredicate = context -> {
			if (exceedsMaxIterations(context.applicationContext(), retryConfig)) {
				return false;
			}

			for (Class<? extends Throwable> clazz : retryConfig.getExceptions()) {
				if (clazz.isInstance(context.exception())) {
					return true;
				}
			}
            return false;
		};

		Retry<ServerWebExchange> reactorRetry = Retry.onlyIf(retryContextPredicate)
				.doOnRetry(context -> reset(context.applicationContext()))
				.retryMax(retryConfig.getRetries());
		return apply(repeat, reactorRetry);
	}

	public boolean exceedsMaxIterations(ServerWebExchange exchange, RetryConfig retryConfig) {
		Integer iteration = exchange.getAttribute("retry_iteration");

		//TODO: deal with null iteration
		return iteration != null && iteration >= retryConfig.getRetries();
	}

	public void reset(ServerWebExchange exchange) {
		//TODO: what else to do to reset SWE?
		exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_ALREADY_ROUTED_ATTR);
	}

	@Deprecated
	public GatewayFilter apply(Repeat<ServerWebExchange> repeat) {
		return apply(repeat, Retry.onlyIf(ctxt -> false));
	}

	public GatewayFilter apply(Repeat<ServerWebExchange> repeat, Retry<ServerWebExchange> retry) {
		return (exchange, chain) -> {
			log.trace("Entering retry-filter");

			int iteration = exchange.getAttributeOrDefault("retry_iteration", -1);
			exchange.getAttributes().put("retry_iteration", iteration + 1);

			return Mono.fromDirect(chain.filter(exchange)
					.log("retry-filter", Level.INFO)
					.retryWhen(retry.withApplicationContext(exchange))
					.repeatWhen(repeat.withApplicationContext(exchange)));
		};
	}
    //......
}
  • 可以看到这个filter使用了reactor的Retry组件,同时往exchange的attribues添加retry_iteration,用来记录重试次数,该值默认从-1开始,第一次执行的时候,retry_iteration+1为0。之后每重试一次,就添加1。
  • filter的apply接收两个参数,一个是Repeat<ServerWebExchange>,一个是Retry<ServerWebExchange>。
  • repeat与retry的区别是repeat是在onCompleted的时候会重试,而retry是在onError的时候会重试。这里由于不一定是异常的时候才可能重试,所以加了repeat。

RetryConfig

spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java

	public static class RetryConfig {
		private int retries = 3;
		
		private List<Series> series = toList(Series.SERVER_ERROR);
		
		private List<HttpStatus> statuses = new ArrayList<>();
		
		private List<HttpMethod> methods = toList(HttpMethod.GET);

		private List<Class<? extends Throwable>> exceptions = toList(IOException.class);

		//......

		public void validate() {
			Assert.isTrue(this.retries > 0, "retries must be greater than 0");
			Assert.isTrue(!this.series.isEmpty() || !this.statuses.isEmpty(),
					"series and status may not both be empty");
			Assert.notEmpty(this.methods, "methods may not be empty");
		}
        //......

	}

可以看到配置文件有5个属性,如下:

  • retries,默认为3,用来标识重试次数
  • series,用来指定哪些段的状态码需要重试,默认SERVER_ERROR即5xx
  • statuses,用于指定哪些状态需要重试,默认为空,它跟series至少得指定一个
  • methods,用于指定那些方法的请求需要重试,默认为GET
  • exceptions,用于指定哪些异常需要重试,默认为java.io.IOException

实例

spring:
  cloud:
    gateway:
      routes:
      - id: retry-demo
        uri: http://localhost:9090
        predicates:
        - Path=/retry/**
        filters:
        - name: Retry
          args:
           retries: 15
           series:
            - SERVER_ERROR
            - CLIENT_ERROR
           methods:
            - GET
            - POST
           exceptions:
            - java.io.IOException
            - java.util.concurrent.TimeoutException

这里指定了针对4xx及5xx的GET或POST方法或者IOException或TimeoutException的时候进行重试,重试次数为15次。

小结

RetryGatewayFilter借助了reactor-addons的retry组件进行了重试,主要使用了Mono的repeatWhen及retryWhen方法,前者在onCompleted的时候触发,后者在onError的时候触发。

doc

© 著作权归作者所有

共有 人打赏支持
go4it
粉丝 51
博文 675
码字总数 477616
作品 0
深圳
聊聊spring cloud gateway的GatewayFilter

序 本文主要研究一下spring cloud gateway的GatewayFilter GatewayFilter spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/filter/GatewayFilter.jav......

go4it
06/09
0
0
聊聊spring.cloud.gateway.default-filters

序 本文主要研究下spring.cloud.gateway.default-filters 配置 default-filters,配置的是FilterDefinition对象 FilterDefinition spring-cloud-gateway-core-2.0.0.RC1-sources.jar!/org/sp......

go4it
06/01
0
0
聊聊spring cloud的RequestHeaderToRequestUri

序 本文主要研究一下spring cloud的RequestHeaderToRequestUriGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gate......

go4it
06/16
0
0
聊聊spring cloud gateway的RedirectToGatewayFilter

序 本文主要研究下spring cloud gateway的RedirectToGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/confi......

go4it
06/13
0
0
聊聊spring cloud gateway的SetStatusGatewayFilter

序 本文主要研究下spring cloud gateway的SetStatusGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config......

go4it
06/15
0
0
聊聊spring cloud gateway的RemoveHopByHopHeadersFilter

序 本文主要研究一下spring cloud gateway的RemoveHopByHopHeadersFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC1-sources.jar!/org/springframework/cloud/gateway......

go4it
05/30
0
0
聊聊spring cloud的PreserveHostHeaderGatewayFilter

序 本文主要研究下spring cloud gateway的PreserveHostHeaderGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gatew......

go4it
06/14
0
0
聊聊spring cloud的DiscoveryClientRouteDefinitionLocator

序 本文主要研究一下spring cloud的DiscoveryClientRouteDefinitionLocator GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gatew......

go4it
06/05
0
0
聊聊spring cloud gateway的GlobalFilter

序 本文主要研究一下spring cloud gateway的GlobalFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/Gateway......

go4it
06/08
0
0
聊聊spring cloud gateway的LoadBalancerClientFilter

序 本文主要研究一下spring cloud gateway的LoadBalancerClientFilter GatewayLoadBalancerClientAutoConfiguration spring-cloud-gateway-core-2.0.0.RELEASE-sources.jar!/org/springfram......

go4it
06/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

arts-week1

Algorithm 594. Longest Harmonious Subsequence - LeetCode 274. H-Index - LeetCode 219. Contains Duplicate II - LeetCode 217. Contains Duplicate - LeetCode 438. Find All Anagrams ......

yysue
25分钟前
0
0
NNS拍卖合约

前言 关于NNS的介绍,这里就不多做描述,相关的信息可以查看NNS的白皮书http://doc.neons.name/zh_CN/latest/nns_background.html。 首先nns中使用的竞价货币是sgas,关于sgas介绍可以戳htt...

红烧飞鱼
57分钟前
0
0
Java IO类库之管道流PipeInputStream与PipeOutputStream

一、java管道流介绍 在java多线程通信中管道通信是一种重要的通信方式,在java中我们通过配套使用管道输出流PipedOutputStream和管道输入流PipedInputStream完成线程间通信。多线程管道通信的...

老韭菜
今天
0
0
用Python绘制红楼梦词云图,竟然发现了这个!

Python在数据分析中越来越受欢迎,已经达到了统计学家对R的喜爱程度,Python的拥护者们当然不会落后于R,开发了一个个好玩的数据分析工具,下面我们来看看如何使用Python,来读红楼梦,绘制小...

猫咪编程
今天
1
0
Java中 发出请求获取别人的数据(阿里云 查询IP归属地)

1.效果 调用阿里云的接口 去定位IP地址 2. 代码 /** * 1. Java中远程调用方法 * http://localhost:8080/mavenssm20180519/invokingUrl.action * @Title: invokingUrl * @Description: * @ret......

Lucky_Me
今天
1
0
protobuf学习笔记

相关文档 Protocol buffers(protobuf)入门简介及性能分析 Protobuf学习 - 入门

OSC_fly
昨天
0
0
Mybaties入门介绍

Mybaties和Hibernate是我们在Java开发中应用的比较多的两个ORM框架。当然,目前Mybaties正在慢慢取代Hibernate,这是因为相比较Hibernate而言Mybaties性能更好,响应更快,更加灵活。我们在开...

王子城
昨天
2
0
编程学习笔记之python深入之装饰器案例及说明文档[图]

编程学习笔记之python深入之装饰器案例及说明文档[图] 装饰器即在不对一个函数体进行任何修改,以及不改变整体的原本意思的情况下,增加函数功能的新函数,因为这个新函数对旧函数进行了装饰...

原创小博客
昨天
1
0
流利阅读笔记33-20180722待学习

黑暗中的生物:利用奇技淫巧快活生存 Daniel 2018-07-22 1.今日导读 如果让你在伸手不见五指的黑暗当中生存,你能熬过几天呢?而大千世界,无奇不有。在很多你不知道的角落,有些生物在完全黑...

aibinxiao
昨天
6
0
Hystrix降级逻辑中如何获取触发的异常

通过之前Spring Cloud系列教程中的《Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)》一文,我们已经知道如何通过Hystrix来保护自己的服务不被外部依赖方拖垮的情况。但是实际...

程序猿DD
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部