天天看點

zuul網關_SpringCloud學習筆記——舊服務網關Zuul服務限流服務限流

zuul網關_SpringCloud學習筆記——舊服務網關Zuul服務限流服務限流

服務限流

服務網關的一個重要功能即服務限流。在Zuul中雖然可以通過前置類型過濾器對有效請求和無效請求(參數有效性,合法性)進行校驗,将無效請求隔離在服務網關之外(傳回錯誤提示資訊、異常資訊)。但有的時候某一個時間點内突發有效請求量很大,超過了系統可承受的範圍,此時可以依靠服務限流算法,限制該時間點内通過的請求數,保證系統可用,避免出現服務雪崩效應。

此時可以通過Spring Cloud提供的Resilience4j限速器(RateLimiter)進行限速,也可以使用spring-cloud-zuul-ratelimit包。

項目依賴

<dependency>            <groupId>io.github.resilience4jgroupId>            <artifactId>resilience4j-spring-boot2artifactId>            <version>0.13.2version>        dependency>                <dependency>            <groupId>com.marcosbarbero.cloudgroupId>            <artifactId>spring-cloud-zuul-ratelimitartifactId>            <version>2.2.2.RELEASEversion>        dependency>
           

使用Resilience4j限流

限流配置

#resilience4j限流配置resilience4j.ratelimiter.limiters.user-service.limit-for-period=3resilience4j.ratelimiter.limiters.user-service.limit-refresh-period-in-millis=5000resilience4j.ratelimiter.limiters.user-service.timeout-in-millis=10
           

上述配置中,resilience4j.ratelimiter.limiters.user-service.limit-for-period配置時間戳内的請求數(預設為50),limit-refresh-period-in-millis配置時間戳(機關毫秒,預設500),timeout-in-millis配置逾時時間。user-service可以替換為其他有意義的名稱。

限流過濾器

@Componentpublic class Resilience4jRateLimiterFilter extends ZuulFilter {    //Resilience4j限速器注冊機    @Autowired    private RateLimiterRegistry rateLimiterRegistry;    /**     * 傳回過濾器類型     * @return 前置類型過濾器     */    @Override    public String filterType() {        return FilterConstants.PRE_TYPE;    }    /**     * 傳回過濾器執行順序      * @return     */    @Override    public int filterOrder() {        return FilterConstants.PRE_DECORATION_FILTER_ORDER+5;    }    /**     * 傳回過濾器是否執行攔截操作     * @return 請求路徑是否為/user/開頭     */    @Override    public boolean shouldFilter() {        RequestContext requestContext=RequestContext.getCurrentContext();        String uri=requestContext.getRequest().getRequestURI();        return uri.startsWith("/user/");    }    /**     * 過濾器具體執行業務邏輯     * @return     * @throws ZuulException     */    @Override    public Object run() throws ZuulException {        //擷取Resilience4j限速器(key與配置檔案的Key名稱一緻)        RateLimiter rateLimiter=rateLimiterRegistry.rateLimiter("user-service");        //限速器執行邏輯        Callable callResult=()->new ResultMessage(true,"執行成功");        //綁定限速器        Callable callResult2=RateLimiter.decorateCallable(rateLimiter,callResult);        //嘗試擷取執行結果        Try resultMessageTry=Try.of(()->callResult2.call()).recover(ex->new ResultMessage(false,"超出限定流量,執行降級操作"));        ResultMessage resultMessage=resultMessageTry.get();      //執行結果傳回true,說明在限流範圍内,限流操作成功,繼續執行後續的自定義過濾器        if(resultMessage.isSuccess())        {            return null;        }        //超過限流範圍處理        RequestContext requestContext=RequestContext.getCurrentContext();        requestContext.setSendZuulResponse(false);//不在路由到下一個執行順序的過濾器,直接傳回失敗        requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());//設定響應狀态碼(值為429)        requestContext.getResponse().setContentType(MediaType.APPLICATION_JSON_VALUE);//設定響應類型(APPLICATION_JSON_UTF8_VALUE已廢棄)        ObjectMapper responseMapper=new ObjectMapper();        String responseBody=null;        try {            responseBody=responseMapper.writeValueAsString(resultMessage);//将執行結果轉換為字元串并輸出        }     catch (Exception e)     {         e.printStackTrace();     }        requestContext.setResponseBody(responseBody);        return null;    }}
           

在開發Zuul過濾器的過程中,需要熟悉Zuul過濾器類型及Zuul内置過濾器執行順序。本例中,限流過濾器應該在過濾有效請求(請求參數有效)後執行,故過濾器執行順序為前置(pre)過濾器PreDecorationFilter後路由(route)過濾器前(PreDecorationFilter用于處理請求上下文,SimpleHostRoutingFilter用于具體的URL請求轉發)。

zuul網關_SpringCloud學習筆記——舊服務網關Zuul服務限流服務限流

我們将Resilience4jRateLimiterFilter(Resilience4j限速過濾器)聲明為元件(@Component),在入口程式中被掃描發現并裝配;注入限速注冊機(RateLimiterRegistry),通過限速注冊機擷取具體的Resilience4j限速器執行個體(rateLimiterRegistry.rateLimiter(key));通過RateLimiter.decorateCallable方法(參數為Resilience4j執行個體,限速器業務邏輯);在嘗試擷取執行結果的過程中發生異常(限流操作超出限制範圍),通過recover方法實作服務降級相關操作(傳回緩存結果、服務降級資訊、異常),提供更好的使用者體驗;未超過服務限流範圍執行後續的過濾器操作,超過服務限流範圍則設定響應資訊給服務調用方展現。

Spring-cloud-zuul-ratelimit限流

為了防止微服務系統中的服務調用接口被惡意頻繁請求調用,需要在服務網關層進行服務限流對服務調用接口安全性進行保護。使用spring-cloud-zuul-ratelimit可以在Zuul的基礎上實作服務網關限流相關功能。

限流方式

限流方式 限流描述
Authenticated User(認證使用者) 使用已經認證的使用者名或'anonymous'
Request Origin(原始請求) 使用使用者的原始請求
URL 使用上遊請求的位址
Global configuration per service(全局配置) 針對每個服務的全局配置,無需指定限流方式

配置詳解

#spring-cloud-zuul-ratelimit配置(全局配置)#是否開啟限速配置(boolean,預設false)zuul.ratelimit.enabled=true #使用Redis緩存對應的度量資料zuul.ratelimit.repository=redis#是否開啟代理服務(boolean,預設false)zuul.ratelimit.behind-proxy=true#是否添加響應報頭(boolean,預設false)zuul.ratelimit.add-response-header=true#每個重新整理時間視窗對應的請求數量限制zuul.ratelimit.default-policy.limit=10#每個重新整理時間視窗對應的請求時間限制zuul.ratelimit.default-policy.quota=1000#重新整理時間視窗時間(預設60,機關秒)zuul.ratelimit.default-policy.refresh-interval=60#全局限流方式(可選,user,origin,url)zuul.ratelimit.default-policy.type=user#spring-cloud-zuul-ratelimit配置(服務執行個體配置)#限制使用者微服務執行個體(user-service)重新整理時間視窗對應的請求數量限制zuul.ratelimit.user-service.limit=5#限制使用者微服務執行個體(user-service)重新整理時間視窗對應的請求時間限制zuul.ratelimit.user-service.quota=100#限制使用者微服務執行個體(user-service)限流方式zuul.ratelimit.user-service.type=origin
           

繼續閱讀