解锁新姿势 | 如何用配置中心实现全局动态流控?

标签: geek | 发表时间:2018-01-24 00:00 | 作者:
出处:http://itindex.net/relian

摘要: 当资源成为瓶颈时,服务框架需要对消费者做限流,启动流控保护机制。流量控制有多种策略,比较常用的有:针对访问速率的静态流控、针对资源占用的动态流控、针对消费者并发连接数的连接控制和针对并行访问数的并发控制。在分布式架构中,应用和应用之间的调用类型分为以下两种,流控方式也略有不同。

点此查看原文: https://yq.aliyun.com/articles/380180?spm=a2c41.11181499.0.0

当资源成为瓶颈时,服务框架需要对消费者做限流,启动流控保护机制。流量控制有多种策略,比较常用的有:针对访问速率的静态流控、针对资源占用的动态流控、针对消费者并发连接数的连接控制和针对并行访问数的并发控制。在实践中,各种流量控制策略需要综合使用才能起到较好的效果。

在分布式架构中,应用和应用之间的调用类型分为以下两种,流控方式也略有不同。

同步RPC类调用,比如RESTful,Dubbo,HSF等都属于该类。对于该类同步调用,通常限流方式为两种:针对服务提供者的并发全局流控,或针对服务消费者的并发局部流控。两种的控制手段类似,都是通过限制服务端或客服端并发调用数来进行限制。

异步MQ类调用,典型如RocketMQ, Kafka,等。对于该类异步调用,通常限流方式是在订阅端限流。限流方式为两种:针对消息订阅者的并发流控,或针对消息订阅者的消费延时流控。

针对消息订阅者的消费延时流控基本原理是,在每次客户端消费时,可以增加一个延时来控制消费速度,这样理论消费并发最快速度为:

MaxRate = 1 / ConsumInterval * ConcurrentThreadNumber

比如如果消息并发消费线程为20,延时为100ms,则理论上可以将并发消费控制在200以下。具体公式如下:

200 = 1 / 0.1 * 20

相比并发线程数流控,消费延时流控优点在于实现相对简单,对MQ类客户端包依赖较少,不需要客户端提供控制并发线程数的动态调整接口。

以上各种流量控制方法,在分布式架构下,如果要做到全局动态控制,一个简单的技术方法是依赖配置中心,即通过配置中心来进行流控参数的下发。

下面章节详细介绍如何基于配置中心来实现异步消息消费的全局动态流控。使用的例子为阿里云上的 MQ (消息队列)和 ACM (应用配置管理)两款产品。

注:之所以用MQ为示例是因为在本文撰写之时,正好MQ Consumer Client SDK并不支持动态调整现成并发数,因此通过基于ACM来动态调整消费延迟的方法正好可以解决MQ消费流控动态的问题。

基于消费延时流控的基本原理

基本原理如下。其中,管理员或应用程序通过ACM控制台发布消费延时配置(RCV_INTERVAL_TIME),所有MQ消费程序订阅该配置。理论上,该配置从发布到下发所有客户端,可以在1秒内完成(取决于网络延时)。

图片描述

代码示例

该章节基于配置中心来实现异步消息消费的全局动态流控的代码示例。使用的例子为阿里云上的MQ(消息队列)和ACM(应用配置管理)两款产品,基于Java语言。关于SDK的详细介绍,可参见两款产品的官方文档。

在ACM上创建消费延时的参数,截屏如下。

图片描述

设置全局消费延时变量

首先,设置消费接收延时的全局变量, 如下。

   // 初始化消息接收延时参数,单位为millisecondstaticintRCV_INTERVAL_TIME =10000;// 初始化配置服务,控制台通过示例代码自动获取下面参数ConfigService.init("acm.aliyun.com",/*租户ID*/"xxx",/*AK*/"xxx",/*SK*/"yyy");// 主动获取配置String content = ConfigService.getConfig("app.mq.qos","DEFAULT_GROUP",6000);

        Properties p =newProperties();try{

            p.load(newStringReader(content));

            RCV_INTERVAL_TIME = Integer.valueOf(p.getProperty("RCV_INTERVAL_TIME"));

        }catch(IOException e) {

            e.printStackTrace();

        }

其次,设置ACM listener,确保当配置被修改时,即使更新 RCV_INTERVAL_TIME 参数, 如下。

   // 初始化的时候,给配置添加监听,配置变更会回调通知ConfigService.addListener("app.mq.qos","DEFAULT_GROUP",newConfigChangeListener() {publicvoidreceiveConfigInfo(String configInfo) {

                Properties p =newProperties();try{

                    p.load(newStringReader(configInfo));

                    RCV_INTERVAL_TIME = Integer.valueOf(p.getProperty("RCV_INTERVAL_TIME"));

                }catch(IOException e) {

                    e.printStackTrace();

                }

            }

        });

设置 MQ 消费延时逻辑

完整实例如下。

注:这里 RCV_INTERVAL_TIME 参数的访问是故意没有加锁的,读者可以自行思考原因。Aliyun ONS Client不提供动态线程并发数,默认并发为20。因此这里正好使用消费延时参数来动态调节QoS。

   //以下代码可直接贴在Main()函数里Properties properties =newProperties();

    properties.put(PropertyKeyConst.ConsumerId,"CID_consumer_group");

    properties.put(PropertyKeyConst.AccessKey,"xxx");

    properties.put(PropertyKeyConst.SecretKey,"yyy");

    properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis,"3000");// 设置 TCP 接入域名(此处以公共云生产环境为例)properties.put(PropertyKeyConst.ONSAddr,"http://onsaddr-internet.aliyun.com/rocketmq/nsaddr4client-internet");

    Consumer consumer = ONSFactory.createConsumer(properties);

    consumer.subscribe(/*Topic*/"topic-name",/*Tag*/null,newMessageListener() 

    {publicActionconsume(Message message, ConsumeContext context) {// MQ Subscribe QoS logical start,// Each consuming process will sleep for RCV_INTERVAL_TIME seconds with 100 ms sleeping cycle.// Within each cycle, the thread will check RCV_INTERVAL_TIME in case it's set to a smaller value.// RCV_INTERVAL_TIME <= 0 means no sleeping.intrcvIntervalTimeLeft = RCV_INTERVAL_TIME;while(rcvIntervalTimeLeft >0) {if(rcvIntervalTimeLeft > RCV_INTERVAL_TIME) {

                    rcvIntervalTimeLeft = RCV_INTERVAL_TIME;

                }try{if(rcvIntervalTimeLeft >=100) {

                        rcvIntervalTimeLeft -=100;

                        Thread.sleep(100);

                    }else{

                        Thread.sleep(rcvIntervalTimeLeft);

                        rcvIntervalTimeLeft =0;

                    }

                }catch(InterruptedException e) {

                    e.printStackTrace();

                }

            }// MQ Subscribe interval logical endsSystem.out.println("Receive: "+ message);/*

             * Put your business logic here.

             */doSomething();returnAction.CommitMessage;

        }

    });

    consumer.start();

运行结果

单机运行consumer进行消费,假设queue内的消息无限多,不存在消费万的情况,分三段测试,分别运行约5分钟,通过ACM配置推送来达到以下效果。

RCV_INTERVAL_TIME = 100 ms

RCV_INTERVAL_TIME = 5000 ms

RCV_INTERVAL_TIME = 1000 ms

结果如下,在单MQ消费业务处理耗时约100ms情况下的,单机并发20线程的测试结果。

RCV_INTERVAL_TIME = 100 ms:平均消费性能约为 9000 tpm 左右

RCV_INTERVAL_TIME = 5000 ms:平均消费性能被限制到了 200 tpm 左右

RCV_INTERVAL_TIME = 1000 ms:平均消费性能回升到到了 1100 tpm 左右

以上结果基本达到消费和 tpm 成反比的预期,最关键的是整个过程中,应用不中断,流控推送结果秒级生效到分布式集群。单机性能结果如下所示。

图片描述

相关 [姿势 中心] 推荐:

解锁新姿势 | 如何用配置中心实现全局动态流控?

- - IT瘾-geek
摘要: 当资源成为瓶颈时,服务框架需要对消费者做限流,启动流控保护机制. 流量控制有多种策略,比较常用的有:针对访问速率的静态流控、针对资源占用的动态流控、针对消费者并发连接数的连接控制和针对并行访问数的并发控制. 在分布式架构中,应用和应用之间的调用类型分为以下两种,流控方式也略有不同. 当资源成为瓶颈时,服务框架需要对消费者做限流,启动流控保护机制.

少女 、 少妇 、熟妇。姿势

- nethibernate - 微博段子
原文地址:http://www.heartrip.com/tweets/12629.html.

学姐,你喜欢什么姿势呢?

- Dex - 犯贱志
曾经,有一个无比NB的人在网吧扫雷扫了一个通宵,另外一个同学看他扫雷,看了一个通宵. 现在在开考研表彰大会,院长为了说身体健康重要,说“如果没有好的身体,老婆可能也是别人的…”. 下面1000人啊,笑得很小心翼翼…. 我和一个哥们在大谈各个时代拍照的姿势,比如80后喜欢V字手势,90后鼓腮帮子. 然后我转头问正在看小说的一个学姐:“学姐,你喜欢什么姿势呢.

为用户设计舒适的姿势

- - 酷勤网-挖经验 [expanded by feedex.net]
酷勤网 � 程序员的那点事. 关心用户的情绪,做出给予和引导正向情感的设计,我们也要关注用户的身体,帮用户用舒服的姿势使用产品. 做一个简单的测试,拿起鼠标,第一次,让光标从屏幕的顶边中点,尽量保持垂直线移动到底部;第二次,让光标从屏幕左边中点,尽量保持水平线移动到右边. 感觉一下,第一次和第二次,哪个操作让你觉得累.

在Linux进行IO的正确姿势

- - idea's blog
很多C/C++程序虽然在做网络编程, 但大多用别人封装好的库, 对底层不甚了解, 感觉 IO 操作不是很简单吗. 我敢说, 大多数人进行 IO 的姿势都不对, 所谓的 IO, 主要是 read()/write() 两个函数.. 先说错误的 IO 读操作:. 看起来好像很正确的样子, 返回值也判断了, 不仅判断 -1, 还判断 0, 应该姿势正确吧.

iOS客户端hack的两种姿势

- - WooYun知识库
分析某商城漏洞,在漏洞验证时采用了两种iOS上的hack工具:cycript和reveal,各有风情,均能攻城拔寨,实乃我辈日常居家、杀人越货之利刃,现与诸君共享之. 该商城的iOS版app为用户提供了找回密码的功能,用户需通过三个步骤找回密码:. 输入一个本地的图形辨识验证码(多余. 提供用户手机号,输入一个短信验证码.

Redis 的正确使用姿势

- - IT瘾-dev
说到分布式缓存,可能大多数人脑海浮现的就是redis了,为什么redis能够在竞争激烈的缓存大战中脱颖而出呢. 原因无非有一下几点:性能好,丰富的特性跟数据结构,api操作简单. 但是用的人多了,就会出现很多不规范或者疏忽的地方,严重的时候甚至会导致生产事故,所以我们有必要来聊聊在Redis使用过程中的一些“正确姿势“.

微服务划分的姿势

- - DockOne.io
【编者的话】我们知道微服务是一种理念,没有确切的定义和边界,好比设计原则,是属于抽象的概念. 在定义不明确的情况下谈划分也是一种各说各话,具体问题需要具体分析,所以这篇文章谈到的划分也不是绝对标准,仅供参考. 有人说微服务不难,难的是服务的划分,虽然我持保留意见,但是从侧面也反应了划分具有一定的困难.

事实证明打炮也是要摆好姿势的

- lzhi - Lzhi&#39;s Views
Apple新老大:硅谷最有权力的Gay. 视频: 把450克钠扔入水池后. 本文网址:http://www.lzhi.org/views/656015. 欢迎加入500人超级QQ群:108869281,交流最新好文章.

花2分钟了解正确的上网姿势

- Bob - 囧片王
用葛炮的话说是:我有姿势我自豪. 2分钟创意短片,告诉你正确的上网姿势,养成良好的习惯,以后就不会腰酸背痛手抽筋了:.