php 漏桶算法,漏桶算法和 NGINX 的 limit_req 模块

DDOS 攻击可能是网络上最常见的攻击之一。互联网发展到今天,当然也有很多成熟的抵御 DDOS 攻击的方法。今天的主角跟其有密切关系,他被称之为漏桶算法。

漏桶算法要解决的一个核心问题,便是如何将不断变化的访问量,变成相对稳定的一个访问量。这么说可能太过抽象,举一个实际的例子,NGINX 接收到互联网上的请求,速率是 n requests/second,或者说 n RPS,但这个 n 是不可控制的,可能是 0.1,也可能是 10 万。NGINX 需要将这些请求发送给后台的 PHP-FPM 服务去处理。假如被访问的 PHP 脚本,能稳定处理的 RPS 是 1 万,而实际的访问量正不断在 0.1 RPS 和 10 万 RPS 之间徘徊(这个例子有点太夸张,懂我意思就行),那么有什么办法可以让 PHP-FPM 接受到来自 NGINX 的请求能相对稳定,这就是漏桶算法需要解决的问题。

漏桶这个名字,其实就非常形象的描述了算法本身的原理。大家都知道,一个身上打了 n 个眼儿的桶,无论你倒进桶里的水多还是少,漏出来的水的流速也会保持稳定,这就是此算法的本质。再以 NGINX + PHP-FPM 为例,我们在 NGINX 配置里定义一个最大处理请求的速度,如果 PHP-FPM 的稳定处理速度峰值是 1000 RPS,那就在 NGINX 里定义处理请求速度最大为 1000 RPS。当 RPS 已经大于这个值的时候,多出来的请求就被 NGINX 这个桶暂时储存起来,排着队等待处理。在 NGINX 的精心照料下,PHP-FPM 会相对稳定的处理来自 NGINX 的请求,而不会出现突然暴增的请求让 PHP-FPM 处理不过来,甚至挂掉。

然而桶也有大小,NGINX 也一样,假如请求太多太多,桶都装不下了,那么桶将会把多出来的请求直接漏掉,返回 503 错误。

上面是服务器的故事,而用户那边的故事是:如果用户浏览器发起请求时,服务器的 RPS 还在 1000 以内,那就看不出什么变化;但如果发起请求的时候正好赶上访问高峰期,那么浏览器会一直等待响应,直到请求“漏”给了 PHP-FPM 处理;极端情况,如果赶上访问多得服务器无法承受时,用户就只能得到一个 503 错误。

精心呵护 PHP-FPM 避免出现因压力突然增大而导致的雪崩效应,是漏桶的一种用法。然而,没有网站愿意返回 503 错误信息给用户。为了避免 503,更正确的姿势是使用负载均衡,增加网站的横向扩展能力以扛住压力,当然,这是另外一个话题了。不过有一种访问,叫恶意访问,以不让服务器罢工不罢休为目的,这种恶意访问叫 DDOS(Distributed Denial of Service),而漏桶更多是用在防止 DDOS 攻击上。

大部分 DDOS,都属于低成本 DDOS 攻击,也就是通过一台或者几台机器,不断向服务器发起请求来实现的。我们只要给每一个 IP 设置一个“桶”,并做一个限制:每个 IP 一秒最多只能有 10 次请求,否则视为有问题的请求。在 NGINX 的配置上体现为:10 RPS,桶的大小为 0,如果一秒内有超过 10 个请求被处理,多出来的请求会立马返回 503。当然这种处理方式也是略显粗暴,配置不好会误伤小区宽带内的正常访问。

说清楚了原理,具体配置的例子如下,其中 rate 就是上面所说的 RPS,而且不仅可以设置 n r/s,也可以设置 n r/m;另外 burst 参数,就是我们的桶大小了:

# 此设置只能放在 http 节点下

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

# 被限制访问的请求,NGINX 默认返回 503 Service Unavailable,

# 但实际上请求过多往往是客户端的不正常访问造成的

# 所以返回客户端错误代码 429 Too Many Request 其实更合适

# 如果你同意此说法,将下面代码反注释即可

# limit_req_status 429;

...

# 此设置在 http, server, location 节点都可以设置;

# 设置了 nodelay 将不会等待

limit_req zone=one burst=5 [nodelay];

配置里的一些细节,这里就不多做介绍了,这些在官方的文档里面都能查得到:

2016-04-22 补充:上面说到访问频率可以设置 n r/s,或者 n r/m,可能有些人会有疑问,1 r/s 和 60 r/m 有区别吗?是否 60 r/m 意味着可以在一分钟的第一秒的时候就有 60 个正常的返回,根据我的测试,其实就是一样的效果,无论访问频率的单位是什么,最终应该都算成了“一次请求的占用时长”

df83231bee01dd4e52438731a8a0385e.png

写作累,服务器还越来越贵

求分担,祝愿好人一生平安

天使打赏人

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值