Sentinel在消息网关的实践

Sentinel在消息网关的实践

前言
  1. Sentinel 是面向分布式服务架构的轻量级流量控制框架,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助您保护服务的稳定性。
  2. 想到流量控制我们就知道漏斗,令牌两种限流方式,及google RateLimite的限流组件。
  3. 想到熔断降级,SpringCould Hystrix大家玩微服务都应该知道。实践过没?深入研究过没?学习难度?
  4. 详细对比下Sentinel与Hystrix 特征
对比内容SentinelHystrix
隔离策略信号量隔离线程池隔离/信号量隔离
熔断降级策略基于响应时间或失败比率基于失败比率
实时指标实现滑动窗口滑动窗口(基于 RxJava)
规则配置支持多种数据源支持多种数据源
扩展性多个扩展点插件的形式
基于注解的支持支持支持
限流基于 QPS,支持基于调用关系的限流不支持
流量整形支持慢启动、匀速器模式不支持
系统负载保护支持不支持
控制台开箱即用,可配置规则、查看秒级监控、机器发现等不完善
常见框架的适配Servlet、Spring Cloud、Dubbo、gRPC 等Servlet、Spring Cloud Netflix
学习难度中国人开发,中文文档外国思维
  1. 看完上面的简单介绍,请移步到官方文档 https://github.com/alibaba/Sentinel/wiki/介绍 同浏览一篇,再看下面实践。
场景应用
  1. 对同一个手机号,30秒内发送短信条数不超过10条,采用热点参数限流组件来实现

  2. 热点参数限流 热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

     商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
     用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
    
  3. 代码如下:

        //对第一个参数设置限制
        ParamFlowRule rule = new ParamFlowRule("mobileNo")
                .setParamIdx(0)
                .setCount(5);
// 针对 int 类型的参数 PARAM_B,单独设置限流 QPS 阈值为 10,而不是全局的阈值 5.
//        ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
//                .setClassType(int.class.getName())
//                .setCount(10);
//        rule.setParamFlowItemList(Collections.singletonList(item));

        ParamFlowRuleManager.loadRules(Collections.singletonList(rule));

  1. 设置规则代码,对参数0的每个值的qps不超过5.
 /**
     * Here we prepare different parameters to validate flow control by parameters.
     */
    private static final String[] params = new String[]{
            "13632634458",
            "15982099035",
//            "15982099035",
//            "15982099035",
//            "15140553376",
//            "15982099035",
//            "18292800909",
//            "18608037915",
//            "13547882172",
//            "13547882172",
//            "18581853266",
//            "18581853266",
//            "18581853266",
//            "15982099035",
//            "15982099035",
//            "18628201097",
//            "13826281991",
//            "13659282837",
//            "13680234325",
//            "18628201097",
//            "18628201097",
//            "13826281991",
//            "18581853266",
//            "13659282837",
//            "18581853266",
//            "18628201097",
//            "18581853266",
//            "18581853266",
//            "13680234325",
//            "18581853266",
//            "18581853266",
    };


    @RequestMapping(value = "/getParam")
        @ResponseBody
        //  @SentinelResource(value = "methodA", blockHandler = "exceptionHandler", fallback = "")
        public String getTwoCache(HttpServletRequest request) {
            Entry entry = null;
            try {
                String param = generateParam();
                entry = SphU.entry("mobileNo", EntryType.IN, 1, param);
                // Add pass for parameter.
                log.info("抢购成功:" + param);
            } catch (BlockException e1) {
                log.info("熔断了" + e1.getMessage());
                return "error";
            } catch (Exception e2) {
                // biz exception
            } finally {
                if (entry != null) {
                    entry.exit();
                }
            }

            return "ok";
        }


     private String generateParam() {
            int i = ThreadLocalRandom.current().nextInt(0, params.length);
            return params[i];
        }

  1. 通过sentinel-dashboard可以知道,只启用两个手机号,/getParam的qps应该为10 qps。如图:

broker


  1. 通过图片可以看mobileNo的qps为10.
  2. 遗憾的是规则采用是1秒时间窗口内获取的qps,对于10秒内该请求数量,还是不够完美。可以自己设计。
滑动时间窗口
  1. 熔断降级采用的错误数,错误率,响应时间,限流的qps都是基于滑动时间窗口。
  2. 我们在流水式计算也经常遇到时间窗口这个概念,在报警系统我们也许选择一个窗口时间。背后原理是一致的滑动时间窗口
  3. 滑动时间窗口它有两个属性,一个是Window size,一个是Advance interval。Window size指定了窗口的大小,也即每次计算最小数据集的大小。而Advance interval定义输出的时间间隔。一个典型的应用场景是,每隔5秒钟输出一次过去1个小时内网站的PV或者UV

broker


  1. 举例:监控系统定义最小时间WindowSize=30s,意思把单位时间30s数据值进行聚合。Advancenterval:为我们获取3分内的时间窗口数据算qps。滑动时间窗口意思已当时间点向前找Advancenterval时间内有效数据。
  2. 时间窗口在kafkaStream,Flink等广泛应用
自定义分布式滑动时间窗口
  1. 定义最小时间WindowSize=30s,采用redis hash数据结构实现窗口,key为窗口标识id,例如01-01 21:01:00.数据属性放入Hash结构。
  2. 利用redis HINCRBY命令为哈希表 key 中的域 field 的值加上增量 increment,很容为数据聚合。
  3. 我们的间隔时间为Advancenterval 可以考虑为1-5分钟,key采用LRU设置大于Advancenterval的失效时间自动过期。
  4. 一个分布式滑动时间窗口已done。
参考
  1. kafkaStream时间窗口详细介绍 http://www.jasongj.com/kafka/kafka_stream/
  2. 限流降级神器「sentinel」基于滑动时间窗口 https://mp.weixin.qq.com/s/B1_7Kb_CxeKEAv43kdCWOA
  3. Sentinel GitHub
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值