精华内容
下载资源
问答
  • 详解Nginx限流配置

    2021-01-10 08:05:22
    本文以示例的形式,由浅入深讲解Nginx限流相关配置,是对简略的官方文档的积极补充。 Nginx限流使用的是leaky bucket算法,如对算法感兴趣,可移步维基百科先行阅读。不过不了解此算法,不影响阅读本文。 空桶 我们...
  • 一般对外暴露的系统,在促销或者黑客攻击时会涌来大量的请求,为了保护系统不被瞬间到来的高并发流量给打垮, 就需要限流,这篇文章主要介绍了nginx限流方案的实现,非常具有实用价值,需要的朋友可以参考下
  • 主要介绍了Nginx源码研究之nginx限流模块详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Nginx限流

    2020-07-19 15:48:52
    nginx限流的作用 一、限制访问频率(正常流量) Nginx中我们使用 ngx_http_limit_req_module模块来限制请求的访问频率,基于漏桶算法原理实现。接下来我们使用 nginx limit_req_zone 和 limit_req 两个指令,限制...

    来源:https://www.cnblogs.com/biglittleant/p/8979915.html
    作者:biglittleant

    nginx限流的作用

    一、限制访问频率(正常流量)

    Nginx中我们使用 ngx_http_limit_req_module模块来限制请求的访问频率,基于漏桶算法原理实现。接下来我们使用 nginx limit_req_zone 和 limit_req 两个指令,限制单个IP的请求处理速率。
    在这里插入图片描述
    语法:limit_req_zone key zone rate

    • key :定义限流对象,binary_remote_addr 是一种key,表示基于 remote_addr(客户端IP)
      来做限流,binary_ 的目的是压缩内存占用量。
    • zone:定义共享内存区来存储访问信息, myRateLimit:10m 表示一个大小为10M,名字为myRateLimit的内存区域。1M能存储16000 IP地址的访问信息,10M可以存储16W, IP地址访问信息。
    • rate 用于设置最大访问速率,rate=10r/s 表示每秒最多处理10个请求。Nginx 实际上以毫秒为粒度来跟踪请求信息,因此10r/s 实际上是限制:每100毫秒处理一个请求。这意味着,自上一个请求处理完后,若后续100毫秒内又有请求到达,将拒绝处理该请求。

    展开全文
  • nginx限流

    2020-06-16 00:17:03
    nginx限流欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右...

    1.nginx与apache的对比

    1.1nginx

    1. 轻量级,采用 C 进行编写,同样的 web 服务,会占用更少的内存及资源
    2. 抗并发,nginx 以 epoll and kqueue 作为开发模型,处理请求是异步非阻塞的,负载能力比 apache 高很多,而 apache 则是阻塞型的。在高并发下 nginx 能 保持低资源低消耗高性能 ,而 apache 在 PHP 处理慢或者前端压力很大的情况下,很容易出现进程数飙升,从而拒绝服务的现象。
    3. nginx 处理静态文件好,静态处理性能比 apache 高三倍以上
    4. nginx 的设计高度模块化,编写模块相对简单
    5. nginx 配置简洁,正则配置让很多事情变得简单,而且改完配置能使用 -t 测试配置有没有问题,apache 配置复杂 ,重启的时候发现配置出错了,会很崩溃
    6. nginx 作为负载均衡服务器,支持 7 层负载均衡
    7. nginx 本身就是一个反向代理服务器,而且可以作为非常优秀的邮件代理服务器
    8. 启动特别容易, 并且几乎可以做到 7*24 不间断运行,即使运行数个月也不需要重新启动,还能够不间断服务的情况下进行软件版本的升级
    9. 社区活跃,各种高性能模块出品迅速

    1.2 apache

    1. apache 的 rewrite 比 nginx 强大,在 rewrite 频繁的情况下,用 apache
    2. apache 发展到现在,模块超多,基本想到的都可以找到
    3. apache 更为成熟,少 bug ,nginx 的 bug 相对较多
    4. apache 超稳定
    5. apache 对 PHP 支持比较简单,nginx 需要配合其他后端用
    6. apache 在处理动态请求有优势,nginx 在这方面是鸡肋,一般动态请求要 apache 去做,nginx 适合静态和反向。
    7. apache 仍然是目前的主流,拥有丰富的特性,成熟的技术和开发社区

    1.2 总结

    两者最核心的区别在于 apache 是同步多进程模型,一个连接对应一个进程,而 nginx 是异步的,多个连接(万级别)可以对应一个进程
    一般来说,需要性能的 web 服务,用 nginx 。如果不需要性能只求稳定,更考虑 apache ,后者的各种功能模块实现得比前者,例如 ssl 的模块就比前者好,可配 置项多。epoll(freebsd 上是 kqueue ) 网络 IO 模型是 nginx 处理性能高的根本理由,但并不是所有的情况下都是 epoll 大获全胜的,如果本身提供静态服务的就只 有寥寥几个文件,apache 的 select 模型或许比 epoll 更高性能。当然,这只是根据网络 IO 模型的原理作的一个假设,真正的应用还是需要实测了再说的。

    2.nginx常用模块了解及使用

    Nginx的各种指令以及配置繁多,有些配置可以在如下的链接 https://tengine.taobao.org/nginx_docs/cn/docs/ 或者在官方文档上查看 nginx常用模块介绍 对于nginx的其余模块可以通过在nginx安装的时候通过./configure指定 可以通过 ./configure --help 命令查看,当然有很多模块默认安装的

    3.限流模块

    比如:抢购的场景,下载限速下就会有涉及运用 限流:主要是当访问量达到一个限制量的时候可以选择以服务器为主要,而选择对用户访问请求的量做限制,对于超出限制的用户请求会采取丢弃或者延迟处理等 方式处理,来保证更多用户来访问处理。

    比如:某一服务器正常在高峰期上能支持的访问量是1w,但是突然某一时刻在访问量上突然暴增一下子超过3w,5w则可能会导致服务器宕机,这个时候我们 就可以通过设置最大的访问如1分钟访问8000次;

    也可以防止攻击(对同一个ip每秒访问多少次)如:30min/次 对应模块:

    ngx_http_limit_conn_module限制连接数
    ngx_http_limit_reg_module限制请求频率

    3.1 ngx_http_limit_reg_module限制请求频率

    4. nginx内置变量说明

    Nginx 同 Apache 和 Lighttpd 等其他 Web 服务器的配置记法不太相同, Nginx 的配置文件使用语法的就是一门微型的编程语言。可以类似写程序一般编写 配置文件,可操作性很大。既然是编程语言,一般也就少不了“变量”这种东西。 所有的 Nginx 变量在 Nginx 配置文件中引用时都须带上 $ 前缀在 Nginx 配置中,变量只能存放一种类型的值,有且也只存在一种类型,那就是字符串类型 使用 set 配置指令对变量 $a 进行了赋值操作 set $hello “hello world” ; Nginx 变量一旦创建,其变量名的可见范围就是整个 Nginx 配置,甚至可以跨越不同虚拟主机的 server 配置块 Nginx 变量名的可见范围虽然是整个配置,但每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,彼此互不干扰 Nginx 内置变量 内置变量存放在 ngx_http_core_module 模块中

    参参数数名名称称注释释
    $arg_PARAMETER HTTP请求中某个参数的值,如/index.php?site=www.ttlsa.com,可以用$arg_site取得www.ttlsa.com这个值.
    $args HTTP$12
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1
    $binary_remote_addr$1

    5. ip黑白名单

    连接限制跟请求限制,会对所有的ip进行限制,我们不希望自己的测试的ip,或者搜索引擎蜘蛛受到限制 根据上面的速率限制的问题:

    limit_req_zone $binary_remote_addr zone=testz:10m rate=1r/s; limit_conn_zone $binary_remote_addr zone=addr:10m;

    目前的情况是针对于所有的请求均会有做限制,而在业务中可能会存在这对于某一些ip是不做限制的需求;在nginx的配置中并不能直接对于变量编辑相应的逻辑 计算因此我们不得不需要换一个方式

    5.1 ngx_http_geo_module

    ngx_http_geo_module模块创建变量,并根据客户端IP地址对变量赋值

    语法: geo [$address] $variable { … }
    默认值: —

    http {// .. geo $whiteIpList { default 1; 192.168.169.139 0; 192.168.169.160 0; include ip/whiteIp.conf; }server { // .. location /geo { return 200 '$whiteIpList'; } } }

    5.2 ngx_http_map_module

    ngx_http_map_module可以根据我们传递的参数

    语法: map string $variable { … }
    默认值: — 上下文: http

    使用方面和geo的方式类似
    需要值得注意的是

    limit_req_zone $binary_remote_addr zone=testz:10m rate=1r/s; limit_conn_zone $binary_remote_addr zone=addr:10m;

    5.3 jmter使用

    6 rewrite模块(ngx_http_rewrite_module)

    展开全文
  • Nginx 限流

    2020-04-14 10:09:22
    限流算法 令牌桶算法 算法思想是: 令牌以固定速率产生,并缓存到令牌桶中; 令牌桶放满时,多余的令牌被丢弃; 请求要消耗等比例的令牌才能被处理; 令牌不够时,请求被缓存。 漏桶算法 算法思想是: 水(请求...

    来源:https://www.cnblogs.com/biglittleant/p/8979915.html
    作者:biglittleant

    限流算法

    令牌桶算法
    在这里插入图片描述
    算法思想是:

    • 令牌以固定速率产生,并缓存到令牌桶中;
    • 令牌桶放满时,多余的令牌被丢弃;
    • 请求要消耗等比例的令牌才能被处理;
    • 令牌不够时,请求被缓存。

    漏桶算法

    在这里插入图片描述
    算法思想是:

    • 水(请求)从上方倒入水桶,从水桶下方流出(被处理);
    • 来不及
    展开全文
  • 为什么要互联网项目要限流 在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;而降级是当服务出问题或者影响到核心...

     

    为什么要互联网项目要限流

    在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,待高峰或者问题解决后再打开;而有些场景并不能用缓存和降级来解决,比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询(评论的最后几页),因此需有一种手段来限制这些场景的并发/请求量,即限流。

    互联网雪崩效应解决方案

    服务降级: 在高并发的情况, 防止用户一直等待,直接返回一个友好的错误提示给客户端。

    服务熔断:在高并发的情况,一旦达到服务最大的承受极限,直接拒绝访问,使用服务降级。

    服务隔离: 使用服务隔离方式解决服务雪崩效应

    服务限流: 在高并发的情况,一旦服务承受不了使用服务限流机制(计时器(滑动窗口计数)、漏桶算法、令牌桶(Restlimite))

     

    高并发限流解决方案

    高并发限流解决方案限流算法(令牌桶、漏桶、计数器)

    限流算法

    常见的限流算法有:令牌桶、漏桶。计数器也可以进行粗暴限流实现。

    计数器

      它是限流算法中最简单最容易的一种算法,比如我们要求某一个接口,1分钟内的请求不能超过10次,我们可以在开始时设置一个计数器,每次请求,该计数器+1;如果该计数器的值大于10并且与第一次请求的时间间隔在1分钟内,那么说明请求过多,如果该请求与第一次请求的时间间隔大于1分钟,并且该计数器的值还在限流范围内,那么重置该计数器

    这种方式有个弊端,可能会产生临界的问题,见上图,假如第59秒进行了10个请求,61秒的时候又进行了10个请求,这20个请求都会执行成功,如果在临界的时候突然有大量请求,可能会违背定义固定速率。解决方法是使用滑动窗口计数器。

     

    /**
    
     * 功能说明: 纯手写计数器方式<br>
    
     */
    
    public class LimitService {
    
    
    
          private int limtCount = 60;// 限制最大访问的容量
    
          AtomicInteger atomicInteger = new AtomicInteger(0); // 每秒钟 实际请求的数量
    
          private long start = System.currentTimeMillis();// 获取当前系统时间
    
          private int interval = 60;// 间隔时间60秒
    
    
    
          public boolean acquire() {
    
                long newTime = System.currentTimeMillis();
    
                if (newTime > (start + interval)) {
    
                      // 判断是否是一个周期
    
                      start = newTime;
    
                      atomicInteger.set(0); // 清理为0
    
                      return true;
    
                }
    
                atomicInteger.incrementAndGet();// i++;
    
                return atomicInteger.get() <= limtCount;
    
          }
    
    
    
          static LimitService limitService = new LimitService();
    
    
    
          public static void main(String[] args) {
    
    
    
                ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
    
                for (int i = 1; i < 100; i++) {
    
                      final int tempI = i;
    
                      newCachedThreadPool.execute(new Runnable() {
    
    
    
                           public void run() {
    
                                 if (limitService.acquire()) {
    
                                       System.out.println("你没有被限流,可以正常访问逻辑 i:" + tempI);
    
                                 } else {
    
                                       System.out.println("你已经被限流呢  i:" + tempI);
    
                                 }
    
                           }
    
                      });
    
                }
    
          }
    
    
    
    }

    滑动窗口计数

     

     

    滑动窗口计数有很多使用场景,比如说限流防止系统雪崩。相比计数实现,滑动窗口实现会更加平滑,能自动消除毛刺。

    滑动窗口原理是在每次有访问进来时,先判断前 N 个单位时间内的总访问量是否超过了设置的阈值,并对当前时间片上的请求数 +1。

      令牌桶算法

    令牌桶算法是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。令牌桶算法的描述如下:

    假设限制2r/s(每秒钟放2个令牌),则按照500毫秒的固定速率往桶中添加令牌;

    桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝;

    当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上;

    如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。

     

    使用RateLimiter实现令牌桶限流

    RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率。

    通常可应用于抢购限流防止冲垮系统;限制某接口、服务单位时间内的访问量,譬如一些第三方服务会对用户访问量进行限制;限制网速,单位时间内只允许上传下载多少字节等。

    下面来看一些简单的实践,需要先引入guava的maven依赖。

     

    <parent>
    
                <groupId>org.springframework.boot</groupId>
    
                <artifactId>spring-boot-starter-parent</artifactId>
    
                <version>2.0.0.RELEASE</version>
    
          </parent>
    
          <dependencies>
    
                <dependency>
    
                      <groupId>org.springframework.boot</groupId>
    
                      <artifactId>spring-boot-starter-web</artifactId>
    
                </dependency>
    
                <dependency>
    
                      <groupId>com.google.guava</groupId>
    
                      <artifactId>guava</artifactId>
    
                      <version>25.1-jre</version>
    
                </dependency>
    
          </dependencies>

    使用RateLimiter 实现令牌桶算法

    /**
    
     * 功能说明:使用RateLimiter 实现令牌桶算法
    
     *
    
     */
    
    @RestController
    
    public class IndexController {
    
          @Autowired
    
          private OrderService orderService;
    
          // 解释:1.0 表示 每秒中生成1个令牌存放在桶中
    
          RateLimiter rateLimiter = RateLimiter.create(1.0);
    
    
    
          // 下单请求
    
          @RequestMapping("/order")
    
          public String order() {
    
                // 1.限流判断
    
                // 如果在500秒内 没有获取不到令牌的话,则会一直等待
    
                System.out.println("生成令牌等待时间:" + rateLimiter.acquire());
    
                boolean acquire = rateLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
    
                if (!acquire) {
    
                      System.out.println("你在怎么抢,也抢不到,因为会一直等待的,你先放弃吧!");
    
                      return "你在怎么抢,也抢不到,因为会一直等待的,你先放弃吧!";
    
                }
    
    
    
                // 2.如果没有达到限流的要求,直接调用订单接口
    
                boolean isOrderAdd = orderService.addOrder();
    
                if (isOrderAdd) {
    
                      return "恭喜您,抢购成功!";
    
                }
    
                return "抢购失败!";
    
          }
    
    
    
    }

     

    漏桶算法

    漏桶作为计量工具(The Leaky Bucket Algorithm as a Meter)时,可以用于流量整形(Traffic Shaping)和流量控制(TrafficPolicing),漏桶算法的描述如下:

    一个固定容量的漏桶,按照常量固定速率流出水滴;

    如果桶是空的,则不需流出水滴;

    可以以任意速率流入水滴到漏桶;

    如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。

    令牌桶和漏桶对比:

    令牌桶是按照固定速率往桶中添加令牌,请求是否被处理需要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求;

    漏桶则是按照常量固定速率流出请求,流入请求速率任意,当流入的请求数累积到漏桶容量时,则新流入的请求被拒绝;

    令牌桶限制的是平均流入速率(允许突发请求,只要有令牌就可以处理,支持一次拿3个令牌,4个令牌),并允许一定程度突发流量;

    漏桶限制的是常量流出速率(即流出速率是一个固定常量值,比如都是1的速率流出,而不能一次是1,下次又是2),从而平滑突发流入速率;

    令牌桶允许一定程度的突发,而漏桶主要目的是平滑流入速率;

    两个算法实现可以一样,但是方向是相反的,对于相同的参数得到的限流效果是一样的。

    另外有时候我们还使用计数器来进行限流,主要用来限制总并发数,比如数据库连接池、线程池、秒杀的并发数;只要全局总请求数或者一定时间段的总请求数设定的阀值则进行限流,是简单粗暴的总数量限流,而不是平均速率限流。

     

     

    一个固定的漏桶,以常量固定的速率流出水滴。

    如果桶中没有水滴的话,则不会流出水滴

    如果流入的水滴超过桶中的流量,则流入的水滴可能会发生溢出,溢出的水滴请求是无法访问的,直接调用服务降级方法,桶中的容量是不会发生变化。

     

     

    漏桶算法与令牌桶算法区别

      ​    主要区别在于“漏桶算法”能够强行限制数据的传输速率,而“令牌桶算法”在能够限制数据的平均传输速率外,还允许某种程度的突发传输。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。

     

    封装RateLimiter

    自定义注解封装RateLimiter.实例:

     

    @RequestMapping("/myOrder")
    
    @ExtRateLimiter(value = 10.0, timeOut = 500)
    
    public String myOrder() throws InterruptedException {
    
                System.out.println("myOrder");
    
                return "SUCCESS";
    
    }

     

    自定义注解

    @Target(value = ElementType.METHOD)
    
    @Retention(RetentionPolicy.RUNTIME)
    
    public @interface ExtRateLimiter {
    
          double value();
    
    
    
          long timeOut();
    
    }

    编写AOP

    @Aspect
    
    @Component
    
    public class RateLimiterAop {
    
          // 存放接口是否已经存在
    
          private static ConcurrentHashMap<String, RateLimiter> rateLimiterMap = new ConcurrentHashMap<String, RateLimiter>();
    
    
    
          @Pointcut("execution(public * com.itmayeidu.api.*.*(..))")
    
          public void rlAop() {
    
          }
    
    
    
          @Around("rlAop()")
    
          public Object doBefore(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    
                MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
    
                // 使用Java反射技术获取方法上是否有@ExtRateLimiter注解类
    
                ExtRateLimiter extRateLimiter = signature.getMethod().getDeclaredAnnotation(ExtRateLimiter.class);
    
                if (extRateLimiter == null) {
    
                      // 正常执行方法
    
                      Object proceed = proceedingJoinPoint.proceed();
    
                      return proceed;
    
                }
    
                // ############获取注解上的参数 配置固定速率 ###############
    
                // 获取配置的速率
    
                double value = extRateLimiter.value();
    
                // 获取等待令牌等待时间
    
                long timeOut = extRateLimiter.timeOut();
    
                RateLimiter rateLimiter = getRateLimiter(value, timeOut);
    
                // 判断令牌桶获取token 是否超时
    
                boolean tryAcquire = rateLimiter.tryAcquire(timeOut, TimeUnit.MILLISECONDS);
    
                if (!tryAcquire) {
    
                      serviceDowng();
    
                      return null;
    
                }
    
                // 获取到令牌,直接执行..
    
                Object proceed = proceedingJoinPoint.proceed();
    
                return proceed;
    
    
    
          }
    
    
    
          // 获取RateLimiter对象
    
          private RateLimiter getRateLimiter(double value, long timeOut) {
    
                // 获取当前URL
    
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    
                HttpServletRequest request = attributes.getRequest();
    
                String requestURI = request.getRequestURI();
    
                RateLimiter rateLimiter = null;
    
                if (!rateLimiterMap.containsKey(requestURI)) {
    
                      // 开启令牌通限流
    
                      rateLimiter = RateLimiter.create(value); // 独立线程
    
                      rateLimiterMap.put(requestURI, rateLimiter);
    
                } else {
    
                      rateLimiter = rateLimiterMap.get(requestURI);
    
                }
    
                return rateLimiter;
    
          }
    
    
    
          // 服务降级
    
          private void serviceDowng() throws IOException {
    
                // 执行服务降级处理
    
                System.out.println("执行降级方法,亲,服务器忙!请稍后重试!");
    
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    
                HttpServletResponse response = attributes.getResponse();
    
                response.setHeader("Content-type", "text/html;charset=UTF-8");
    
                PrintWriter writer = response.getWriter();
    
                try {
    
                      writer.println("执行降级方法,亲,服务器忙!请稍后重试!");
    
                } catch (Exception e) {
    
    
    
                } finally {
    
                      writer.close();
    
                }
    
    
    
          }
    
    
    
          public static void main(String[] args) {
    
                // 使用Java反射技术获取方法上是否有@ExtRateLimiter注解类
    
                ExtRateLimiter extRateLimiter = IndexController.class.getClass().getAnnotation(ExtRateLimiter.class);
    
                System.out.println(extRateLimiter);
    
          }
    
    
    
    }

    接入层限流

     

    接入层通常指请求流量的入口,该层的主要目的有:负载均衡、非法请求过滤、请求聚合、缓存、降级、限流、A/B测试、服务质量监控等等。

    Nginx官方版本限制IP的连接和并发分别有两个模块:

    • limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 "leaky bucket"。
    • limit_req_conn 用来限制同一时间连接数,即并发限制。

    limit_req_zone 参数配置

    Syntax:	limit_req zone=name [burst=number] [nodelay];
    Default:	—
    Context:	http, server, location
    

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

    • 第一个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址。
    • 第二个参数:zone=one:10m表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息。
    • 第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还可以有比如30r/m的。

    limit_req zone=one burst=5 nodelay;

    • 第一个参数:zone=one 设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应。
    • 第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。
    • 第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。

    例子:

    http {
        limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
        server {
            location /search/ {
                limit_req zone=one burst=5 nodelay;
            }
    }        
    

    下面配置可以限制特定UA(比如搜索引擎)的访问:

    limit_req_zone  $anti_spider  zone=one:10m   rate=10r/s;
    limit_req zone=one burst=100 nodelay;
    if ($http_user_agent ~* "googlebot|bingbot|Feedfetcher-Google") {
        set $anti_spider $http_user_agent;
    }
    

    其他参数

    Syntax:	limit_req_log_level info | notice | warn | error;
    Default:	
    limit_req_log_level error;
    Context:	http, server, location
    

    当服务器由于limit被限速或缓存时,配置写入日志。延迟的记录比拒绝的记录低一个级别。例子:limit_req_log_level notice延迟的的基本是info。

    Syntax:	limit_req_status code;
    Default:	
    limit_req_status 503;
    Context:	http, server, location
    

    设置拒绝请求的返回值。值只能设置 400 到 599 之间。

    ngx_http_limit_conn_module 参数配置

    这个模块用来限制单个IP的请求数。并非所有的连接都被计数。只有在服务器处理了请求并且已经读取了整个请求头时,连接才被计数。

    Syntax:	limit_conn zone number;
    Default:	—
    Context:	http, server, location
    
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    
    server {
        location /download/ {
            limit_conn addr 1;
        }
    

    一次只允许每个IP地址一个连接。

    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $server_name zone=perserver:10m;
    
    server {
        ...
        limit_conn perip 10;
        limit_conn perserver 100;
    }
    

    可以配置多个limit_conn指令。例如,以上配置将限制每个客户端IP连接到服务器的数量,同时限制连接到虚拟服务器的总数。

    Syntax:	limit_conn_zone key zone=name:size;
    Default:	—
    Context:	http
    
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    

    在这里,客户端IP地址作为关键。请注意,不是$ remote_addr,而是使用$ binary_remote_addr变量。 $ remote_addr变量的大小可以从7到15个字节不等。存储的状态在32位平台上占用32或64字节的内存,在64位平台上总是占用64字节。对于IPv4地址,$ binary_remote_addr变量的大小始终为4个字节,对于IPv6地址则为16个字节。存储状态在32位平台上始终占用32或64个字节,在64位平台上占用64个字节。一个兆字节的区域可以保持大约32000个32字节的状态或大约16000个64字节的状态。如果区域存储耗尽,服务器会将错误返回给所有其他请求。

    Syntax:	limit_conn_log_level info | notice | warn | error;
    Default:	
    limit_conn_log_level error;
    Context:	http, server, location
    

    当服务器限制连接数时,设置所需的日志记录级别。

    Syntax:	limit_conn_status code;
    Default:	
    limit_conn_status 503;
    Context:	http, server, location
    

    设置拒绝请求的返回值。

    实战

    实例一 限制访问速率

     

    limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;
    
    
    
    server {
    
      location /login/ {
    
        limit_req zone=ip_limit;
    
        proxy_pass http://login_upstream;
    
      }
    
    }

     

    • $binary_remote_addr 针对客户端ip限流;
    • zone=ip_limit:10m 限流规则名称为ip_limit,允许使用10MB的内存空间来记录ip对应的限流状态;
    • rate=10r/s 限流速度为每秒10次请求
    • location /login/ 对登录进行限流

      漏桶漏出请求是匀速的。10r/s是怎样匀速的呢?每100ms漏出一个请求。

      在这样的配置下,桶是空的,所有不能实时漏出的请求,都会被拒绝掉。

      所以如果10次请求同时到达,那么只有一个请求能够得到执行,其它的,都会被拒绝。

      这不太友好,大部分业务场景下我们希望这10个请求都能得到执行。

    实例二 burst缓存处理 

    limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;
    
    server {
      location /login/ {
        limit_req zone=ip_limit burst=12;
        proxy_pass http://login_upstream;
      }
    }

    burst=12 漏桶的大小设置为12

    逻辑上叫漏桶,实现起来是FIFO队列,把得不到执行的请求暂时缓存起来。

    这样漏出的速度仍然是100ms一个请求,但并发而来,暂时得不到执行的请求,可以先缓存起来。只有当队列满了的时候,才会拒绝接受新请求。

    这样漏桶在限流的同时,也起到了削峰填谷的作用。

    在这样的配置下,如果有10次请求同时到达,它们会依次执行,每100ms执行1个。

    虽然得到执行了,但因为排队执行,延迟大大增加,在很多场景下仍然是不能接受的。

    实例三 nodelay降低排队时间

    延续实例二的配置,我们加入nodelay选项:

    limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;
    
    server {
      location /login/ {
        limit_req zone=ip_limit burst=12 nodelay;
        proxy_pass http://login_upstream;
      }
    }

     nodelay 把开始执行请求的时间提前,以前是delay到从桶里漏出来才执行,现在不delay了,只要入桶就开始执行。

    要么立刻执行,要么被拒绝,请求不会因为限流而增加延迟了。

    提高了处理效率,提高了“瞬时处理速度”,平均速度还是受rate限制。当burst满了后不会继续排队等待,直接丢弃。

     

    展开全文
  • Nginx 限流熔断

    2021-09-10 17:27:30
    nginx 限流熔断 令牌桶算法 思想 : 令牌以固定速率产生 , 并缓存到令牌桶中 令牌桶放慢时 , 多余的令牌被丢弃 请求要消耗等比例的令牌才能被处理 令牌不够时, 请求被缓存 漏桶算法 思想 : 将请求放入 “漏...
  • 限流配置(nginx.conf) 配置说明 limit_req_zone 这个变量只能在HTTP中使用,limit_req_zone,用来限制请求的频率。 $binary_remote_addr 限制的关键词 可以是 IP 或 虚拟服务 这里是ip限制 zone=per...
  • nginx限流方案

    2019-11-12 16:47:12
    Nginx自身有的请求限制模块ngx_http_limit_req_module、流量限制模块ngx_stream_limit_conn_module基于令牌桶算法,可以方便的控制令牌速率,自定义调节限流,实现基本的限流控制。 对于提供下载的网...
  • 实战:使用Nginx限流

    2020-07-10 20:18:54
    Nginx不仅可以做Web服务器、做反向代理、负载均衡,还可以做限流系统。此处我们就Nginx为例,介绍一下如何配置一个限流系统。 Nginx使用的限流算法是漏桶算法。 (1)是安装NginxNginx的安装我们在8.5.7中已经...
  • Nginx限流配置记录

    2020-10-13 17:45:30
    nginx限流配置 nginx限流算法 令牌桶算法 令牌以固定速率产生,并缓存到令牌桶中; 令牌桶放满时,多余的令牌被丢弃; 请求要消耗等比例的令牌才能被处理; 令牌不够时,请求被缓存 漏桶算法 水(请求)从...
  • Tomcat和nginx限流

    2021-09-27 17:16:04
    https://www.cnblogs.com/linjiqin/p/9600590.html https://www.cnblogs.com/crazymakercircle/p/11748214.html
  • 一般对外暴露的系统,在促销或者黑客攻击时会涌来大量的请求,为了保护系统不被瞬间到来的高并发流量给打垮, 就需要限流,这篇文章主要介绍了nginx限流方案的实现,非常具有实用价值,需要的朋友可以参考下 ...
  • 一般对外暴露的系统,在促销或者黑客攻击时会涌来大量的请求,为了保护系统不被瞬间到来的高并发流量给打垮, 就需要...接下来通过本文给大家分享使用nginx实现分布式限流的方法,感兴趣的朋友跟随脚本之家小编一起学习吧
  • nginx限流配置

    千次阅读 2019-12-16 11:41:45
    说明:此处nginx的安装略,主要做一下nginx常用限流配置内容。限流方式主要有以下两种,安装选其中一种即可。 一、单位时间访问限流QPS: 说明: 使用nginx的 ngx_http_limit_req_module模块进行限制的,使用limit_...
  • nginx限流 在http设置中添加限流的设置,20r/s 每个ip每秒允许20次访问。 设置完成后再需要限流的接口中调用该设置。 http{ limit_req_zone $uri zone=api_read:20m rate=20r/s; } server{ location /test/api { ...
  • nginx 限流

    千次阅读 2019-04-21 18:01:51
    nginx限流算法(漏桶算法) 漏桶算法(Leaky Bucket)是网络世界中流量整形(Traffic Shaping)或速率限制(Rate Limiting)时经常使用的一种算法,它的主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏...
  • 3.Nginx实现限流的方式 3.1 模块介绍 3.2 模块指令实战 1.设置共享内存区域和允许的最大并发数。当超过此限制时,服务器将返回错误以响应请求。由ngx_http_limit_conn_module模块提供此功能。 2.对单个ip进行...
  • lua脚本nginx限流

    2020-02-13 20:42:01
    #使用指定限流配置,burst=4表示允许同时有4个并发连接,如果不能同时处理,则会放入队列,等请求处理完成后,再从队列中拿请求 #nodelay 并行处理所有请求 limit_req zone=contentRateLimit burst=4 nodelay; #...
  • [nginx源码]nginx限流模块详解

    千次阅读 2018-09-26 18:01:07
    1.限流算法 1.1计数器 1.2 漏桶算法 1.3 令牌桶算法 2.nginx基础知识 2.1HTTP请求处理过程 2.2 nginx事件处理简单介绍 3. ngx_http_limit_req_module模块解析 3.1配置指令 3.2源码解析 3.2.1数据结构 ...
  • 一文搞懂Nginx限流(简单实现)

    千次阅读 2019-07-12 10:26:17
    Nginx现在已经是最火的负载均衡之一,在流量陡增的互联网面前,接口限流也是很有必要的,尤其是针对高并发的场景。Nginx限流主要是两种方式:限制访问频率和限制并发连接数。 限流(rate limiting)是NGINX众多...
  • nginx限流配置.docx

    2019-11-06 11:50:04
    nginx 实现对ip的限流
  • 实现多维度限流限流算法计数器漏桶算法令牌桶算法限流方案具体实现网关限流redis+luaNginx限流 限流算法 计数器 计数器比较简单粗暴,比如我们限制的是1s能够通过的请求数,实现的思路就是从第一个请求进来开始计时...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 42,753
精华内容 17,101
关键字:

nginx限流

友情链接: 设置分辨率.rar