写点什么

预案三板斧的限流大法

  • 2019-10-21
  • 本文字数:2794 字

    阅读完需:约 9 分钟

预案三板斧的限流大法

限流策略:多维防御+纵深防御

限流能力

限流是针对请求的各种特征,多维防御+纵深防御,从而限制流量,实现对服务端资源的合理使用。这里的特征是指一个请求所包含的各种信息,包括但不限于 IP、Header、URI、Cookie 等。常见的限流策略有以下三种(以 Nginx 为例进行说明):


  • 限制请求数,意思是请求的次数不能太多


Nginx:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html


  • 限制并发连接数,意思是请求的频率不能太快


Nginx:http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html


  • 限制传输速度,意思是请求的体积不能太大


Nginx:http://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate


Nginx 还提供 work_connections 和 worker_processes 这类针对程序的全局设置,但是这些配置并非是客户端的请求的特征,不能直接作用于特定请求特征的流量,因此不属于本文限流的讨论范畴。

多维防御

所谓的多维防御,不仅仅针对 IP 进行限制,还可以从 URI、Cookie、状态码等多个维度进行限制,同时还可以组合起来进行精细化的限制,举例说明:


  • 状态码+IP,如果恶意扫描整个网站,必然会出现较多的 404 状态码,这时候结合其他维度,就可以进行一定的防御和限制

  • URI+Cookie,可以避免公司 IP 出口导致的请求被误伤,同时也解决了 IP 模式下阈值设置太大的问题

纵深防御

所谓的纵深防御,则是指针对单一维度,进行多层级的防御,实现精细化的限制。以 IP 维度为例进行说明:


  • 每秒钟,单个 IP 最多可以访问 100 次

  • 每十秒钟,单个 IP 最多可以访问 500 次

  • 每分钟,单个 IP 最多可以访问 1000 次

阈值设置

上述的阈值只是简单举例,并没有太大的参考价值,在实际部署的过程中,一般需要至少 30 天的访问日志以及多个节假日的访问日志进行离线分析,从而得出业务特定的合理阈值,然后在通过灰度逐步全量。初期的阈值,建议设置的比预估阈值至少高一倍,先具备限流功能,然后再慢慢打磨阈值,避免因为阈值设置不合理,导致限流功能上线受阻,那就得不偿失了。

限流的算法

那各种限流策略背后的实现机制是怎样的呢?常见的限流算法有固定窗口计数器,滑动窗口计数器,漏洞和令牌桶四种,在各类软件的具体实现上却不尽相同,详细内容可以参考这篇文章《分布式系统关注点——限流该怎么做?》,本文仅介绍较为常用的两种算法。

固定窗口计数器

将时间划分为固定时间窗口(例如每秒一个单位),在每个固定的时间窗口内对请求进行计数,如果请求的次数超过了限制,则本时间窗口内所有的后续请求都被丢弃,直到下一个固定时间窗口时,重置计数器。



该算法常被吐槽流量突增,举例来说 100r/m(每分钟 100 次请求),可能在第一秒钟就请求完毕,更有甚者,在两个时间窗口交界处可能会产生 2 倍的请求,这样就会导致短时的流量突增。但是,只要把时间粒度控制在秒级,效果还是可以的。因此,滑动窗口就没有太大的必要进行介绍了,大家看相关文章即可。


漏桶

漏桶算法,有一个固定大小的队列,进入的请求全部放入该队列中,如果队列满,则丢弃进入的请求。同时,以固定的速率从队列中消费请求。好处就是,不管流量进来多少,出去的速率始终固定。


该算法的主要不足就是消费速率设置会偏保守一些,因为不同请求的资源消耗和处理耗时不同,为了能够适配各类场景,必然会导致消费速率设置较为保守。缓解的方法,对不同的请求类型进行集群拆分,从而能够更加精细化的设置消费速率。


各层级限流

全局统一接入:GFE/BFE/JFE

全局统一接入的产品,Goolge 叫做 GFE,Baidu 叫做 BFE,JD 叫做 JFE。这类产品会将公司所有对外流量进行统一的接入和调度,同时具备较强的通用防护能力,如抗 D、WAF 等。


对于一些业务定制化的复杂限流规则,一般会下放到各个业务线自己的接入端来实现。


Webserver:Nginx/OpenResty

上面介绍各种 XFE 的时候提到,一些业务定制化的复杂限流规则,会下放到各个业务线的接入端来实现,在这个阶段,因为 Webserver 的选择较多,所以实现方式也较多,没有统一的标准,一般是直接利用 webserver 提供的限流能力,或者是通过插件方式来实现,前者多以 Nginx 为主,后者则是 Nginx+lua/Nginx+lua+redis 的形式。


本文以 Nginx 为例来进行说明,业务侧的整体思路应该是多维防御+纵深防御,从而实现较好的限流效果。


多维防御,以 Nginx 的 limit_req 为例进行说明,不仅仅对来源 IP 进行流控,还可以对请求的 uri,cookie 进行流控,还可以对 ip+uri+cookie 的组合进行流控,从多个维度下手,进而实现更好的效果。


limit_req_zone $ip zone=1:10m rate=100r/s;


limit_req_zone ip zone=2:10m rate=100r/s;


limit_req_zone ip$cookie zone=3:10m rate=100r/s;


limit_req zone=1 burst=30 nodelay;


limit_req zone=2 burst=10 nodelay;


limit_req zone=3 burst=30 nodelay;


纵深防御,以 Nginx 的 limit_req 为例进行说明,主要是通过漏斗思路,设置三级防御体系,第一级是粗滤,因此阈值可以设置的较大,仅拦截明显的恶意行为即可,第二级过滤,可以拦截一些异常请求,第三级过滤,则可以将大部分异常请求进行拦截。


limit_req_zone $ip zone=11:10m rate=100r/s;


limit_req_zone $ip zone=12:10m rate=500r/10s;


limit_req_zone $ip zone=13:10m rate=1200r/1m;


limit_req zone=1 burst=50 nodelay;


limit_req zone=2 burst=100 nodelay;


limit_req zone=3 burst=200 nodelay;


备注:Nginx 本身并不支持 500r/10s 这种模式,同时,60r/m 的效果等同于 1r/s,因此上述的配置只能起到一个演示的作用。实际上是需要大家通过插件的方式来实现上述的效果。Nginx 官方对于 r/m 的解释如下:The rate is specified in requests per second (r/s). If a rate of less than one request per second is desired, it is specified in request per minute (r/m). For example, half-request per second is 30r/m.

应用程序和中间件:Istio

对于大部分自研的程序来讲,限流功能如有必要,就得自行实现了,算法前面已经介绍过了,当然,也可以参考 Google 的 RateLimiter。


对于进入了 Docker 的程序,则可以考虑引入 Istio,改造成本可控,收益上,限流,熔断,鉴权等等功能均可具备,但是目前大规模应用的公司还不多,大家都是在慢慢探索中。


对于短期内还无法实现虚拟化的业务,则可以考虑类似 Istio 的模式,在每个程序前,在关键程序前,在和多个下游交互的程序前,适度放置 Proxy 来实现流控的效果。在 AWS 的 Proxy-ELB,就是挂在了每组服务之前。这种模式的缺点就在于会略为增加延时,但如果是同 Regin 部署,那么只要增加的 Proxy 层级数量可控,整体延时影响也可控。


极少数情况下,也有业务直接通过 Iptable 的方式进行限流,对于物理机的部署模式,笔者只能建议要谨慎使用。


参考文章


分布式服务限流实战,已经为你排好坑了


分布式系统关注点——限流该怎么做?


华为交换机设置配置说明


BFE开源版本


2019-10-21 11:5612580

评论

发布
暂无评论
发现更多内容

仅仅上线一小时,下载量就破10W!阿里内部Java性能优化实战手册

java小李

面试 JVM

索信达控股:探寻金融数字化转型契机下的高增长“密码”

索信达控股

短视频SEO营销系统软件开发资料

java并发编程

十二万伏特皮卡丘

技术分析| 即时通讯和实时通讯的区别

anyRTC开发者

音视频 WebRTC 即时通讯 实时通讯 实时消息

短视频SEO获客系统软件开发简介

从简历被拒到收割8个大厂offer,我用了3个月成功破茧成蝶

java小李

面试

贝丽美牙系统开发(开发案例),贝丽美牙源码设计

系统开发咨询1357O98O718

独家!精挑细选三个月的臻品Java面试题,无糟粕!高质量

白亦杨

Java 编程 程序员 架构师 计算机

花朵分类(一)

毛显新

深度学习 tensorflow keras

Tensorflow serving with docker

毛显新

tensorflow Docker

双特新零售系统开发(开发模式),双特新零售现成源码

系统开发咨询1357O98O718

Go语言:如何通过 RPC 来实现跨平台服务!

微客鸟窝

Go 语言

抖音获客系统开发(软件开发),抖音获客源码模式

系统开发咨询1357O98O718

短视频SEO软件系统开发资料

妙视亮眼贴系统开发案例分析,妙视亮眼贴开发源码

系统开发咨询1357O98O718

南山二脂系统开发功能,南山二脂源码案例设计

系统开发咨询1357O98O718

直呼内行!靠着这份阿里10w字面试总结,我成功收到了4个大厂offer

Java 程序员 架构 面试 计算机

一周信创舆情观察(7.19~7.25)

统小信uos

短视频询盘软件系统开发内容

通过创建GeoLine给地图添加烟花图效果

ThingJS数字孪生引擎

大前端 地图 物联网 可视化

WebAssembly正逐渐成为FaaS的主力

吴脑的键客

Docker Faas webassembly

发布两小时,霸榜GitHub!Spring Boot实战文档

java小李

Spring Boot

IT自动化运维工具就用行云管家!省心省力省事!

行云管家

云管平台 IT运维 行云管家 自动化运维

逆袭成功,不愧是阿里内部面试参考指南,已帮我拿下了8个大厂的offer

Java 程序员 架构 面试 计算机

【共识专栏】共识的分类(上)

趣链科技

区块链 联盟共识 共识机制 共识算法

后端开发-Reactor设计模式

Linux服务器开发

reactor 设计模式 网络编程 线程池 epoll

GitHub万人斩!Java系列面试宝典,我拿到之后直接反杀了面试官

java小李

git cherry-pick

直播时各种背景是怎么实现的?聊一聊虚拟背景背后的技术

阿里云视频云

阿里云 计算机视觉 视频会议 虚拟背景 人像抠图

抖音获客APP开发,抖音获客系统开发(成功案例),抖音获客系统源码

系统开发咨询1357O98O718

只出现一次的数字

Memorys

Java 面试 算法

预案三板斧的限流大法_软件工程_焦振清_InfoQ精选文章