前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >天天P图 - 分布式频控系统的设计和优化

天天P图 - 分布式频控系统的设计和优化

作者头像
天天P图攻城狮
发布于 2018-05-28 09:10:58
发布于 2018-05-28 09:10:58
2.7K6
举报
文章被收录于专栏:天天P图攻城狮天天P图攻城狮

为什么要做分布式频控系统?

相信之前刷屏的“八一军装照”和“小学生证件照”大家都不陌生。类似这样的运营活动突然涌入的巨大流量对天天P图后台造成的冲击不可小觑。就拿军装照来说,短短三小时,后台请求量就由10W/min突发到110W/min,短时间内无法调集足够多的机器来应对这些突发的流量,所以一套智能的分布式频控系统就非常有必要了。另外,随着天天P图人脸融合这一极具创意的技术知名度越来越高,也越来越多的第三方想和我们进行合作,使用我们的人脸融合能力。针对不同的第三方给予不同容量的后台处理能力也是很有必要的。综上,分布式频控系统的设计和开发提上日程。

图1 八一军装照

频控系统可用来对流量的削峰管理,使进入后台的流量尽在掌控之中,对后台的过载和雪崩防护可谓意义重大。它还可以对使用同一个接口的不同用户进行不同的频控额度管理,提供差异化服务。

当前厂内厂外很多业务都使用单机频控。单机频控只能做简单的流量拦截,简单而又粗暴,不考虑集群中各机器性能的差异性,不考虑逻辑系统的真实容量及容量可变性,进行简单的设置和拦截。要想全局频控和智能频控,还是得自己做一套!

频控策略的设计

根据一些现有方案的研究,我大致把频控策略分为以下几类:

图2 几种频控策略的对比

即时消费即时结算模式

该模式的原理是,接入层每收到一个请求都去频控中心进行频控校验,如果超限,进行拦截,如果未超限,请求放行,进行下一步的业务逻辑处理。

该方案有其优点,实现简单,频控实时性好。

但该方案对业务是阻塞的,而且性能低,每一次请求都需要访问频控中心,进行存储读写。该方案不具有接入层的抗流能力,即频控中心压力会随着接入层涌入请求量同比例放大。

预付费模式

该模式原理是,间隔一段时间去频控中心拉取一定流量额度,等这些额度消耗完了再去频控中心拉取下一批额度。根据有无额度,决定是否拦截。

该方案较第一种方案性能大幅提升,并具有极高的抗流能力。因为该模式不需要每次访问频控中心。

但该方案额度难以较好分配。一种分配方案是根据接入机数量,进行平均分配。这种方案没法考虑机器性能的差异,并且机器数并不是一成不变的,不具有良好的扩展性,而且如有机器出现故障,会影响整体的频控准确性。

先消费再结算模式

该模式是在前两种模式的基础上进行优化改进创造而来。

原理是,先放行一定数量的请求,然后批量上报到频控中心进行校验。根据校验结果,来决定接下来的请求是否拦截。

该模式是一种异步批量上报模式,对业务来说非阻塞,具有极高的性能和抗流能力。只是实时性稍差一点。但频控系统作为业务系统的辅助系统,该方案相对于其他优点来说,实时性稍差可以接受。故频控系统采用该种方案。

频控系统完整结构

如下图所示,频控系统分agent(FcAgent)和频控中心server(FcSvr)两块。agent和业务CGI部署在同一机器中,频控server负责进行频控的校验。

图3 频控系统架构图

共享内存kv用来存储各接口的频控结果,共享内存队列用来存放通过的请求记录。请求进入CGI后,只需要读取共享内存中该接口的频控结果,即可决定对该请求是否通行或者拦截。如果通行,向共享内存队列插入一条通行记录,再进行接下来其他的业务逻辑处理。FcAgent负责从共享内存队列中提取通行记录,累积到一定量后,向FcSvr进行上报检验是否频控超限,将获取的结果写回到共享内存kv中供下一次请求校验使用。

频控的配置信息存储在Redis中,使用运营系统进行频控额度等配置信息的更新。

频控计算方法

关于频控计算方法,业内主要分为计算器法、滑动窗口法、漏桶算法、令牌桶算法。计数器法简单,但是存储成本较高,而且有边界问题。

滑动窗口只是在计数器法上面进行精度再切割,降低了边界问题发生的风险,存储成本依旧很高。

漏桶算法原理是设定桶的一个恒定水流出速率,如果请求的流入速率大于桶设置的流出速率,桶自然会溢出,从而频控超限。漏桶算法可保证桶的流入速率即请求流入速率不超过设定的某一固定值。令牌桶算法本质和漏桶算法类似。只是说是定时向桶里匀速放入令牌,通过桶里是否有令牌来决定是否频控超限。

图4 漏桶算法示意图

这里采用基于漏桶算法的分布式改进算法进行频控的校验计算。

按照传统漏桶算法,当请求进来时,需要计算桶当前水量,桶剩余水量,根据剩余水量是否溢出来判断是否超限。随后更新当前时间戳,桶当前水量,已放行水量。用来进行下次的秒级频控和总额度频控。

一次频控校验需改写多个字段的值,需进行事务性保证。如果加锁的话,又极大影响了服务的性能。所以这里采取一次频控校验只需INCR更新当前桶水量即可,桶的其它信息(桶重置时间戳、秒级频控值、桶容量、已放行总量、频控总额度)进行缓存处理。

根据更新后的桶当前水量值减去这段时间流出的水量,即可知道桶的剩余水量。桶剩余水量减去桶容量,即可得桶溢出水量。

这里采用桶溢出时间这个概念进行频控拦截依据。桶溢出水量除以秒级频控值,即为桶溢出时间。桶溢出时间,即表明系统在该段溢出时间内,是不允许放入请求的。将该溢出时间返回给FcAgent,CGI在该溢出时间之后才放行新的请求。

图5 溢出时间的计算方法

频控总额度是否超限的判断依据是缓存中的已放行总量加上当前桶已放行量(桶当前水量-桶初始容量)是否超出总频控额度。

桶只有在桶配置信息发生变更或者桶长时间未有请求流入时才会进行重置。此时需要刷新桶缓存信息。

该种改进可保证频控计算的原子化,一次INCR操作即可完成秒级频控和总额度频控的校验。

异步上报的难点

几个问题制约着异步上报时间间隔不能太长也不能太短。

a) 频控延迟问题

异步上报必然会带来频控延迟问题。上报间隔越长延迟越严重。所以从这个角度看,上报间隔越小越好。

b) 突刺消耗问题

突刺消耗指一个时间周期内,前一段时间就消耗了全部流量,导致后一段时间无流量消耗,请求全部拦截。从这个角度看,上报间隔越小越好。

c) 匀速误限问题

匀速误限指请求速率不均匀导致被匀速削峰后造成误限。匀速误限一般在整体请求速率低于频控速率而局部请求速率高于频控速率的情况下发生。从这个角度看,上报间隔越长越好。

图6 匀速误限示意图

d) 频控压力问题

上报时间间隔越小,对频控中心压力越大。从这个角度看,上报间隔越小越好。

综上几个问题考虑,上报间隔既不能太小也不能太大。另外,仅仅以时间间隔作为上报依据的话,不管时间间隔设置多小,也难以解决突发高流量情况下,流量瞬间超限的情况。所以这里采用时间和个数两个维度,进行异步上报的依据。

个数维度解决频控延迟、突刺消耗、频控压力、流量突发问题,时间维度解决匀速误限、请求稀少问题。

那么,个数维度中的个数该怎么选定呢?假如全局每秒允许流入1000个请求,有10台接入机,这里的个数维度就绝对要小于1000/10,即最多累积10个请求就必须进行频控上报,否则就可能出现超限风险。当然,需要考虑频控上报到频控中心的请求延迟,所以要在该个数基础上进行一定倍数的缓冲,即设定一个缓冲倍数,个数维度即为1000/10/缓冲倍数,以该数值作为个数维度的间隔依据。

个数间隔 = 频控值/最大机器数/缓冲倍数

时间间隔 = 300ms

图7 异步上报时机

高可靠保证:容灾与纠错

a) 系统模块的容灾

系统某个模块出现故障是必须要考虑的情况。在当前分布式频控系统中,如果频控中心svr或者存储系统出现故障怎么办?常见的处理策略可能是要么请求全部放行,要么请求全部拦截。全部放行有造成冲垮业务服务的风险,全部拦截将会导致全业务不可用,显然都不是完美的解决方案。

在这里,可以引入局部频控策略。那么,局部频控的依据是什么呢?当然是上一次的频控结果了。在上一次频控结果的基础上,进行本地计算当次请求是否超限。

局部溢出时间 = max(0, (上次溢出时间 + 请求量/单机秒级频控量 - (当前时间戳-上次时间戳))

计算出的局部溢出时间如果大于0,表明请求在接下来该段时间内将进行拦截。

b) 局部纠错机制

除了对系统核心模块的容灾策略,多线程高并发下的数据准确问题也是系统高可靠的重要一环。Agent模块间隔异步批量频控校验避免了同一业务同一时刻发生频控校验的情况,然而网络异常情况下仍然可能出现频控结果逆序到达的情况。加锁太影响性能,而且发生逆序情况也是低概率事件,所以这里引入局部纠错机制对于逆序到达的频控结果直接废弃,避免对频控准确性造成影响。

那么,怎么判断频控结果是否逆序到达呢?我们的判断依据是:同一时刻收到的频控溢出时间后者必定大于前者。如同时先后收到溢出时间为30ms,20ms,则20ms这次直接剔除。

即如果该次溢出时间小于上次溢出时间减两次结果时间间隔的值,则认为该次结果为逆序,不予采信。

下图是采取容灾和纠错策略前后的频控效果图。 红色曲线代表实际请求每秒流入量,蓝色曲线代表实际请求每秒放行量。当蓝线越趋近于直线,表明频控准确率越高。

图8 无容灾纠错频控效果图

图9 有容灾纠错频控效果图

从上面两张效果图对比可以看出,局部频控和纠错解决了频控质量的波动问题,使得每秒请求放行量基本处于直线水平。

更智能的频控:动态频控

当某个调用方调用某个接口流量超过了当初设定的频控值,是不是就是直接进行拦截呢?我们这边对不同的调用方给予不同的评级,对于vip调用方(如人民日报),如果请求流量超限的话,会结合当前图片处理系统的处理能力,进行自动的频控值上调,达到动态频控的目的,最大限度地发挥图片系统的图片处理能力。

对于非vip的用户,如果流量超限,对于超限的流量也可以将流量引导到P图的下载,实现流量变现,降低图片系统的压力。

以下为动态频控流程图。多级预警、人工扩容和自动扩容相结合、超限流量变现,实现更智能的频控。

图10 动态频控流程图

极高的频控性能

a) 根据压测和线上表现,该分布式频控系统频控准确率超过99%(某时间段实际放行请求数/某时间段限制放行请求数),局部波动不超过2%(某秒多放行或少放行请求数/每秒频控值)

b) 每个业务每秒只会对频控中心产生接入机器数*缓冲倍数次请求,故接入层可抵御百万级每秒的涌入请求(取决于接入层的系统性能)

c) 2台4核8G虚拟机组成的频控中心系统性能可达10w/s,可支撑约2500个业务的频控校验

最后附上线上频控系统监控图。蓝色代表实际每秒放行请求量,红色代表实际请求涌入量。蓝色基本呈一条直线,表明频控效果良好。

图11 频控效果监控图


作者简介:jianghongwu(吴江红),天天P图后台开发工程师

文章后记: 天天P图是由腾讯公司开发的业内领先的图像处理,相机美拍的APP。欢迎扫码或搜索关注我们的微信公众号:“天天P图攻城狮”,那上面将陆续公开分享我们的技术实践,期待一起交流学习!

加入我们: 天天P图技术团队长期招聘 (1)图像处理算法工程师,(2)Android/iOS开发工程师,期待对我们感兴趣或者有推荐的技术牛人加入我们(base在上海)!联系方式:ygdai@tencent.com/keyishen@tencent.com/kesenhu@tencent.com

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-05-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 天天P图攻城狮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
6 条评论
热度
最新
容灾是什么?
容灾是什么?
回复回复点赞举报
蓝色曲线和红色曲线是一个量级单位吗?看上去要小得多
蓝色曲线和红色曲线是一个量级单位吗?看上去要小得多
回复回复点赞举报
咦,这天天P图还有付费项呢?
咦,这天天P图还有付费项呢?
回复回复点赞举报
还有待优化,有的还是有违和感
还有待优化,有的还是有违和感
回复回复点赞举报
我用过,还挺好玩的,P得还真像那么回事
我用过,还挺好玩的,P得还真像那么回事
回复回复点赞举报
朋友圈里之前很火
朋友圈里之前很火
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
分布式高可靠之流量控制篇,你也能像大禹一样去治水
在上一篇文章中(分布式高可靠之负载均衡,今天看了你肯定会),我带你学习了分布式高可靠中的负载均衡。负载均衡的核心在于,将用户请求均匀分配到多个处理服务器处理,以解决单个服务器的单点瓶颈问题。但,如果用户请求数非常多的话,即便实现了负载均衡,服务器能力达到上限,还是无法处理所有的用户请求。
架构师修炼
2020/07/17
2.8K0
SpringCloudAlibaba+Nacos+Nginx+Dubbo分布式服务流量管理设计
胡弦,视频号2023年度优秀创作者,互联网大厂P8技术专家,Spring Cloud Alibaba微服务架构实战派(上下册)和RocketMQ消息中间件实战派(上下册)的作者,资深架构师,技术负责人,极客时间训练营讲师,四维口袋KVP最具价值技术专家,技术领域专家团成员,2021电子工业出版社年度优秀作者,获得2023电子工业出版技术成长领路人称号,2024年电子工业出版社博文视点20周年荣誉专家称号。
35岁程序员那些事
2024/04/26
3220
SpringCloudAlibaba+Nacos+Nginx+Dubbo分布式服务流量管理设计
分布式高并发系统限流原理与实践
随着业务的发展壮大,对后端服务的压力也会越来越大,为了打造高效稳定的系统, 产生了分布式,微服务等等系统设计,因为这个原因,设计复杂度也随之增加,基于此 诞生了高并发系统三大利器限流,缓存,降级/熔断。
merlinfeng
2020/12/31
8800
分布式高并发系统限流原理与实践
面试必备:4种经典限流算法讲解
最近,我们的业务系统引入了Guava的RateLimiter限流组件,它是基于令牌桶算法实现的,而令牌桶是非常经典的限流算法。本文将跟大家一起学习几种经典的限流算法。
捡田螺的小男孩
2021/06/15
1.9K2
面试必备:4种经典限流算法讲解
一个 Redis 的雪崩和穿透问题,小学妹画了个图,结果入职了
阿粉的一个小学妹最近刚从某个小互联网公司跳槽,然后最近面试的挺多的,一个不善言语的小姑娘,技术还是 OK 的,本来之前是做 UI 的,但是时间长了,感觉没太大意思,所以就开始学了后端,然后从原有公司慢慢的转为了后端开发人,也就是我们所说的 “程序猿”,最近面试给阿粉谈了谈她的面试经验。阿粉比较印象深刻的一句话就是,我给你画个图,你看一下,这是对面试官说的,事情是什么样子的呢?
Java极客技术
2022/12/02
2210
一个 Redis 的雪崩和穿透问题,小学妹画了个图,结果入职了
使用Guava的RateLimiter做限流
1.在日常生活中,我们肯定收到过不少不少这样的短信,“京东最新优惠卷…”,“天猫送您…”。这种类型的短信是属于推广性质的短信。这种短信一般群发量会到千万级别。然而,要完成这些短信发送,我们是需要调用服务商的接口来完成的。倘若一次发送的量在200万条,而我们的服务商接口每秒能处理的短信发送量有限,只能达到200条每秒。那么这个时候就会产生问题了,我们如何能控制好程序发送短信时的速度昵?于是限流器就得用上了。
哲洛不闹
2019/08/06
1K0
高并发下的限流策略
限流策略通常是用来在高qps下进行流量限制的,常见的方式有计数器、令牌桶、漏桶。在这次活动中我负责的模块是控制的对下游的流量,我们可以让那些请求选择丢弃、等待或者降级这些限流算法可以自行实现也可以利用现有的限流工具,比如说Guava的令牌桶,具体看场景需求吧,下面来看一下这几种限流策略,再说说我写的限流方式。
邹志全
2019/07/31
1.8K0
【Node开发】分布式调用限频限流的开发设计
作者:harkinli  腾讯CSIG工程师 |导语  在Node服务开发中,常常需要对许多批量请求进行限频发送,以保证被调用方的系统安全或者调用限制,这里以企业微信API的客户标签修改为例,讲述在企业微信API的限频要求下的分布式限频模块的算法和设计细节。 01 前言 后端服务是十分重视容灾和负载的,特别是在系统的承载服务急剧增加之后,各种性能瓶颈就开始出现了,其中比较常见的则是对高并发下场景的调用支持程度。本篇文章并不是介绍如何去设计支持高并发的系统设计,这整个主题过于庞大,小编也是在学习之中,待有所
腾讯大讲堂
2021/03/09
1.6K0
如何保证核心链路稳定性的流控和熔断机制?
仅从设计优化、服务拆分、自动扩容等方面进行优化,有时候并不能完全解决问题。比如,有时流量增长过快,扩容流程还来不及完成,服务器可能就已经抗不住了
码农架构
2020/11/16
6250
如何保证核心链路稳定性的流控和熔断机制?
精讲高并发核心编程,限流原理与实战,限流策略原理与参考实现
在通信领域中,限流技术(Time Limiting)被用来控制网络接口收发通信数据的速率,实现通信时的优化性能、较少延迟和提高带宽等。
愿天堂没有BUG
2022/10/28
3240
精讲高并发核心编程,限流原理与实战,限流策略原理与参考实现
常见限流算法解读
在现在的互联网系统中有很多业务场景,比如商品秒杀、下单、数据查询详情,其最大特点就是高并发,但是我们的系统通常不能承受这么大的流量,继而产生了很多的应对措施:消息队列、多级缓存、异地多活。但是无论如何优化,由于硬件的物理特性决定了我们系统性能的上限,如果强行接收所有请求,往往造成服务雪崩,导致服务的不可用,这个时候服务限流就成为我们必不可少的一个手段了。
一个风轻云淡
2023/11/15
6900
高并发系统设计之限流
当我们谈论Web应用或者服务,一个重要的话题就不能避免:「限流」。这是一种保护系统和维持服务稳定性的重要手段。
BookSea
2023/10/16
5580
高并发系统设计之限流
基本限流算法与GuavaRateLimiter实现
总结: 固定窗口算法适用于对请求速率有明确要求且流量相对稳定的场景,但对于突发流量和请求分布不均匀的情况,可能需要考虑其他更灵活的限流算法。
leobhao
2024/08/07
1660
基本限流算法与GuavaRateLimiter实现
分布式系列之限流组件
在高并发场景下,请求量瞬间到达,后端服务器即使有缓存、集群主备、分库分表、容错降级等措施,也有可能扛不住这请求量,因此可考虑引入限流组件。限流的目的:防止恶意请求流量或流量超出系统承载。
johnny666
2024/09/23
2470
服务端频率控制的几种实现方式
对于某一个接口I,请求频率阈值T,假设请求均匀分散到N台服务器上,每台服务器上接口I的频率阈值就是T/N,这样每台机器通过检查接口I的本地请求频率就可以做频率控制。
腾讯 BBTeam 团队
2018/05/31
4.2K0
1.计数器算法
计数器算法是在一定的时间间隔里,记录请求次数,当请求次数超过该时间限制时,就把计数器清零,然后重新计算。当请求次数超过间隔内的最大次数时,拒绝访问。
磊哥
2023/03/09
4780
1.计数器算法
限流系列之一:微服务常见限流方案及 TSF 限流原理
在微服务高并发场景下,微服务之间的调用量不断增加,大流量很可能会引起服务崩溃,微服务的稳定性对业务系统的影响也比较大。一般微服务容错组件都提供了限流的方式来保护我们的系统,本文主要介绍微服务限流的几种主流方案与适用的场景。
腾讯云中间件团队
2025/03/18
3170
限流系列之一:微服务常见限流方案及 TSF 限流原理
大规模分布式架构中,怎样设计和选择 API 限流技术?
本文由极客时间整理自腾讯云微服务中心高级研发工程师丁硕青在 QCon+ 案例研习社的演讲《大规模分布式架构中 API 限流技术探索与实践》。 作者|丁硕青 编辑|王丽娜 你好,我是丁硕青,目前在腾讯云负责 API 网关等中间件产品的研发工作,工作以来主要从事云计算相关的项目,也从 0 到 1 经历过不少项目的落地。今天主要想跟你聊一下在分布式架构中,我们应该如何设计和选择一个最适合的 API 限流技术方案。 接下来,我会从以下四个章节来进行介绍: 为什么需要限流 常见限流算法 分布式限流技术要点
深度学习与Python
2023/03/29
1K0
大规模分布式架构中,怎样设计和选择 API 限流技术?
如何通过限流算法防止系统过载
我们在日常生活中,就有很多限流的例子,比如地铁站在早高峰的时候,会利用围栏让乘客们有序排队,限制队伍行进的速度,避免大家一拥而上;再比如在疫情期间,很多景点会按时段限制售卖的门票数量,避免同一时间在景区的游客太多等等。
栗筝i
2023/02/02
6190
如何通过限流算法防止系统过载
经典限流算法设计与实现
假设单位时间是一秒,限流阈值为3。在单位时间1秒内,每来一个请求,计数器就加1,如果计数器累加的次数超过限流阈值3,则后续的请求全部拒绝。等到1s结束后,计数器清零,重新开始计数。
大忽悠爱学习
2023/10/27
6990
经典限流算法设计与实现
相关推荐
分布式高可靠之流量控制篇,你也能像大禹一样去治水
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档