nginx 访问频率控制

Nginx访问频率控制

HTTP服务器的吞吐率(单位时间吞吐量)一般有一个上限,尤为是普通配置的机器,在带宽够的状况下,用压测工具常常能把服务器压出翔,为了线上环境稳定性,防止恶意攻击影响到其余用户,可选择对客户端访问频率进行合理限制。html

限制原理

限制原理并不难,可一句话归纳为:“根据客户端特征,限制其访问频率”,客户端特征主要指IP、UserAgent等。使用IP比UserAgent更可靠,由于IP没法造假,UserAgent可随意伪造。node

虽然IP没法造假,但恶意人员能够利用代理,所以仅依靠限制IP访问频率并不能应对大量代理的状况,另外在限制IP访问频率时也要考虑多用户共享网络出口的状况,好比校园网、企业局域网网络之类。nginx

实践

因为存在盲区,不知道Nginx中有访问控制模块,想着本身在应用代码中使用Redis实现基于IP的访问频率控制,在准备写代码以前发现Nginx有limit_req模块可限制基于IP的访问频率,所以选择Nginx,这确定比本身实现更省事,性能也更优秀。算法

limit_req_zone

Syntax:  limit_req_zone key zone=name:size rate=rate;
Default: —
Context: http
  • key,表示做为限制的请求特征,能够包含文本与变量,IP场景使用$binary_remote_addr
  • name,zone的名称,limit_req会用到
  • size,zone的大小,1M大小在64位系统可存储8000个state(ip、count...),每次添加新state时,可能删除至多两个前60秒未使用的state,若添加新state时zone大小不够,则删除较旧的state,释放空间后依旧不够返回503
  • rate,访问速率,支持秒或者分钟为单位,但nginx内部使用毫秒追踪请求数,若是限制是10r/1s,其实是1r/100ms

limit_req

Syntax:  limit_req zone=name [burst=number] [nodelay];
Default: —
Context: http, server, location
  • name,limit_req_zone中配置的名称
  • burst,可理解为缓冲卡槽,若是设置则全部请求都经由缓冲卡槽转发给upstream,一般可并发接收的请求数为number + 1,但当number为0时会拒绝全部请求
  • nodelay,缓冲卡槽中请求转发给upstream的时机,不设置时,会按照zone的速率逐个转发,当设置为nodelay时,请求到达缓冲卡槽后会当即转发给upstream,但卡槽中的占位依旧按照频率释放

配置

理解limit_req_zonelimit_req以后,感叹这真是个好设计,也知道它背后的形象的名称:漏桶算法服务器

了解配置方式后开始实际操做,在Nginx配置中的http内添加:网络

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

在须要限制的server内添加:并发

limit_req zone=one burst=10 nodelay;

按照官方文档,2M大小在64位系统中大约可存储16000个状态数据,针对本身的我的网站足够,10r/s即1r/100ms,配合burst=10应该也OK,重启Nginx,而后使用压测工具检验一下。工具

rate、burst、nodelay的不一样特色:性能

排除其余因素,rate的大小针对同一客户端的平均吞吐率起到决定性做用,而burst与nodelay可根据业务需求选择,burst越大可接收的并发请求越多,但rate跟不上可能致使大量客户端请求超时,nodelay在rate较小时能够提高业务在瞬时的吞吐率表现网站

白名单

之因此会限制IP访问频率,主要是为了阻止外部调用者的恶意行为,但通过上述配置后,对系统内部调用者一样会有所限制,所以咱们但愿将内部调用者列入白名单内,使其不受访问频率限制。

这主要借助Nginx中的geo与map功能,经过geo将IP映射成值,而后再经过map将值映射成变量或常量,刚好limit_req_zone中若是key为''表示不对其进行频率限制,因此只须要将白名单用户的key设置为''

修改配置文件中http的内容:

geo $limit {
    default 1;
    127.0.0.1 0;     # 本机地址
    172.31.0.0/16 0; # 内网地址
}
 
map $limit $limit_key {
    0 "";
    1 $binary_remote_addr;
}

limit_req_zone $limit_key zone=one:2m rate=10r/s;

总结

至此,根据IP限制访问频率配置完成,Nginx中与limit_req相似的还有limit_conn,可用来在链接层面进行限制,同时针对limit_req还有两个配置项limit_req_statuslimit_req_log_level,前者用来设置达到限制时返回何种状态码,后者制定达到限制时的日志采用何种级别,会致使达到限制的信息出如今不一样的日志文件中。

从打算本身实现,到使用Nginx实现,感受本身的对服务器的理解还须要提高,应该从合理性角度就能够推断出Nginx包含该类功能,而不是在搜索的过程当中发现Nginx包含该功能。

ref https://amsimple.com/blog/article/47.html

相关文章
相关标签/搜索