文档章节

聊聊spring cloud gateway的RetryGatewayFilter

go4it
 go4it
发布于 2018/06/19 23:07
字数 747
阅读 63
收藏 1

本文主要研究一下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
粉丝 76
博文 855
码字总数 747392
作品 0
深圳
私信 提问
Spring Cloud Gateway重试机制

前言 重试,我相信大家并不陌生。在我们调用Http接口的时候,总会因为某种原因调用失败,这个时候我们可以通过重试的方式,来重新请求接口。 生活中这样的事例很多,比如打电话,对方正在通话...

尹吉欢
2018/09/17
0
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
2018/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
2018/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
2018/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
2018/06/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux Wireshark普通用户启动使用方案

当系统安装好Wireshark后请正常启动是否可以进行正常使用,如果不行请参考下列指导 向系统添加一个用户组 sudo groupadd wireshark //如提示此组存在可跳过 将指定用户添加到这个组中 sudo...

CHONGCHEN
今天
1
0
CSS 选择器参考手册

CSS 选择器参考手册 选择器 描述 [attribute] 用于选取带有指定属性的元素。 [attribute=value] 用于选取带有指定属性和值的元素。 [attribute~=value] 用于选取属性值中包含指定词汇的元素。...

Jack088
今天
2
0
数据库篇一

数据库篇 第1章 数据库介绍 1.1 数据库概述  什么是数据库(DB:DataBase) 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据...

stars永恒
今天
4
0
Intellij IDEA中设置了jsp页面,但是在访问页面时却提示404

在Intellij IDEA中设置了spring boot的jsp页面,但是在访问时,却出现404,Not Found,经过查找资料后解决,步骤如下: 在Run/Debug Configurations面板中设置该程序的Working Directory选项...

uknow8692
昨天
4
0
day24:文档第五行增内容|每月1号压缩/etc/目录|过滤文本重复次数多的10个单词|人员分组|

1、在文本文档1.txt里第五行下面增加如下内容;两个方法; # This is a test file.# Test insert line into this file. 分析:给文档后增加内容,可以用sed 来搞定;也可以用while do done...

芬野de博客
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部