架构

微服务 9: 集成Sentinel网关服务 (限流功能)(文末有

2021-04-13  本文已影响0人  _River_
文章知识来源主要来源于:赵俊夫先生的博客  以下为原文链接
https://blog.csdn.net/u011177064/category_9572944.html
1:什么是服务限流
我们后端的接口调用频次(QPS/TPS)动辄上百万,甚至达到千万级别,
这对于服务端的承受能力是一个巨大的考验。
那么限流在这个问题中起到什么作用呢?
其实就是对于流量进行有策略的管理和限制。 比如说在一个系统中,有订单查询服务,商品查询服务,积分查询等,
如果一个系统能支持的QPS(每秒查询次数)是100,那么这100该如何如何分配就是限流功能所考虑的事情。

根据这些服务的重要性,我们可能会把商品查询服务的QPS设置的比较高,
因为这类用户查询到商品是有购买意向的,而订单查询、积分查询啥的

在用户访问量过大时,我们就能尽量保证有购买意向的用户正常使用系统。
2:什么是Sentinel
在SpringCloud GateWay服务网关中集成Sentinel来实现服务的限流功能。
主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
3:Pom配置
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
4: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:参数限流配置。
    若不提供,则代表不针对参数进行限流,该网关规则将会被转换成普通流控规则;
    否则会转换成热点规则。
    其中的字段:
    1:parseStrategy:从请求中提取参数的策略,目前支持提取来源 (四种模式)
        1:IP(PARAM_PARSE_STRATEGY_CLIENT_IP)
        2:Host(PARAM_PARSE_STRATEGY_HOST)
        3:任意 Header(PARAM_PARSE_STRATEGY_HEADER)
        4:任意 URL 参数(PARAM_PARSE_STRATEGY_URL_PARAM)

    2: fieldName:若提取策略选择 Header 模式或 URL 参数模式,则需要指定对应的 header 名称或 URL 参数名称。

    3:pattern:参数值的匹配模式,只有匹配该模式的请求属性值会纳入统计和流控;若为空则统计该请求属性的所有值。(1.6.2 版本开始支持)

    4: matchStrategy:参数值的匹配策略支持:
            1:精确匹配(PARAM_MATCH_STRATEGY_EXACT)、
            2:子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)
            3: 正则匹配(PARAM_MATCH_STRATEGY_REGEX)。(1.6.2 版本开始支持)

加载网关规则方式:
    1:用户可以通过 GatewayRuleManager.loadRules(rules) 手动加载网关规则,
    2:通过 GatewayRuleManager.register2Property(property) 注册动态规则源动态推送(推荐方式)
5:注入Sentinel配置
 /**
     * 设置进行限流的Api集合
     */
    private void initCustomizedApis() {
        /*
            ApiDefinition:用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。
            比如我们可以定义一个 API 叫 myGateway,
            请求 path 模式为
            /nacos-provider/loadBanlance/print  默认为准确的         URL_MATCH_STRATEGY_EXACT
             /nacos-provider/loadBanlance/**    如需/**需要设置成    URL_MATCH_STRATEGY_PREFIX
             的都归到 myGateway 这个 API 分组下面。
         */

        //限流的时候可以针对这个自定义的 API 分组维度进行限流。
        Set<ApiDefinition> definitions = new HashSet<>();
        //设置限流路径
        ApiDefinition api = new ApiDefinition("myGateway")
                .setPredicateItems(new HashSet<ApiPredicateItem>() {{
                    add(new ApiPathPredicateItem()
//                            .setPattern("/nacos-provider/loadBanlance/print")
                            .setPattern("/nacos-provider/loadBanlance/**")
                            .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)
                    );
                }});

        definitions.add(api);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }

    /**
     * 设置限流的Api集合的具体限流
     */
    private void initGatewayRules() {
        /*
        GatewayFlowRule:网关限流规则,
        针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,
        支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。
        */
        Set<GatewayFlowRule> rules = new HashSet<>();

        /*设置限流规则
        count: QPS即每秒钟允许的调用次数
        intervalSec: 每隔多少时间统计一次汇总数据,统计时间窗口,单位是秒,默认是 1 秒。
        */
        //针对上面的  自定义ApiDefinition分组进行限流
        rules.add(new GatewayFlowRule("myGateway")
                .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
                .setCount(5)
                .setIntervalSec(1)

        );
        GatewayRuleManager.loadRules(rules);
    }
6:测试 重复请求
方法一:
设置 允许调用次数少点(直接设置成0) 然后在postman不断进行点击请求
方法二:
使用postman进行并发测试

1:设置三个完全一样的请求路径 然后存到集合里面
2:在0秒的延迟(delay)内 开启 10个线程(Interation)  进行对集合进行请求 
3:点击请求 查看结果  发现该路径限制1秒内 只能请求5次
7:自定义异常返回
public class MyBlockRequestHandler implements BlockRequestHandler {

    private static final String DEFAULT_BLOCK_MSG_PREFIX = "Blocked by Sentinel: ";

    @Override
    public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) {
        // 返回http状态码为200
        return ServerResponse.status(200).contentType(MediaType.APPLICATION_JSON_UTF8)
                .body(fromObject(buildErrorResult(ex)));
    }
    
    private ErrorResult buildErrorResult(Throwable ex) {
        return new ErrorResult(200,
                DEFAULT_BLOCK_MSG_PREFIX + ex.getClass().getSimpleName());
    }
    
    private static class ErrorResult {
        private final int code;
        private final String message;

        ErrorResult(int code, String message) {
            this.code = code;
            this.message = message;
        }

        public int getCode() {
            return code;
        }

        public String getMessage() {
            return message;
        }
    }
}
8:限流日志
默认sentinel的限流日志会存放在这里
有兴趣的话可以自己查看  后续会讲到sentinel的可视化日志界面
C:\Users\HSJ\logs\csp

项目连接

请配合项目代码食用效果更佳:
项目地址:
https://github.com/hesuijin/spring-cloud-alibaba-project
Git下载地址:
https://github.com.cnpmjs.org/hesuijin/spring-cloud-alibaba-project.git

在gateway  模块下
上一篇下一篇

猜你喜欢

热点阅读