SpringCloudGateway基於Sentinel的限流


SpringCloudGateway基於Sentinel的限流

 

Sentinel 支持對 Spring Cloud Gateway、Zuul 等主流的 API Gateway 進行限流。

 

 Sentinel介紹:

從 1.6.0 版本開始,Sentinel 提供了 Spring Cloud Gateway 的適配模塊,可以提供兩種資源維度的限流:    
     *  route 維度:即在 Spring 配置文件中配置的路由條目,資源名為對應的 routeId
     *  自定義 API 維度:用戶可以利用 Sentinel 提供的 API 來自定義一些 API 分組
 
Sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模塊,此模塊中包含網關限流的規則自定義 API 的實體和管理邏輯:
     *  GatewayFlowRule :網關限流規則,針對 API Gateway 的場景定制的限流規則,可以針對不同
         route 或自定義的 API 分組進行限流,支持針對請求中的參數、Header、來源 IP 等進行定制化的
         限流。
     *  ApiDefinition :用戶自定義的 API 定義分組,可以看做是一些 URL 匹配的組合。比如我們可以
        定義一個 API 叫 my_api ,請求 path 模式為 /foo/** 和 /baz/** 的都歸到 my_api 這個 API
        分組下面。限流的時候可以針對這個自定義的 API 分組維度進行限流。

 

 

 

(1)環境搭建 

導入Sentinel 的響應依賴 
<!-- sentinel限流依賴 -->
<dependency>
   <groupId>com.alibaba.csp</groupId>
   <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
   <version>1.7.2</version>
</dependency>

 

(2)編寫配置類 

package com.kerry.gateway.filter;

@Configuration
public class GatewayConfiguration {

    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    /**
     * 配置限流的異常處理器:SentinelGatewayBlockExceptionHandler
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        return new SentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
    }
    /**
     * 配置限流過濾器
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
    /**
     * 配置初始化的限流參數
     */
    @PostConstruct
    public void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
//        rules.add( new GatewayFlowRule("category-service") //資源名稱    //普通全局限流
//                        .setCount(1) // 限流閾值
//                        .setIntervalSec(1) // 統計時間窗口,單位是秒,默認是 1 秒
//        );

        //http://localhost:8001/admin/category/demo.do/1?id=1  當鏈接帶有參數id時,會匹配到限流中
        //http://localhost:8001/admin/category/demo.do/1   如果沒有帶參數id時,不會被匹配進限流中。
//        rules.add(new GatewayFlowRule("category-service") //參數限流
//                .setCount(1)
//                .setIntervalSec(1)
//                .setParamItem(new GatewayParamFlowItem()
//                    .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM).setFieldName("id")
//                )
//        );

        //上面的話是直接對資源進行限流

        //下面是通過自定義api分組進行限流 其里面的資源都在下面進行設置好了對應的匹配路徑.
        rules.add(new GatewayFlowRule("category_api").setCount(1).setIntervalSec(1));
        rules.add(new GatewayFlowRule("headline_api").setCount(1).setIntervalSec(1));
        GatewayRuleManager.loadRules(rules);
    }

    // 自定義API分組
    @PostConstruct
    private void initCustomizedApis() {
        Set<ApiDefinition> definitions = new HashSet<>();

        ApiDefinition api1 = new ApiDefinition("category_api")
        .setPredicateItems(new HashSet<ApiPredicateItem>() {{
            //以/product-service/product 開頭的請求
            add(new ApiPathPredicateItem().setPattern("/admin/category/**").
            setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
        }});

        ApiDefinition api2 = new ApiDefinition("headline_api")
        .setPredicateItems(new HashSet<ApiPredicateItem>() {{
            ///order-service/order 完成的url路徑匹配
            //add(new ApiPathPredicateItem().setPattern("/order-service/order"));
            //add(new ApiPathPredicateItem().setPattern("/order/buy"));
            add(new ApiPathPredicateItem().setPattern("/admin/headline/**").
            setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
        }});
        definitions.add(api1);
        definitions.add(api2);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

    //自定義異常提示
    @PostConstruct
    public void initBlockHandlers() {
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map map = new HashMap<>();
                map.put("code", 001);
                map.put("message", "對不起,接口限流了");
                return ServerResponse.status(HttpStatus.OK).//狀態碼200
                        contentType(MediaType.APPLICATION_JSON_UTF8).//application/json;charset=UTF-8
                        body(BodyInserters.fromObject(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}

(3)網關配置 

server: port: 8001 spring: application: name: server-gateway #服務名稱 cloud: gateway: routes: - id: category-service uri: lb://service-category predicates: - Path=/category/**,/admin/category/**   filters: #限流功能 - RewritePath=/admin/category/(?<segment>.*), /admin/category/$\{segment} - id: headline-service uri: lb://service-headline predicates: - Path=/headline/**,/admin/headline/** eureka: client: service-url: defaultZone: http://127.0.0.1:8000/eureka registry-fetch-interval-seconds: 5 # 獲取服務列表的周期:5s instance: prefer-ip-address: true #使用ip注冊 ip-address: 127.0.0.1

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM