Nginx访问频率控制

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

限制原理

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

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

实践

由于存在盲区,不知道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

nginx 访问频率控制的更多相关文章

  1. openresty开发系列37--nginx-lua-redis实现访问频率控制

    openresty开发系列37--nginx-lua-redis实现访问频率控制 一)需求背景 在高并发场景下为了防止某个访问ip访问的频率过高,有时候会需要控制用户的访问频次在openresty中, ...

  2. 基于nginx的频率控制方案思考和实践

    基于nginx的频率控制方案思考 标签: 频率控制 nginx 背景 nginx其实有自带的limit_req和limit_conn模块,不过它们需要在配置文件中进行配置才能发挥作用,每次有频控策略的 ...

  3. Nginx 访问日志轮询切割

    Nginx 访问日志轮询切割脚本 #!/bin/sh Dateformat=`date +%Y%m%d` Basedir="/application/nginx" Nginxlog ...

  4. 按日期切割nginx访问日志--及性能优化

    先谈下我们需求,一个比较大的nginx访问日志,根据访问日期切割日志,保存在/tmp目录下. 测试机器为腾讯云机子,单核1G内存.测试日志大小80M. 不使用多线程版: #!/usr/bin/env ...

  5. 一、基于hadoop的nginx访问日志分析---解析日志篇

    前一阵子,搭建了ELK日志分析平台,用着挺爽的,再也不用给开发拉各种日志,节省了很多时间. 这篇博文是介绍用python代码实现日志分析的,用MRJob实现hadoop上的mapreduce,可以直接 ...

  6. Python正则表达式,统计分析nginx访问日志

    目标: 1.正则表达式 2.oop编程,统计nginx访问日志中不同IP地址出现的次数并排序 1.正则表达式 #!/usr/bin/env python # -*- coding: utf-8 -*- ...

  7. Nginx访问控制模块

    一.Nginx访问控制模块 Nginx默认安装的模块http_access_module,可以基于来源IP进行访问控制. 1.模块安装 nginx中内置ngx_http_access_module,除 ...

  8. logstash收集nginx访问日志

    logstash收集nginx访问日志 安装nginx #直接yum安装: [root@elk-node1 ~]# yum install nginx -y 官方文档:http://nginx.org ...

  9. 使用python找出nginx访问日志中访问次数最多的10个ip排序生成网页

    使用python找出nginx访问日志中访问次数最多的10个ip排序生成网页 方法1:linux下使用awk命令 # cat access1.log | awk '{print $1" &q ...

随机推荐

  1. Spring 如何保证后置处理器的执行顺序 - OrderComparator

    Spring 如何保证后置处理器的执行顺序 - OrderComparator Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.htm ...

  2. Python之路(第二十六篇) 面向对象进阶:内置方法

    一.__getattribute__ object.__getattribute__(self, name) 无条件被调用,通过实例访问属性.如果class中定义了__getattr__(),则__g ...

  3. 博客写作的Checklist

    Checklist 1.不要发明术语. 2.不要使用指代不清的代词.如:我,他. 3.不要使用错误的承前省. 4.不要使用口语. 5.给出结论之前,先交代背景. 6.站立会议报告中应有燃尽图. 7.燃 ...

  4. SLI的相关学习

    今天帮人安装前年的机皇-微星GT80S的操作系统,安装好后用鲁大师测试下跑分,发现双显卡和单显卡鲁大师的跑分竟然一样,就像副显卡根本没有工作,听主人所这台机器能跑到36万以上. 然后就苦逼的尝试,把B ...

  5. 各种 on事件触发js代码

    [转]各种 on事件触发js代码 1.onmouseenter:当鼠标进入选区执行代码 <div style="background-color:red" onmouseen ...

  6. Python脚本语言第一行的写法

    脚本语言的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它,就这么简单 #!/usr/bin/python是告诉操作系统执行这个脚本的时候,调用/usr/bin下的python ...

  7. 2019.01.08 bzoj4543: [POI2014]Hotel加强版(长链剖分+dp)

    传送门 代码: 长链剖分好题. 题意:给你一棵树,问树上选三个互不相同的节点,使得这个三个点两两之间距离相等的方案数. 思路: 先考虑dpdpdp. fi,jf_{i,j}fi,j​表示iii子树中离 ...

  8. 2018.06.27The Windy's(费用流)

    The Windy's Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6003 Accepted: 2484 Descripti ...

  9. 下载安装mysql的一些坑

    在mysql下载安装的过程中会有一些坑,另外navicat连接mysql数据库时也存在一定的坑,总结如下: 1.计算机中丢失某个dll文件 这个问题好解决,下载个文件就搞定了,下载地址:https:/ ...

  10. 对象序列化:pickle和shelve

    import pickle class DVD: def __init__(self,tilte,year=None,duration=None,director_id=None): self.tit ...