网站首页 > 技术教程 正文
序
本文主要研究一下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
- reactor-extra-retry
- 聊聊reactor extra的retry
- RxJava's repeatWhen and retryWhen, explained
猜你喜欢
- 2024-09-25 屡败屡战RETRY第六关关卡攻略 屡屡败屡战的意思
- 2024-09-25 基于redis实现的分布式队列 基于 redis 实现分布式锁是?
- 2024-09-25 .NET 使用 mysql 时 EnableRetryOnFailure() 函数的作用及注意事项
- 2024-09-25 新连载漫画大作导视(十月篇) 十日十月漫画作家
- 2024-09-25 基于guava的重试组件Guava-Retryer
- 2024-09-25 我是怎样得到AO3内容的 我是怎样得到ao3内容的英文
- 2024-09-25 Spring Boot 中使用 spring-retry 轻松解决重试
- 2024-09-25 Java重试利器之Guava-Retryer retry java
- 2024-09-25 springCloud负载均衡机制 springcloud负载均衡策略有哪些
- 2024-09-25 LabVIEW调用DLL中一、二级指针参数及打包exe运行异常的解决办法
你 发表评论:
欢迎- 05-1613步震撼淘宝大促闪光裂纹破墙立体字PS制作教程
- 05-16AI教程 | 绘制扁平的萌萌哒图标
- 05-160基础学平面设计所需了解的基础常识汇总
- 05-16自学平面设计需要多长时间?十六年职业设计总监告诉你
- 05-16平面设计都要学习哪些内容?
- 05-16李涛PS教程 高手之路PS教程 合成教程 —制作一个小星球
- 05-16Illustrator实例教程:制作炫酷的漩涡效果
- 05-16Illustrator实例教程:利用混合工具制作一朵炫酷的花
- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)