当前位置: 首页>后端>正文

springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流


文章目录

  • 前言
  • 第一节 Gateway网关限流
  • 第二节 路由维度的限流
  • 第三节 自定义API分组维度限流


前言

什么是网关限流?
限流有哪些维度?
如何自定义限流规则?

第一节 Gateway网关限流

网关是所有请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,本次采用Sentinel组件实现网关的限流。Sentinel支持对SpringCloud Gateway、 Zuul等主流网关进行限流。

springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流,springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流_spring boot,第1张

从1.6.0版本后,Sentinel提供了SpringCloud Gateway的适配模块,可以提供两种资源维度的限流

  • route维度:在spring配置文件中配置的路由条目,资源名为对应的routeId
  • 自定义API维度:用户可以利用Sentinel提供的API来自定义一些API分组

第二节 路由维度的限流

如何进行路由维度的限流?

  1. 在api-gateway模块里引入依赖
<!--sentinel网关限流-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
        </dependency>
  1. 编写路由维度限流代码
package com.lcz.config;

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.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
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.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 网关限流
 */
@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;
    }



    //初始化一个限流过滤器
    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    //配置初始化的限流参数
    @PostConstruct
    public void doInit() {
        Set<GatewayFlowRule> rules=new HashSet<>();
        rules.add(new GatewayFlowRule("product_route") //product_route 路由的id
                .setCount(1)  //限流阈值
                .setIntervalSec(1)); //统计时间窗口,单位秒
        GatewayRuleManager.loadRules(rules);
    }

    //配置限流的异常处理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    //自定义限流异常页面
    @PostConstruct
    public void initBlockHandlers(){
        BlockRequestHandler blockRequestHandler=new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map map=new HashMap();
                map.put("code",0);
                map.put("message","API网关限流");

                Mono<ServerResponse>  mono=ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject(map));
                return mono;
            }
        };

        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }

}

代码针对的是配置文件的product_route这个路由进行的限流。

springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流,springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流_gateway_02,第2张

  1. 启动网关测试,频繁请求,发现路由product_route被限流了。而请求其它路由则未被限流。

第三节 自定义API分组维度限流

自定义API分组限流是一种更细粒度的限流规则。
如何实现API分组限流?

  1. 只要对上面GatewayConfiguration进行稍作修改
package com.lcz.config;

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.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
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.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 网关限流
 */
@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;
    }

    //初始化一个限流过滤器
    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    //配置初始化的限流参数
    @PostConstruct
    public void doInit() {
        Set<GatewayFlowRule> rules=new HashSet<>();
        /**
         * 针对路由的限流,资源名product_route为路由id
         */
        rules.add(new GatewayFlowRule("product_route") //product_route 路由的id
                .setCount(1)  //限流阈值
                .setIntervalSec(1)); //统计时间窗口,单位秒

        /**
         * 针对api分组的限流,设置了两组限流规则
         */
        rules.add(new GatewayFlowRule("order_api1").setCount(1).setIntervalSec(1));
        rules.add(new GatewayFlowRule("order_api2").setCount(1).setIntervalSec(1));

        GatewayRuleManager.loadRules(rules);
    }

    //配置限流的异常处理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    //自定义限流异常页面
    @PostConstruct
    public void initBlockHandlers(){
        BlockRequestHandler blockRequestHandler=new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map map=new HashMap();
                map.put("code",0);
                map.put("message","API网关限流");

                Mono<ServerResponse>  mono=ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject(map));
                return mono;
            }
        };

        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }

    //自定义API分组
    @PostConstruct
    public void initCustomizedApis(){
        Set<ApiDefinition> definitions=new HashSet<>();
        ApiDefinition api1=new ApiDefinition("order_api1");
        api1.setPredicateItems(new HashSet<ApiPredicateItem>(){
            {
                //可以设置多个匹配规则
                add(new ApiPathPredicateItem().setPattern("/server-order/api1/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                add(new ApiPathPredicateItem().setPattern("/server-order/api3/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
            }
        });
        ApiDefinition api2=new ApiDefinition("order_api2");
        api2.setPredicateItems(new HashSet<ApiPredicateItem>(){
            {
//
                /**
                 * setMatchStrategy设置匹配策略,如果不设置匹配策略,默认就是SentinelGatewayConstants.URL_MATCH_STRATEGY_EXACT,精确匹配,URL链接需相同<br>
                 */
                add(new ApiPathPredicateItem().setPattern("/server-order/api2/demo1"));
//                add(new ApiPathPredicateItem().setPattern("/server-order/api2/demo1").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_EXACT));
            }
        });

        definitions.add(api1);
        definitions.add(api2);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

}

解释一下新增的内容,新增了两组资源的限流规则,资源名为order_api1和order_api2

springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流,springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流_限流_03,第3张

springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流,springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流_限流_04,第4张

  1. 上面我们定义了对/server-order/api1/**和/server-order/api2/demo1的不同限流分组,因为调用的是order这个微服务,所以需要在order模块里面编写测试的demo
@RestController
@Slf4j
public class ApiDemoController {


    @RequestMapping("/api1/demo1")
    public String demo1() {
        return "hello";
    }
    @RequestMapping("/api1/demo2")
    public String demo2() {
        return "hello";
    }
    @RequestMapping("/api2/demo1")
    public String demo3() {
        return "hello";
    }
    @RequestMapping("/api2/demo2")
    public String demo4() {
        return "hello";
    }
}
  1. 启动网关和order模块测试,频繁请求http://127.0.0.1:7000/server-order/api1/demo2,提示被限流。而请求http://127.0.0.1:7000/server-order/api2/demo2 则未被限流,但是请求http://127.0.0.1:7000/server-order/api2/demo1则被限流,因为规则里添加了它。

springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流,springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流_架构_05,第5张

springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流,springcloud gateway 如何屏蔽内部api暴露 springcloud gateway限流_限流_06,第6张



https://www.xamrdz.com/backend/3ew1962946.html

相关文章: