日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【云原生微服务>SCG网关篇十二】Spring Cloud Gateway集成Sentinel API实现多种限流方式

發布時間:2024/5/8 javascript 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【云原生微服务>SCG网关篇十二】Spring Cloud Gateway集成Sentinel API实现多种限流方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、前言
  • 二、Gateway集成Sentinel API
    • 0、集成Sentinel的核心概念
      • 1)GatewayFlowRule 和 ApiDefinition
      • 2)GatewayFlowRule字段解釋
    • 1、針對Route維度限流
      • 驗證
    • 2、針對API維度限流
      • 驗證
    • 3、自定義限流異常返回值
      • 驗證
  • 三、總結

一、前言

至此微服務網關系列文章已出:

  • 【云原生&微服務>SCG網關篇一】為什么要有網關、生產環境如何選擇網關
  • 云原生&微服務>SCG網關篇二】生產上那些灰度發布方式
  • 【云原生&微服務>SCG網關篇三】Spring Cloud Gateway是什么、詳細使用案例
  • 云原生&微服務>SCG網關篇四】Spring Cloud Gateway內置的11種PredicateFactory如何使用
  • 【云原生&微服務>SCG網關篇五】Spring Cloud Gateway自定義PredicateFactory
  • 【云原生&微服務>SCG網關篇六】Spring Cloud Gateway內置的18種Filter使用姿勢
  • 【云原生&微服務>SCG網關篇七】Spring Cloud Gateway基于內置Filter實現限流、熔斷、重試
  • 【云原生&微服務>SCG網關篇八】Spring Cloud Gateway三種自定義Filter、GlobalFilter的方式
  • 【云原生&微服務>SCG網關篇九】Spring Cloud Gateway集成Nacos詳細案例
  • 【云原生&微服務>SCG網關篇十】Spring Cloud Gateway集成Actuator、Zipkin詳細案例
  • 【云原生&微服務>SCG網關篇十一】Spring Cloud Gateway解決跨域問題
  • 聊了以下問題:

  • 為什么要有網關?網關的作用是什么?
  • 網關的分類?
  • 網關的技術選型?
  • 使用網關時常用的灰度發布方式有哪些?
  • Spring Cloud Gateway是什么?詳細使用案例?
  • Spring Cloud Gateway內置的11種PredicateFactory
  • 如何自定義PredicateFactory?
  • Spring Cloud Gateway內置的18種常用的Filter
  • Spring Cloud Gateway基于內置Filter實現限流、熔斷、重試
  • Spring Cloud Gateway三種自定義Filter、GlobalFilter的方式
  • Spring Cloud Gateway集成Nacos案例
  • Spring Cloud Gateway集成Actuator、Zipkin案例
  • Spring Cloud Gareway如何解決CORS跨域問題
  • 我們已經聊過了Spring Cloud Gateway的一種限流方式:使用內置的Filter(RequestRateLimiterGatewayFilterFactory)結合Redis使用令牌桶算法實現限流;這里我們再聊一下另外一種:Spring Cloud Gateway集成Sentinel實現限流。

    PS:SpringCloud版本信息:

    <properties><spring-boot.version>2.4.2</spring-boot.version><spring-cloud.version>2020.0.1</spring-cloud.version><spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version> </properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><!--整合spring cloud--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!--整合spring cloud alibaba--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies> </dependencyManagement>

    二、Gateway集成Sentinel API

    sentinel服務1.6.0以上的版本可支持整合到網關進行統一流控:

    sentinel提供了兩種資源維度的限流:

    • route維度:在配置文件中配置路由,資源名為對應的 routeId,一般是對某個微服務進行限流;這種維度屬于粗粒度的限流。
    • 自定義API維度:通過Sentinel 提供的API來自定義一些API分組,針對某一類的uri進行匹配限流,可以跨多個微服務;這種維度屬于細粒度的限流。

    gateway整合sentinel默認不支持 URL 粒度限流;因此通過 Spring Cloud Alibaba 接入時,將spring.cloud.sentinel.filter.enabled 配置為 false,以關閉流控控制臺上的 URL 資源視圖。

    gateway整合Sentinel的maven依賴:

    <dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-spring-cloud-gateway-adapter</artifactId><version>1.8.0</version> </dependency>

    0、集成Sentinel的核心概念

    整體集成原理如下:

    1)GatewayFlowRule 和 ApiDefinition

    網關的限流規則GatewayFlowRule:

    • 針對 API Gateway 的場景定制的限流規則,可以針對不同 route 或自定義的 API 分組進行限流,支持針對請求中的參數、Header、來源 IP 等進行定制化的限流;
      用戶自定義的API分組ApiDefinition:
    • ApiDefinition可以看做是一些 URL 匹配的組合;限流的時候可以針對這個自定義的 API 分組進行限流。

    2)GatewayFlowRule字段解釋

    網關限流規則 GatewayFlowRule 的字段如下:

    • resource:資源名稱,可以是網關中的 route 名稱或者用戶自定義的 API 分組名稱。
    • resourceMode:規則是針對 API Gateway 的 route(RESOURCE_MODE_ROUTE_ID)還是用戶在 Sentinel 中定義的 API 分組(RESOURCE_MODE_CUSTOM_API_NAME),默認是 route。
    • grade:限流指標維度,同限流規則的 grade 字段。
    • count:限流閾值
    • intervalSec:統計時間窗口,單位是秒,默認是 1 秒。
    • controlBehavior:流量整形的控制效果,同限流規則的 controlBehavior 字段,目前支持快速失敗和勻速排隊兩種模式,默認是快速失敗。
    • burst:應對突發請求時額外允許的請求數目。
    • maxQueueingTimeoutMs:勻速排隊模式下的最長排隊時間,單位是毫秒,僅在勻速排隊模式下生效。
    • paramItem:參數限流配置。若不提供,則代表不針對參數進行限流,該網關規則將會被轉換成普通流控規則;否則會轉換成熱點規則。其中的字段:
    • parseStrategy:從請求中提取參數的策略,目前支持提取來源 IP(PARAM_PARSE_STRATEGY_CLIENT_IP)、Host(PARAM_PARSE_STRATEGY_HOST)、任意 Header(PARAM_PARSE_STRATEGY_HEADER)和任意 URL 參數(PARAM_PARSE_STRATEGY_URL_PARAM)四種模式。
    • fieldName:若提取策略選擇 Header 模式或 URL 參數模式,則需要指定對應的 header 名稱或 URL 參數名稱。
    • pattern:參數值的匹配模式,只有匹配該模式的請求屬性值會納入統計和流控;若為空則統計該請求屬性的所有值。(1.6.2 版本開始支持)
    • matchStrategy:參數值的匹配策略,目前支持精確匹配(PARAM_MATCH_STRATEGY_EXACT)、子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)和正則匹配(PARAM_MATCH_STRATEGY_REGEX)。(1.6.2 版本開始支持)

    可以通過GatewayRuleManager.loadRules(rules) 手動加載網關規則、 或 通過 GatewayRuleManager.register2Property(property) 注冊規則(推薦方式);

    特別注意:當使用 Spring Cloud Alibaba Sentinel 數據源模塊時,需要注意網關流控規則數據源類型是 gw-flow,若將網關流控規則數據源指定為 flow 則不生效。

    application.yml配置文件:

    spring:application:name: nacos-gatewaycloud:nacos:discovery:server-addr: 106.15.139.143:8848gateway:discovery:locator:# 開啟從注冊中心動態創建路由的功能enabled: true# 是否使用service-id的小寫,默認是大寫lower-case-service-id: trueroutes:- id: gateway-nacos-service-route# 其中配置的lb://表示從注冊中心獲取服務,后面的gateway-nacos-provider表示目標服務在注冊中心上的服務名uri: lb://gateway-nacos-providerpredicates:- Path=/nacos/sentinel/** #被限流filters:- StripPrefix=2# 自定義Sentinel API分組限流- id: red_routeuri: lb://gateway-nacos-providerpredicates:- Path=/red/** #被限流filters:- StripPrefix=1- id: green_routeuri: lb://gateway-nacos-providerpredicates:- Path=/green/** #不被限流filters:- StripPrefix=1

    下面的三個樣例均依賴此application.yml配置文件。

    1、針對Route維度限流

    搞一個ConfigurationClass,在類初始化的最后階段(@PostConstruct標注的方法)實例化一個GatewayFlowRule,并將其添加到GatewayRuleManager中;GatewayFlowRule中指定針對哪個Route限流、限流的規則是什么?

    package com.saint.gateway.sentinel;import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set;import javax.annotation.PostConstruct;import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.web.reactive.result.view.ViewResolver;import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;/*** 針對某個Route限流** @author Saint*/ @Configuration public class GatewayConfiguration {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolvers.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}/*** 注入一個全局限流過濾器SentinelGatewayFilter* Filter的優先級最高*/@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}/*** 注入限流異常處理器* Filter的優先級最高*/@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}/*** 初始化限流規則*/@PostConstructpublic void doInit() {initGatewayRules();}/*** Route維度限流規則*/private void initGatewayRules() {Set<GatewayFlowRule> rules = new HashSet<>();// 這里表示1s僅允許通過一個請求,GatewayFlowRule構造函數中的如參為路由名GatewayFlowRule gatewayFlowRule = new GatewayFlowRule("gateway-nacos-service-route").setCount(1).setIntervalSec(1);rules.add(gatewayFlowRule);GatewayRuleManager.loadRules(rules);} }

    當前案例表示針對routeId為gateway-nacos-service-route的路由做限流:1s僅允許一個請求通過;

    驗證

    當請求被限流時會返回429狀態碼,響應體內容為:

    {"code":429,"message":"Blocked by Sentinel: ParamFlowException"}

    2、針對API維度限流

    自定義API分組限流,將/nacos/sentinel/**和/red/**進行統一分組,并提供name=saint_customized_api,然后在初始化網關限流規則時,針對該name設置限流規則;

    package com.saint.gateway.sentinel;import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set;import javax.annotation.PostConstruct;import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.web.reactive.result.view.ViewResolver;import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem; import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;/*** 自定義API分組限流** @author Saint*/ @Configuration public class GatewayConfiguration1 {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration1(ObjectProvider<List<ViewResolver>> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolvers.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}/*** 注入SentinelGatewayFilter* Filter的優先級最高*/@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}/*** 注入限流異常處理器* Filter的優先級最高*/@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}/*** 初始化限流規則*/@PostConstructpublic void doInit() {initCustomizedApis();initGatewayRules();}/*** 自定義API分組限流,將/nacos/sentinel/**和/red/**進行統一分組,并提供name=saint_customized_api,然后在初始化網關限流規則時,針對該name設置* 限流規則。同時,可以通過setMatchStrategy來設置不同path下的限流參數策略*/private void initCustomizedApis() {Set<ApiDefinition> definitions = new HashSet<>();// 自定義針對API限流的ApiDefinition,apiName可以隨便取,在GatewayFlowRule中填入即可。ApiDefinition apiDefinition = new ApiDefinition("saint_customized_api");// 匹配下面請求路徑的請求將被限流apiDefinition.setPredicateItems(new HashSet<ApiPredicateItem>() {{add(new ApiPathPredicateItem().setPattern("/nacos/sentinel/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));add(new ApiPathPredicateItem().setPattern("/red/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));}});definitions.add(apiDefinition);GatewayApiDefinitionManager.loadApiDefinitions(definitions);}/*** 針對分組name來設置限流規則*/private void initGatewayRules() {// 針對ApiDefinition進行限流GatewayFlowRule rule = new GatewayFlowRule("saint_customized_api").setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME).setCount(1).setIntervalSec(1);Set<GatewayFlowRule> rules = new HashSet<>();rules.add(rule);GatewayRuleManager.loadRules(rules);} }

    驗證

    當我們訪問/nacos/sentinel/**和/red/**路徑時才會被限流,其他路徑均不會。

    3、自定義限流異常返回值

    Sentinel默認的異常處理器是com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler,我們可以根據這個Handler自定義一個WebExceptionHandler實現類。

    1> 自定義WebExceptionHandler實現類:

    package com.saint.gateway.sentinel;import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.util.function.Supplier; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.result.view.ViewResolver; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebExceptionHandler; import reactor.core.publisher.Mono;import java.util.List;/*** 異常處理器*/ public class MySentinelGatewayBlockExceptionHandler implements WebExceptionHandler {private List<ViewResolver> viewResolvers;private List<HttpMessageWriter<?>> messageWriters;private final Supplier<ServerResponse.Context> contextSupplier = () -> {return new ServerResponse.Context() {public List<HttpMessageWriter<?>> messageWriters() {return MySentinelGatewayBlockExceptionHandler.this.messageWriters;}public List<ViewResolver> viewResolvers() {return MySentinelGatewayBlockExceptionHandler.this.viewResolvers;}};};public MySentinelGatewayBlockExceptionHandler(List<ViewResolver> viewResolvers,ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolvers;this.messageWriters = serverCodecConfigurer.getWriters();}/*** 該方法的作用是,將限流的異常信息寫回客戶端*/private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) {ServerHttpResponse serverHttpResponse = exchange.getResponse();serverHttpResponse.getHeaders().add("Content-type", "application/json;charset=UTF-8");byte[] datas = "{"code":999,"msg":"訪問人數太多了,讓我歇歇吧"}".getBytes();DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas);return serverHttpResponse.writeWith(Mono.just(buffer));}public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {if (exchange.getResponse().isCommitted()) {return Mono.error(ex);} else {return !BlockException.isBlockException(ex) ? Mono.error(ex): this.handleBlockedRequest(exchange, ex).flatMap((response) -> this.writeResponse(response, exchange));}}private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) {return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);} }

    2> 將MySentinelGatewayBlockExceptionHandler注入到Spring容器中:

    // 注入自定義的限流異常處理器 @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public MySentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new MySentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); }

    驗證

    接著根據API分組限流的案例進行驗證;

    響應的狀態碼是200,body是我們自定義的body:

    {"code":999,"msg":"訪問人數太多了,讓我歇歇吧"}

    三、總結

    sentinel提供了兩種資源維度的限流:

    • route維度:在配置文件中配置路由,資源名為對應的 routeId,一般是對某個微服務進行限流;這種維度屬于粗粒度的限流。
    • 自定義API維度:通過Sentinel 提供的API來自定義一些API分組,針對某一類的uri進行匹配限流,可以跨多個微服務;這種維度屬于細粒度的限流。

    本文的演示案例基于文章()

    PS:Sentinel整合Nacos配置源:

    spring:cloud: #配置SpringCloudGateway的路由sentinel:transport:dashboard: ip:port #sentinel控制臺的請求地址datasource:ds1:nacos:server-addr: ip:portdata-id: ${spring.application.name}-${spring.profiles.active}-sentinel-gw-flowgroup-id: DEFAULT_GROUPdata-type: json# 流控規則rule-type: gw-flowds2:nacos:server-addr: ip:portdata-id: ${spring.application.name}-${spring.profiles.active}-sentinel-gw-api-groupgroup-id: DEFAULT_GROUPdata-type: json# api類型rule-type: gw-api-groupeager: true #立即加載log:# 日志存放目錄dir: /data/sentinel/gateway

    引入maven依賴:

    <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> </dependency>

    先自我介紹一下,小編13年上師交大畢業,曾經在小公司待過,去過華為OPPO等大廠,18年進入阿里,直到現在。深知大多數初中級java工程師,想要升技能,往往是需要自己摸索成長或是報班學習,但對于培訓機構動則近萬元的學費,著實壓力不小。自己不成體系的自學效率很低又漫長,而且容易碰到天花板技術停止不前。因此我收集了一份《java開發全套學習資料》送給大家,初衷也很簡單,就是希望幫助到想自學又不知道該從何學起的朋友,同時減輕大家的負擔。添加下方名片,即可獲取全套學習資料哦

    總結

    以上是生活随笔為你收集整理的【云原生微服务>SCG网关篇十二】Spring Cloud Gateway集成Sentinel API实现多种限流方式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。