极客专栏《Nginx 核心知识 100 讲》55-56 小节的笔记
55 | preaccess 阶段: 对连接做限制的 limit_conn 模块
在 preaccess 阶段限制用户并发连接数的 limit_conn 模块. 上一节讲到匹配 location, 匹配到之后, 接下来的模块往往它们的指令都可以出现在 location 中. preaccess 阶段中有两个模块 limit_req,limit_conn. 一个是用来限制每秒处理请求数, 一个是限制并发连接数.
问题: 如何限制每个客户端的并发链接数
image.PNG
使用了共享内存. 接下来会看到它用到了一个 zone 指令. 所有的 nginx 的 zone 指令都是在分配共享内存.
限制有效性取决于关键字的设计. 比如我们限制客户端的并发连接数. 而我们的 nginx 之前有 SLB, 通过 realip 模块取到用户真实 ip. 根据这个 ip 再来做并发连接数限制.
limit_conn 指令
image.PNG
limit_conn 指令的 number 是可以允许并发连接数. 这些并发连接数是根据 key(往往取自于用户 IP,remote_addr) 来定的.
image.PNG
例子
image.PNG
当 nginx 作为资源服务器为用户提供使用时, 限制用户发起的并发连接数是比较常用的功能. limit_conn 模块设计好它的 key 是个关键.
留言问题
1.rate 这个指标设置多大合适呢, 有没有什么参考值, 另外 burst 这个桶设置多大合适呢
作者回复
rate 需要匹配产品设计策略, 或者结合运营收入和运维带宽成本来分析. burst 设置多大合适, 只与产品设计和场景有关, 没有统一参考值的.
2. 在 limit_conn_zone $binary_remote_addr zone=perip:10m; 配置中, 如果共享区域内存耗尽, Nginx 文档上说回对所有请求都返回错误, 那么, 如何监测此类情况呢
作者回复
可以使用第 38 课介绍过的 slab_stat, 监控 fails 指标以及共享内存 slab 已用量
3. 多台 nginx 的时候, 如何限制并发连接数?
作者回复
跨主机通讯? nginx 模块并不支持, 你可以考虑 openresty+Redis 的方案, 其中 Redis 集群作中心存储, key 是客户端标识, value 是当前并发连接数.
4. 请问在您的例子里, 严格的来讲, 是第一个请求还未结束, 第二个請求又发起的时候, 并发连接数为 2 对吗?
作者回复
对的
56 | preaccess 阶段: 对请求做限制的 limit_req 模块
问题: 如何限制每个客户端的每秒处理请求数?
image.PNG
Leaky Bucket
image.PNG
突发性的流量, 右上角那副图. 横轴是以秒为单位, 纵轴是每秒传输的流量. 前两秒中都是 12Mbps,2-7 秒钟没有流量, 7-10 每秒 2Mbps. 这种突发流量使用了 Leaky Bucket 以后就变成了右下角的那副图了, 每秒 3Mbps. 累加起来的值跟右上图是一致的. 左图形象的说明了这个操作.
当盆满了还在滴水就立刻给用户返回 503. 但没有满的时候, 下面的流速达到最大化, 水滴就存在盆里. 用户的请求就在变慢, 而不是被拒绝.
limit_req 指令
image.PNG
burst=number 盆里可以容纳多少个请求. nodelay 意义, 当设置了 nodelay,burst 里面的请求就会立即返回错误.
image.PNG
例子
image.PNG
image.PNG
rate=2r/m. 每分钟处理两个请求. 之所以加这样的限制是为了更快的看到效果.
image.PNG
image.PNG
image.PNG
limit_conn 跟 limit_req 都打开之后看下, 返回的是 500 还是 503?limit_req 是在 limit_conn 之前. 所以, limit_req 已经拒绝用了 limit_conn 就得不到执行.
留言问题
我对生效范围是全部 work 进程还不是很理解.
这样问您: 比如总共有 10 个模块被编译进了二进制文件, nginx 启动时, 先启动 master 进程, master 进程然后启动多个 work 进程.
这多个 work 进程的工作任务是同样的吗? 或者他们分别负责不同的工作, 比如第一个 work 负责前五个模块的工作, 第二个 work 负责后五个的工作?
作者回复
每个 worker 进程是等效的, 功能完全相同. 多 worker 进程的意义在于使用多 CPU, 第 5 部分内容会详细介绍. 由内核调度 worker 进程, 决定把哪些连接交给哪个 worker 进程处理.
2. 请问怎么获取 post 请求中的参数值呢, 我想通过 post 请求参数进行限流.:-)
作者回复
根据请求中的 body 么? 这样不行, 你没办法利用 preaccess 阶段的模块了, 因为这些模块工作时, 只能确保接收到完整的 url 参数和 http header, 是否接收到完整的 body 中的 form 完全无法保证
3. 在视频 5 分钟作用的时候, 您的配置文件是 2r/m, 然后用 curl limit.taohui.tech 连续发了 2 条请求, 然后第二条请求返回 503, 为啥不是第三条返回 503, 第二条就 503 了呢? 我的理解里面发第 2 条请求的时候是满足 2r/m 的
作者回复
可能是视频剪辑时剪辑掉啦, 你的理解是对的:-)
3. 老师你好 WAF 这种过滤规则在哪个阶段
作者回复
多数 lua waf 都是在 access 阶段工作的
4. 限制请求和连接的 ip 是指 tcp 层的请求的 ip 吧, 如果 ngnix 前面加了 WAF 和负载均衡, 对这个有没有影响呢?
作者回复
不是哦, 你可以再看一下第 50 课里的 realip 模块, 这个 ip 可以不是 tcp 层中的 remote ip, 而是 http request header 中的 xforwarded-for 或者 x-realip 头部的内容
5.limit_** 指令中的 key 究竟是什么意思呢? 它和限制的数量有什么关系? 比如说 key 是用户 ip,limit_conn 是 2, 就表示每个不同的用户只能同时有两个连接到服务器吗?
作者回复
是的
来源: http://www.jianshu.com/p/944375d27e55