国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring Cloud Gateway重試機制

shery / 1878人閱讀

摘要:還有就是重試次數如果太多的話會導致請求量加倍,給后端造成更大的壓力,設置合理的重試機制才是最關鍵的。今天我們來簡單的了解下中的重試機制和使用。使用講解是對請求重試提供的一個。

前言

重試,我相信大家并不陌生。在我們調用Http接口的時候,總會因為某種原因調用失敗,這個時候我們可以通過重試的方式,來重新請求接口。

生活中這樣的事例很多,比如打電話,對方正在通話中啊,信號不好啊等等原因,你總會打不通,當你第一次沒打通之后,你會打第二次,第三次...第四次就通了。

重試也要注意應用場景,讀數據的接口比較適合重試的場景,寫數據的接口就需要注意接口的冪等性了。還有就是重試次數如果太多的話會導致請求量加倍,給后端造成更大的壓力,設置合理的重試機制才是最關鍵的。

今天我們來簡單的了解下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 List series = toList(Series.SERVER_ERROR);
        
    private List statuses = new ArrayList<>();
        
    private List methods = toList(HttpMethod.GET);

    private List> exceptions = toList(IOException.class);
        
    // .....
}

retries:重試次數,默認值是3次

series:狀態碼配置(分段),符合的某段狀態碼才會進行重試邏輯,默認值是SERVER_ERROR,值是5,也就是5XX(5開頭的狀態碼),共有5個值:

public enum Series {
    INFORMATIONAL(1),
    SUCCESSFUL(2),
    REDIRECTION(3),
    CLIENT_ERROR(4),
    SERVER_ERROR(5);
}

statuses:狀態碼配置,和series不同的是這邊是具體狀態碼的配置,取值請參考:org.springframework.http.HttpStatus

methods:指定哪些方法的請求需要進行重試邏輯,默認值是GET方法,取值如下:

public enum HttpMethod {
    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
}

exceptions:指定哪些異常需要進行重試邏輯,默認值是java.io.IOException

代碼測試

就寫個接口,在接口中記錄請求次數,然后拋出一個異常模擬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小區");
}

更多Spring Cloud代碼盡在:https://github.com/yinjihuan/...

源碼欣賞
    @Override
    public GatewayFilter apply(RetryConfig retryConfig) {
        // 驗證重試配置格式是否正確
        retryConfig.validate();

        Repeat statusCodeRepeat = 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 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);
        };
    }
歡迎加入我的知識星球,一起交流技術,免費學習猿天地的課程(http://cxytiandi.com/course)

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73649.html

相關文章

  • Spring Cloud Gateway實戰之五:內置filter

    摘要:歡迎訪問我的歡迎訪問我的內容所有原創文章分類匯總及配套源碼,涉及等本篇概覽本篇概覽作為實戰系列的第五篇,是時候了解過濾器的作用了,本篇咱們一起來了解內置好的過濾器,真是種類繁多功能強大過濾器顧名思義,就是在請求頭部添加指定的內容帶有的完整配歡迎訪問我的GitHubhttps://github.com/zq2599/blog_demos內容:所有原創文章分類匯總及配套源碼,涉及Java、Doc...

    reclay 評論0 收藏0
  • SpringCloud升級之路2020.0.x版-41. SpringCloudGateway 基本

    摘要:將請求封裝成將請求封裝成的接口定義是但是最外層傳進來的參數是和,需要將他們封裝成,這個工作就是在中做的。其實主要任務就是將各種參數封裝成除了和本次請求相關的和,還有會話管理器,編碼解碼器配置,國際化配置還有用于擴展。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent接下來,將進入我們升級之路的又一大模塊,即網關模塊。網關模塊我們廢棄了...

    不知名網友 評論0 收藏0
  • springcloud-feign實現服務發現

    摘要:本文重點介紹一下基于實現服務發現。使用方式下面我們開始的使用添加和的依賴添加注解開啟服務發現,注解支持客戶端。同樣子,他可以使用默認的也可以使用或者修改配置文件服務名字服務無端口會隨機選擇一個服務集群名字注冊中心地址,完成。 springcloud-feign實現服務發現 上一篇介紹了nacos實現配置和注冊中心,在微服務中只有配置和注冊中心遠遠不夠,還需要有服務發現。本文重點介紹一...

    _DangJin 評論0 收藏0
  • spring cloud gateway 之限流篇

    摘要:常見的限流方式,比如適用線程池隔離,超過線程池的負載,走熔斷的邏輯。在令牌桶算法中,存在一個桶,用來存放固定數量的令牌。,令牌桶每秒填充平均速率。 轉載請標明出處: https://www.fangzhipeng.com本文出自方志朋的博客 在高并發的系統中,往往需要在系統中做限流,一方面是為了防止大量的請求使服務器過載,導致服務不可用,另一方面是為了防止網絡攻擊。 常見的限流方式,...

    joy968 評論0 收藏0
  • SpringCloud(第 025 篇)Zuul 路由后面的微服務掛了后,Zuul 提供了一種回退機

    摘要:英文意思就是說提供一個回退機制當路由后面的服務發生故障時。注意注解能注冊到服務上,是因為該注解包含了客戶端的注解,該是一個復合注解。地址可以查看該微服務網關代理了多少微服務的。 SpringCloud(第 025 篇)Zuul 路由后面的微服務掛了后,Zuul 提供了一種回退機制來應對熔斷處理 - 一、大致介紹 1、在一些不穩定因素導致路由后面的微服務宕機或者無響應時,zuul 就會累...

    Jochen 評論0 收藏0

發表評論

0條評論

shery

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<