2KB项目,专业的源码交易网站 帮助 收藏 每日签到

使用 HAProxy 基于 HTTP 头实现的速率限制

  • 时间:2019-01-23 18:32 编辑:2KB 来源:2KB.COM 阅读:527
  • 扫一扫,手机访问
  • 分享
摘要:
HAproxy 英文原文:Rate Limiting based on HTTP headers with HAProxy

最近我有一个关于第三方客户端软件升级的问题。针对我们的系统,除了那些没有有意义的请求,也还产生许许多多有用(问题)。

这篇文章的细节是我怎样把一个动态的速率限制添加进我们的HAProxy负载平衡,大量地节流仅仅是一组由于客户端bug引起的非常特定的HTTP请求导致的,即使是同样的一些URL,或者是其他请求,(系统)保持着常规的操作。

在这篇文章中的描述文件可以在GitHub仓库上轻易访问。

其它翻译版本 (1) 加载中

蜂拥时的踩踏

让事情变得有趣的情况是什么呢,客户端软件工作正常,但一个后端的同步功能重复(很无情)上传了大量的小物件,即使它们已经在后端被发送,创建了很多副本。与此同时,应用的交互部分工作良好。此外,尽管有问题的更新已分发到了大多数用户,但只有特定的使用模式才会错误,影响引发一小部分的安装。

由于高频次的请求来自于几乎没有限制的客户端,更重的异步服务器端处理起来无法跟上,导致队列缓慢且未完成请求不断增长。

而正确的队列首先应该确保大多数用户在常规工作中意识不到他们所处系统变慢,很明显,我们需要在我们后端上寻找一种解决措施,使得指定的客户端的更新能够持续和推动。

其它翻译版本 (1) 加载中

可选方案

最显而易见的解决方案是取消受影响的OAuth客户端ID的访问,但它的副作用很大。或者呢,应用停止响应所有客户端,包括那些还没有进行异常更新安装的或者还没有触发bug的。显然这不是一个好的选择。

另一个我们考虑的办法是引入一个以客户端ID作为鉴别器的速率限制。它也同样有副作用,将用户彻底所在外面,影响很多无辜的用户。基本上任何只考虑客户端账号ID的方法都会影响比理应用户更多的用户。

其它翻译版本 (1) 加载中

实施修复

我们将要实施的是一个基于用户访问令牌的速率限制配置,而不是修正客户端软件或调用针对受损客户端的特定API。这种方法本身并不是特别灵巧,而且更改实现相应HAProxy的配置比预期要难。大多数的例子是基于发送者的IP地址,但是我们不想对处于同一NAT防火墙内的用户都做一致的惩罚。

事不宜迟,下面是haproxy.cfg的一个片段:

frontend fe_api_ssl
  bind 192.168.0.1:443 ssl crt /etc/haproxy/ssl/api.pem no-sslv3 ciphers ...
  default_backend be_api
 
  tcp-request inspect-delay 5s
 
  acl document_request path_beg -i /v2/documents
  acl is_upload hdr_beg(Content-Type) -i multipart/form-data
  acl too_many_uploads_by_user sc0_gpc0_rate() gt 100
  acl mark_seen sc0_inc_gpc0 gt 0
 
  stick-table type string size 100k store gpc0_rate(60s)
 
  tcp-request content track-sc0 hdr(Authorization) if METH_POST document_request is_upload
 
  use_backend 429_slow_down if too_many_uploads_by_user mark_seen 
 
backend be_429_slow_down
  timeout tarpit 2s
  errorfile 500 /etc/haproxy/errorfiles/429.http
  http-request tarpit

让我们一一来看一下细节。

首先,紧接着前端模块的名称 fe_api_ssl ,我们绑定了需要的ip地址和端口,并且利用证书和私钥以及一组密码设置了 TLS 。

然后,我们设置了后端,将由模块 be_api 默认处理这些没有频率限制的请求。

下一行,需要tcp-request inspect-delay 来确认后续的检查所需的信息都是有效的。如果不填写,HAProxy可能会有一些告警,因为我们后续会使用到一些tcp相关的指标。 像这样设置这个delay的选项,会使得HAProxy 等待最多五秒钟来进行三次握手,直到它开始评估是否命中检查规则。若不设置,将引起一些冲突,因为规则将在第一个可能还未完成的数据包上直接应用,造成不可预计的后果。

再接下来的块代码则是包含了ACL规则的定义。这里需要重点说明一下,这些规则并不是在这里执行的。这里的ACL仅仅是为了设置的规则能生效以及被遵守。

  • document_request 用于检测被请求的资源中的path_beg是否在有包含/v2/documents/,-i 表示不区分大小写。

  • is_upload则检测头部中的Content-Type的值是否匹配multipart/form-data,同样不区分大小写。这里的Content-Type即为有问题的代码路径被执行触发异常后返回给客户端的。另外一些客户端可能接入同样的资源,但却有着不同的Content-Type。这里就不一一罗列了。

  • too_many_uploads_by_user这个规则稍微有点绕。它主要用于检测0号通用计数器(GPC)的平均增长是否在配置指定的时间段内超出100。我们稍候会再次讨论这一点。

  • mark_seen定义了在HAProxy 的执行过程中0号通用计数器应该保持增长。这里所以说的0号通用计数器即为在上述too_many_uploads_by_user检测增长率的计数器。

再下一步,我们将定义一张保存着字符串 - 对象(type string)这样映射关系的对照表,大约最大可以有100.000行。里面的字符串就是头部身份验证中的值,例如:用户接入的token(对应下一行配置)。每一个token旁边存储的值即为0号通用计数器每一分钟的增长率。

关于ACL规则的定义暂时先讲这么多。接下来我们将检测请求进来的内容(tcp-request content)。一般情况下,我们在上述中的stick-table映射表中开启了对会话身份验证的追踪。这些值被列在关键字if(默认是逻辑与)的后面。例如在当前特定的场景下,我们仅仅关注对报文类型为document_request(正如在前面ACL定义中的名字)且Content-Type(即为:is_upload ACL)正确的HTTP POST(METH_POST)请求进行追踪。

值得注意的是,到目前为止too_many_uploads_by_user和mark_seen的ACL规则还没被执行,因为他们仅仅只是声明而已。

too_many_uploads_by_user和mark_seen将会作为use_backend指令中的一部分而被执行。这里将会申请与默认后端完全不一样的后端以防命中too_many_requests_by_user ACL规则。对此为了检测全部有意义请求的所有流量,我们必须确保GPC确实是持续递增的,以便stick-table映射表为每一个用户接入的token都持有一个大于0的值。

这就是mark_seen伪ACL规则发挥作用的地方。它的唯一目的就是为追踪入口流量而增长映射表中的CPC。可能看起来这样做有点奇怪,但请记住,ACL规则定义实际上并不做任何的事情,却把配置的规则和后面将被执行的动作/检测关联起来。

事实上,无论何时只要一个进来的请求匹配满足了条件(POST方法,正确的请求路径,正确的报文类型Content-Type),计数器都会加1。如果增长率超过100次每分钟,再进来的请求就会转发到指定的be_429_slow_down后端处理。

如果进来的请求响应过慢,将会交由默认配置的后端处理。

be_429_slow_down 后端使用了所谓的tarpit特性 -- 通常用于在定义时期关掉请求前通过保持长连接来绑定相关的资源。在HTTP的tarpit选项中可以发送返回一个错误给客户端。然而,HAProxy不允许在tarpit选项中自定义的HTTP状态响应码,而是统一通常返回500。当我们需要既能缓解错误的请求,又需要提醒客户端对应具体的错误码时,我们使用了一点点黑客的技巧:通过errorfile文件,我们可以在返回500(但实际上是返回的状态码429)的情况下同时一个自定义的429.http文件。这虽然有违最佳实践,但可以很好地工作:

HTTP/1.1 429 Too Many Requests
Cache-Control: no-cache
Connection: close
Content-Type: text/plain
Retry-After: 60
 
Too Many Requests (HAP429).

更多信息,请查看: HAProxy关于errorfile的文档

结论

网上大部分关于HAProxy频率限制的例子,都是根据ip和端口来限制,没有跟高级协议相关资讯。我们需要在脑海中花一点点时间来把所有与HAProxy的计数器、stick-table 还有访问规则这些零碎信息整合起来。

上述的配置已经应用在生产环境中,并且完美地把我们的后端服务器与有问题的客户端隔离起来。如果将来我们需要其他的限制,我们也可以采用这种更细粒度而且有效的方法来处理。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部