在我们的例子中,队列中的第20个数据包等待2秒钟被转发,此时对其的响应可能对客户端不再有用。 要解决这种情况,请将nodelay参数与burst参数一起添加:
通过nodelay参数,Nginx仍然根据burst参数在队列中分配时隙,并且强加配置的速率限制,但是不排除转发排队的请求。 相反,当请求到达“太快”时,Nginx会立即转发,只要队列中有一个可用的时隙。 它将该插槽标记为“已占用”,并且不会将其释放以供其他请求使用,直到经过适当的时间(在本例中为100毫秒之后)。
假设像以前一样,20个时隙的队列是空的,21个请求同时从给定的IP地址到达。 Nginx立即转发所有21个请求,并将队列中的20个插槽标记为已占用,然后每100毫秒释放1个插槽(如果有25个请求,Nginx会立即转发21个插槽,标记20个插槽,拒绝4个请求状态503 )。
现在假设在第一组请求之后101毫秒被转发,另外20个请求同时到达。 队列中只有1个插槽被释放,所以Nginx转发1个请求,并拒绝其他19个状态为503的队列。 如果在20个新请求到达之前经过了501毫秒,那么5个空闲空间,所以Nginx立即转发5个请求,拒绝15个请求。
效果相当于每秒10个请求的速率限制。 如果您希望在不限制请求之间的允许间隔的情况下施加速率限制,则nodelay选项非常有用。
注意:对于大多数部署,我们建议将burst和nodelay参数包含到limit_req指令中。
高级配置示例
通过将基本速率限制与其他Nginx功能相结合,您可以实现更多细微的流量限制。
白名单
此示例显示如何对不在“白名单”上的任何人的请求施加速率限制。
这个例子使用了geo和map指令。 geo块为白名单中的IP地址分配一个0值到$limit值,其他0 1 。 然后,我们使用地图将这些值转换为一个密钥,以便:
如果$limit是0,$limit_key设置为空字符串。
如果$limit是1,则$limit_key以二进制格式设置为客户端的IP地址。
把两者放在一起,$limit_key被设置为白名单IP地址的空字符串,否则设置为客户端的IP地址。 当limit_req_zone目录(密钥)的第一个参数为空字符串时,限制不适用,因此列入白名单的IP地址(在10.0.0.0/8和192.168.0.0/24子网中)不受限制。 所有其他IP地址每秒限制为5个请求。
limit_req指令将限制应用于/位置,并且允许在配置的限制上突发多达10个分组而没有转发延迟
在一个位置包含多个limit_req指令
您可以在一个位置包含多个limit_req指令。 所有与给定请求匹配的限制都被应用,这意味着使用最严格的限制。 例如,如果多于一个指令施加延迟,则使用最长的延迟。 同样,如果这是任何指令的影响,即使其他指令允许它们通过,请求也会被拒绝。