Spring Cloud Gateway重试机制原理解析_java
Spring Cloud Gateway重试机制原理解析_java
重试,我相信大家并不陌生。在我们调用Http接口的时候,总会因为某种原因调用失败java中spring原理,这个时候我们可以通过重试的方式Spring Cloud Gateway重试机制原理解析_java,来重新请求接口。
生活中这样的事例很多,比如打电话,对方正在通话中啊,信号不好啊等等原因java中spring原理,你总会打不通,当你第一次没打通之后,你会打第二次Spring Cloud Gateway重试机制原理解析_java,第三次…第四次就通了。
重试也要注意应用场景,读数据的接口比较适合重试的场景,写数据的接口就需要注意接口的幂等性了。还有就是重试次数如果太多的话会导致请求量加倍,给后端造成更大的压力,设置合理的重试机制才是最关键的。
今天我们来简单的了解下 Cloud 中的重试机制和使用。
使用讲解
是 Cloud 对请求重试提供的一个 。
配置方式:
spring: cloud: gateway: routes: - id: fsh-house uri: lb://fsh-house predicates: - Path=/house/** filters: - name: Retry args: retries: 3 series: - SERVER_ERROR statuses: - OK methods: - GET - POST exceptions: - java.io.IOException
配置讲解
配置类源码:org..cloud....ctory.:
public static class RetryConfig { private int retries = 3; private Listseries = toList(Series.SERVER_ERROR); private List statuses = new ArrayList<>(); private List methods = toList(HttpMethod.GET); private List > exceptions = toList(IOException.class); // ..... }
:重试次数,默认值是3次
:状态码配置(分段)java中spring原理,符合的某段状态码才会进行重试逻辑,默认值是,值是5,也就是5XX(5开头的状态码),共有5个值:
public enum Series { INFORMATIONAL(1), SUCCESSFUL(2), REDIRECTION(3), CLIENT_ERROR(4), SERVER_ERROR(5); }
:状态码配置,和不同的是这边是具体状态码的配置,取值请参考:org..http.
:指定哪些方法的请求需要进行重试逻辑,默认值是GET方法,取值如下:
public enum HttpMethod { GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; }
:指定哪些异常需要进行重试逻辑,默认值是java.io.
代码测试
就写个接口,在接口中记录请求次数,然后抛出一个异常模拟500,通过网关访问这个接口,如果你配置了重试次数是3,那么接口中会输出4次结果才是对的,证明重试生效了。
AtomicInteger ac = new AtomicInteger(); @GetMapping("/data") public HouseInfo getData(@RequestParam("name") String name) { if (StringUtils.isBlank(name)) { throw new RuntimeException("error"); } System.err.println(ac.addAndGet(1)); return new HouseInfo(1L, "上海", "虹口", "XX小区"); }
源码欣赏
@Override public GatewayFilter apply(RetryConfig retryConfig) { // 验证重试配置格式是否正确 retryConfig.validate(); RepeatstatusCodeRepeat = null; if (!retryConfig.getStatuses().isEmpty() || !retryConfig.getSeries().isEmpty()) { Predicate > repeatPredicate = 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; }; statusCodeRepeat = Repeat.onlyIf(repeatPredicate) .doOnRepeat(context -> reset(context.applicationContext())); } //TODO: support timeout, backoff, jitter, etc... in Builder Retry exceptionRetry = null; if (!retryConfig.getExceptions().isEmpty()) { Predicate > 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; }; // 使用reactor extra的retry组件 exceptionRetry = Retry.onlyIf(retryContextPredicate) .doOnRetry(context -> reset(context.applicationContext())) .retryMax(retryConfig.getRetries()); } return apply(statusCodeRepeat, exceptionRetry); } public boolean exceedsMaxIterations(ServerWebExchange exchange, RetryConfig retryConfig) { Integer iteration = exchange.getAttribute(RETRY_ITERATION_KEY); //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); } public GatewayFilter apply(Repeat repeat, Retry retry) { return (exchange, chain) -> { if (log.isTraceEnabled()) { log.trace("Entering retry-filter"); } // chain.filter returns a Mono Publisher publisher = chain.filter(exchange) //.log("retry-filter", Level.INFO) .doOnSuccessOrError((aVoid, throwable) -> { // 获取已经重试的次数,默认值为-1 int iteration = exchange.getAttributeOrDefault(RETRY_ITERATION_KEY, -1); // 增加重试次数 exchange.getAttributes().put(RETRY_ITERATION_KEY, iteration + 1); }); if (retry != null) { // retryWhen returns a Mono // retry needs to go before repeat publisher = ((Mono )publisher).retryWhen(retry.withApplicationContext(exchange)); } if (repeat != null) { // repeatWhen returns a Flux // so this needs to be last and the variable a Publisher publisher = ((Mono )publisher).repeatWhen(repeat.withApplicationContext(exchange)); } return Mono.fromDirect(publisher); }; }
推荐阅读:vue ajax 拦截原理与实现方法示例_vue.jsVUE 实现动态给对象增加属性,并触发视图更新操作示例_vue.服务器修改远程桌面默认端口过程图示_其它相关flask框架配置mysql数据库操作详解详解no input file 三种解决方法_php实例统一异常处理实例代码 实现简短小音效基于制作词云图实现栈和队列的简单操作方法示例调用函数、类和文件操作简单实例总结 命令使用详解实现将一维数组按标准长度分隔为二维数组从0开始学习大数据之java spark编程入门与项目实践使用播放短音效算法最浅显理解(小白教程)_C 语言
热门内容:包/库安装,解决: DLL load while 测试GPU是否可用和cudnn检测是否可用 ::
2
系统找不到指定的文件excel怎么把重复项合并? excel将相同名字的数据合并在一起的教程办公软件_软件教程怎么重启服务的命令? 服务启动与停止命令的教程系列_操作系统win11蜘蛛纸牌在哪 win11玩蜘蛛纸牌游戏的方法系列_操作系统如何用ps调整贴图明暗色差的颜色? ps中调整色彩明暗度的的技巧教程win10开机10秒倒计时怎么取消? Win10取消开机倒计时的三种方法系列_操作系统电脑C盘拒绝访问或打不开怎么办? win11/win10 C盘决绝访问的多种解决办法系列_操作系统WPS如何并排比较两个文档 WPS并排比较两个文档的方法_金山WPS_办公软件_软件教程WPS打印时如何添加装订线 WPS打印时添加装订线的方法_金山WPS_办公软件_软件教程怎么关闭/edge浏览器打开外部应用程序的弹窗 禁止广告弹窗的技巧_浏览下载_软件教程WPS表格筛选后如何恢复原本的所有数据 Excel还原筛选的数据的方法_金山WPS_办公软件_软件教程win10搜索不到指定内容怎么办? Win10搜索文件功能找不到文件的多种解决办法系列_操作系统Win11更新失败资源管理器崩溃无限重启怎么解决?系列_操作系统WPS饼图如何设置为分离性饼图 WPS饼图设置为分离性饼图的方法_金山WPS_办公软件_软件教程wps表格无法拖动怎么回事? WPS Excel单元格无法拖拽移动的解决方法_金山WPS_办公软件_软件教程WPS幻灯片中如何添加创意图形 WPS幻灯片中添加创意图形的方法_金山WPS_办公软件_软件教程Win11系统保护在哪? Win11关闭保护的技巧系列_操作系统WPS表格如何设置四舍五入取整 WPS表格设置数字四舍五入取整方法_金山WPS_办公软件_软件教程
- 随机文章
- 热门文章
- 热评文章