微服务实战:Gateway 服务网关限流

介绍

网关是所有请求的公共入口,因此可以在网关处对请求进行限流,而且限流的方式很多,本章我们来采用 sentinel 组件实现网关限流

Sentinel 支持对 SpringCloud Gateway、Zuul等主流网关进行限流。

微服务实战:Gateway 服务网关限流

Sentinel 提供了 SpringCloud Gateway 的适配模块,Sentinel 提供了两种资源限流方式。


  • route:在 Spring 配置文件中配置的路由条目,资源名对应的 routeld;

  • 自定义API:用户可以利用Sentinel提供的API 来自定义API分组。


一、代码示例

1.route限流

pom.xml文件导入依赖

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

编写配置类

Sentinel的Gateway限流是通过 Filter来实现的 ,使用的时候只需要注入对应的 SentinelGatewayFilter实例以及 SentinelGatewayBlockExceptionHandler实例即可。

@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(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    //配置初始化的限流参数
    @PostConstruct
    public void initGatewayRules() {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("shop-product")//资源名称,对应路由id
                        .setCount(1)//限流阀值
                        .setIntervalSec(1)//统计时间窗口,单位是秒,默认是1秒
        );
        GatewayRuleManager.loadRules(rules);
    }


    //配置限流异常处理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        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", "接口被限流了");
                return ServerResponse
                        .status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                        .body(BodyInserters.fromObject(map));
            }
        } ;
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}

  • resource:
    资源名称,它可以是网关中定义的路由(route)名称,或者是用户在Sentinel中自定义的API分组名称。这个属性用于指定限流规则使用的具体资源。

  • esourceMode:
    资源模型,用于指明限流规则是应用于API Gateway的路由(RESOURCE_MODE_ROUTE_ID)还是用户在Sentinel中定义的API分组(RESOURCE_MODE_CUSTOM_API_NAME)。默认值是路由模式。

  • rade:
    限流指标维度,与限流规则的grade字段相同,用于指定限流的具体标准或条件。

  • ount
    限流阈值,表示在指定时间窗口内允许通过的最大请求数。

  • ntervalSec:
    统计时间窗口,单位是秒,用于计算限流阈值的时间范围。默认值为1秒。

  • ontrolBehavior:


    流量整形的控制效果,与限流规则的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和matchStrategy:

    这两个字段为后续可能实现的参数匹配特性预留,当前尚未实现。


  • 测试:

    在一秒钟内多次访问

    http://localhost:7000/product/product/1?token=1232

    就可以看到限流规则起作用了


    微服务实战:Gateway 服务网关限流

    2.自定义API分组:

    可以自定义一个API分组来实现限流(自定义API分组是一个细粒度的限流规则)

    //配置初始化的限流参数
    @PostConstruct
    public void initGatewayRules()
    {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("shop_product_api").setCount(1).setIntervalSec(1));
        rules.add(new GatewayFlowRule("shop_order_api").setCount(1).setIntervalSec(1));
        GatewayRuleManager.loadRules(rules);
    }

    //自定义API分组
    @PostConstruct
    private void initCustomizedApis()
    {
        Set<ApiDefinition> definitions = new HashSet<>();
        //定义小组1
        ApiDefinition api1 = new ApiDefinition("shop_product_api")
                .setPredicateItems(new HashSet<ApiPredicateItem>(){{
                    //以/product/product/api1开头的请求
                    add(new ApiPathPredicateItem().setPattern("/product/product/**")
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                }});
        //定义小组2
        ApiDefinition api2 = new ApiDefinition("shop_order_api")
                .setPredicateItems(new HashSet<ApiPredicateItem>(){{
                    //完全匹配/order/order2/message
                    add(new ApiPathPredicateItem().setPattern("/order/order2/message"));
                }});
        definitions.add(api1);
        definitions.add(api2);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }


    在一秒钟内多次访问

    http://localhost:7000/product/product/1?token=1232

    也可以看到限流启作用了。


    微服务实战:Gateway 服务网关限流






原文始发于微信公众号(Java技术前沿):微服务实战:Gateway 服务网关限流

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/299660.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!