摘要:還有就是重試次數(shù)如果太多的話會導(dǎo)致請求量加倍,給后端造成更大的壓力,設(shè)置合理的重試機制才是最關(guān)鍵的。今天我們來簡單的了解下中的重試機制和使用。使用講解是對請求重試提供的一個。
前言
重試,我相信大家并不陌生。在我們調(diào)用Http接口的時候,總會因為某種原因調(diào)用失敗,這個時候我們可以通過重試的方式,來重新請求接口。
生活中這樣的事例很多,比如打電話,對方正在通話中啊,信號不好啊等等原因,你總會打不通,當(dāng)你第一次沒打通之后,你會打第二次,第三次...第四次就通了。
重試也要注意應(yīng)用場景,讀數(shù)據(jù)的接口比較適合重試的場景,寫數(shù)據(jù)的接口就需要注意接口的冪等性了。還有就是重試次數(shù)如果太多的話會導(dǎo)致請求量加倍,給后端造成更大的壓力,設(shè)置合理的重試機制才是最關(guān)鍵的。
今天我們來簡單的了解下Spring Cloud Gateway中的重試機制和使用。
使用講解RetryGatewayFilter是Spring Cloud Gateway對請求重試提供的一個GatewayFilter Factory。
配置方式:
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.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory.RetryConfig:
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); // ..... }
retries:重試次數(shù),默認(rèn)值是3次
series:狀態(tài)碼配置(分段),符合的某段狀態(tài)碼才會進行重試邏輯,默認(rèn)值是SERVER_ERROR,值是5,也就是5XX(5開頭的狀態(tài)碼),共有5個值:
public enum Series { INFORMATIONAL(1), SUCCESSFUL(2), REDIRECTION(3), CLIENT_ERROR(4), SERVER_ERROR(5); }
statuses:狀態(tài)碼配置,和series不同的是這邊是具體狀態(tài)碼的配置,取值請參考:org.springframework.http.HttpStatus
methods:指定哪些方法的請求需要進行重試邏輯,默認(rèn)值是GET方法,取值如下:
public enum HttpMethod { GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; }
exceptions:指定哪些異常需要進行重試邏輯,默認(rèn)值是java.io.IOException
代碼測試就寫個接口,在接口中記錄請求次數(shù),然后拋出一個異常模擬500,通過網(wǎng)關(guān)訪問這個接口,如果你配置了重試次數(shù)是3,那么接口中會輸出4次結(jié)果才是對的,證明重試生效了。
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小區(qū)"); }
更多Spring Cloud代碼盡在:https://github.com/yinjihuan/...
源碼欣賞@Override public GatewayFilter apply(RetryConfig retryConfig) { // 驗證重試配置格式是否正確 retryConfig.validate(); Repeat歡迎加入我的知識星球,一起交流技術(shù),免費學(xué)習(xí)猿天地的課程(http://cxytiandi.com/course)statusCodeRepeat = null; if (!retryConfig.getStatuses().isEmpty() || !retryConfig.getSeries().isEmpty()) { Predicate > repeatPredicate = context -> { ServerWebExchange exchange = context.applicationContext(); // 判斷重試次數(shù)是否已經(jīng)達到了配置的最大值 if (exceedsMaxIterations(exchange, retryConfig)) { return false; } // 獲取響應(yīng)的狀態(tài)碼 HttpStatus statusCode = exchange.getResponse().getStatusCode(); // 獲取請求方法類型 HttpMethod httpMethod = exchange.getRequest().getMethod(); // 判斷響應(yīng)狀態(tài)碼是否在配置中存在 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) -> { // 獲取已經(jīng)重試的次數(shù),默認(rèn)值為-1 int iteration = exchange.getAttributeOrDefault(RETRY_ITERATION_KEY, -1); // 增加重試次數(shù) 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); }; }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73649.html
摘要:歡迎訪問我的歡迎訪問我的內(nèi)容所有原創(chuàng)文章分類匯總及配套源碼,涉及等本篇概覽本篇概覽作為實戰(zhàn)系列的第五篇,是時候了解過濾器的作用了,本篇咱們一起來了解內(nèi)置好的過濾器,真是種類繁多功能強大過濾器顧名思義,就是在請求頭部添加指定的內(nèi)容帶有的完整配歡迎訪問我的GitHubhttps://github.com/zq2599/blog_demos內(nèi)容:所有原創(chuàng)文章分類匯總及配套源碼,涉及Java、Doc...
摘要:將請求封裝成將請求封裝成的接口定義是但是最外層傳進來的參數(shù)是和,需要將他們封裝成,這個工作就是在中做的。其實主要任務(wù)就是將各種參數(shù)封裝成除了和本次請求相關(guān)的和,還有會話管理器,編碼解碼器配置,國際化配置還有用于擴展。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent接下來,將進入我們升級之路的又一大模塊,即網(wǎng)關(guān)模塊。網(wǎng)關(guān)模塊我們廢棄了...
摘要:本文重點介紹一下基于實現(xiàn)服務(wù)發(fā)現(xiàn)。使用方式下面我們開始的使用添加和的依賴添加注解開啟服務(wù)發(fā)現(xiàn),注解支持客戶端。同樣子,他可以使用默認(rèn)的也可以使用或者修改配置文件服務(wù)名字服務(wù)無端口會隨機選擇一個服務(wù)集群名字注冊中心地址,完成。 springcloud-feign實現(xiàn)服務(wù)發(fā)現(xiàn) 上一篇介紹了nacos實現(xiàn)配置和注冊中心,在微服務(wù)中只有配置和注冊中心遠(yuǎn)遠(yuǎn)不夠,還需要有服務(wù)發(fā)現(xiàn)。本文重點介紹一...
摘要:常見的限流方式,比如適用線程池隔離,超過線程池的負(fù)載,走熔斷的邏輯。在令牌桶算法中,存在一個桶,用來存放固定數(shù)量的令牌。,令牌桶每秒填充平均速率。 轉(zhuǎn)載請標(biāo)明出處: https://www.fangzhipeng.com本文出自方志朋的博客 在高并發(fā)的系統(tǒng)中,往往需要在系統(tǒng)中做限流,一方面是為了防止大量的請求使服務(wù)器過載,導(dǎo)致服務(wù)不可用,另一方面是為了防止網(wǎng)絡(luò)攻擊。 常見的限流方式,...
摘要:英文意思就是說提供一個回退機制當(dāng)路由后面的服務(wù)發(fā)生故障時。注意注解能注冊到服務(wù)上,是因為該注解包含了客戶端的注解,該是一個復(fù)合注解。地址可以查看該微服務(wù)網(wǎng)關(guān)代理了多少微服務(wù)的。 SpringCloud(第 025 篇)Zuul 路由后面的微服務(wù)掛了后,Zuul 提供了一種回退機制來應(yīng)對熔斷處理 - 一、大致介紹 1、在一些不穩(wěn)定因素導(dǎo)致路由后面的微服務(wù)宕機或者無響應(yīng)時,zuul 就會累...
閱讀 2676·2023-04-25 18:10
閱讀 1617·2019-08-30 15:53
閱讀 2811·2019-08-30 13:10
閱讀 3228·2019-08-29 18:40
閱讀 1134·2019-08-23 18:31
閱讀 1209·2019-08-23 16:49
閱讀 3408·2019-08-23 16:07
閱讀 883·2019-08-23 15:27