写点什么

预案三板斧的限流大法

  • 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:5612744

评论

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

云端协同,打造全场景智能会议,华为云会议更专业“会”更好

科技之光

低代码平台 - 危险的赌注

世开 Coding

软件开发 低代码 开发框架

web前端培训学习能找到工作吗

小谷哥

新手剪辑师秒变大神 高级感视频剪辑的几种常用技巧

懒得勤快

React中常见的TypeScript定义实战

xiaofeng

React

分布式事务Seata框架的AT模式

C++后台开发

分布式 微服务 后端开发 C++开发 Seata框架

倒计时第2天!2022 XDR网络安全运营新理念峰会即将开幕

未来智安XDR SEC

网络安全

前端培训学习完之后可以从事的工作方向

小谷哥

大数据开发培训学习方法

小谷哥

二十年CRM市场跌宕起伏,Zoho选择“慢速”奔跑

ToB行业头条

代码质量与安全 | 关于糟糕代码的那些事

龙智—DevSecOps解决方案

代码质量 代码安全

代码质量与安全 | 入门必备:什么是自动化测试?

龙智—DevSecOps解决方案

代码质量 自动化测试 测试质量

1024,节日快乐

未来智安XDR SEC

如何规范App广告的隐私获取,让用户拥有更多知情权?

HarmonyOS SDK

广告sdk

持续引领产业发展,华为云桌面连续6年位居国内市占率第一

路过的憨憨

华为

React-hooks+TypeScript最佳实战

xiaofeng

React

TPU演进十年:Google的十大经验教训

OneFlow

人工智能 深度学习 TPU

SAP | 聊一聊必不可少的Debug

暮春零贰

debug SAP 10月月更

BizWorks应⽤平台基于KubeVela的实践

阿里云E2企业云服务

阿里云 中台 插件 企业架构和云服务 api 网关

1024程序员节 | 畅聊名“猿”之路,重磅视频预告

小谷哥

机器学习在基于 URL 的客户端监控分析中的优化和实践

Shopee技术团队

机器学习 数据分析 url 客户端 数据监控

SAP | 如何使用内部表

暮春零贰

SAP 10月月更 内部表

生产数据实时分析,产品质量高效管控|打造面向工业4.0的智能工厂02

EMQ映云科技

云原生 物联网 IoT 边云协同 10月月更

为企业远程会议保驾护航,华为云会议安全更有保障!

科技之光

MDAP:可观测性数据分析平台设计与实践

Shopee技术团队

数据分析 APM 性能 终端 数据监控

华为云数据库 GaussDB(for MySQL),让企业无忧数据恢复

科技之光

【文本检测与识别白皮书】第三章 - 第三节:算法模型 2

合合技术团队

人工智能 深度学习 大数据 文字识别

RFO SIG:openEuler AWS AMI 制作详解

openEuler

Linux 开源 Kubernetes 云原生 AWS

命令执行相关的web题

w010w

命令行 CTF 每日一题 10月月更 web基础

支持随时随地一键开会,华为云会议场景适用性更强!

科技之光

版本控制 | 游戏开发企业如何高效远程协作?

龙智—DevSecOps解决方案

版本控制 游戏开发 版本管理

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