nginx实现ip限流的具体示例

 更新时间:2024年07月24日 09:28:33   作者:xiaohezi  
限流的方式油很多种,本文主要介绍了nginx实现ip限流的具体示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

说到限流,大家一定能想到很多算法,比如  令牌桶 、漏桶 、计数器限流、 信号量 等等。 解决方案也有很多,以 java 为例,Guava 库中的 RateLimiter 类 可以实现,Semaphore 类也可以实现。再复杂点儿,比如你是一个分布式微服务系统,可以上 Hystrix、Resilience4j 这种现成的方案。

从系统架构上来说,无非是在单体应用的当前进程中实现,还是分布式应用的非当前进程中之实现。当然还有另一种方案,就是不在业务应用中实现,而是把这种跟业务不那么紧耦合的功能抽象出去,在网络层面对所有进入系统的请求进行统一的限流控制,这种方式的好处是可以避免每个微服务都实现自己的限流逻辑。

现在很多 API 网关,尤其是新晋的 “云原生” 网关都具备这个功能(基本是标配),比如:Zuul、Kong、Ambassador、APISIX 等。

我们先不论系统是不是分布式微服务的,就单说限流这个事儿,其实也完全可以用 API 网关的思路来实现。就是我不用非要把代码写在应用中,如果我就是不想改代码呢?我想随时调整个限流策略还得重启应用? 应用那么重,生效时间那么长,我可不想重启!

所以我们回头看看自己架构中的这些软件,一定能想到这位老朋友 Nginx 。当然无论是原味的 Nginx 还是跟它有血缘关系的 openResty 都一样。

想像一下,用 nginx 配置一下然后nginx -s reload 就能搞定了,岂不痛快 ?!

正题

下文我们开始介绍在 nginx 怎么配置能实现针对某些(讨厌的)ip 进行限流,且不影响系统正常运行。 (感叹:nginx 是个好东西!!!)

可能有些朋友看到标题就已经开始写 prompt 了,喝着 coffee 等着 AI 给你一行行输出答案,然后心里想:“什么年代了,大哥,还用写个文章专门说这事儿吗?你得学会用工具呀” 。

我想说的是,关于这个问题 AI 能给你回答对 90% 的内容,剩下的 10% 你得自己改。开发同学都知道 ,别说 10% 了,0.1% 不对,程序也不 work 呀。我是不会告诉你我花了一下午时间跟 AI 都聊了什么的。

你也别抬杠说我用的工具不对,市面上但凡有的我都用了,真不行,所以我觉得还是值得写一下的。

配置详解

其实改的地方不多,首先我们要在 nginx 默认配置文件的 http 下面配置:

geo $limit_ip {
        default 0;  # 默认为 0,表示不受限制
        1.2.3.4 1;  # 需要被限制的 IP
        # 添加更多需要限制的 IP 地址
    }

    map $limit_ip $limit_key {
      0 "";
      1 $binary_remote_addr;
    }

    # 定义限流区域
    limit_req_zone $limit_key zone=mylimit:10m rate=2r/s;

我们解释一下。

geo 指令:

geo 名字来源于“geographic”,意指地理位置。但是值得注意的是,geo 指令实际上只基于 IP 地址进行匹配,而 IP 地址与地理位置之间的映射需要额外的数据库或服务来提供。许多第三方服务和数据库(如 MaxMind GeoIP、GeoLite2 等)可以用来更精确地将 IP 地址转换为地理位置信息。

解释一下我们上文中中 geo 的配置:

  • geo $limit_ip { ... }:定义了一个名为 $limit_ip的变量,用于根据客户端 IP 地址设置不同的值。
  • default 0;:默认情况下,如果客户端 IP 地址不在列表中,$limit_ip 的值为 0。
  • 1.2.3.4 1;:如果客户端 IP 地址是 1.2.3.4,则 $limit_ip 的值为 1。这里的 1 是一个标记,表示这个 IP 地址需要被限制。

总结来说就是用 geo 指令标记需要限制的 IP 地址

map 指令:

  • map $limit_ip $limit_key { ... }:根据$limit_ip的值来设置另一个变量$limit_key。
  • 0 "";:如果$limit_ip的值为 0(即默认情况),则$limit_key的值为空字符串。
  • 1 $binary_remote_addr;:如果$limit_ip的值为 1(即被标记的 IP 地址),则$limit_key的值为客户端 IP 地址的二进制形式($binary_remote_addr)。

不知道聪明的你看出来没有,我们这里其实设置的是 “黑名单” (即我想限制哪些 ip 我就配置哪些,剩下的不限制),在 geo 配置的 ip 到了 map 这里以后,将这些 IP 地址映射到了一个变量上,即 limit_key 。如果你想设置白名单(即我想让哪些 ip 不被限制我就配置哪些,剩下的都限制)不就是反过来操作嘛。

举个白名单的例子:

geo $limit {
    default 1;
    10.0.0.0/8 0;
    192.168.0.0/24 0;
    172.20.0.35 0;
}
map $limit $limit_key {
    0 "";
    1 $binary_remote_addr;
}

limit_req_zone

接着是整块配置的最后一行。

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

使用 limit_req_zone 指令定义了一个限流区域,对标记的 IP 地址进行请求速率限制。如果一个 IP 地址不在 geo 指令中定义,则不受限制。如果一个 IP 地址被标记,则它的请求速率会被限制在每秒 2 个请求。

  • $limit_key:使用$limit_key 变量作为限流的键。
  • zone=mylimit:10m:设置共享内存区域的大小为 10MB,用于存储限流信息。
  • rate=2r/s:设置每个键值(即每个 IP 地址)的请求速率限制为每秒 2 个请求。

其实这些指令都有一些详细参数,简单起见,我就不介绍了,都有 AI 了,需要的话自己查吧。我们说点儿重点。
我猜你可能关心  zone=mylimit  里面到底是什么样的,里面到底有啥 。是的,这很重要,了解清楚 zone 的结构很关键,关于 zone 的数据我没细看过,但结构大致类似这样:

{
  "mylimit": {
    "123.124.210.242": {
      "current": 0,  // 当前请求计数
      "last": 1618305483,  // 上次请求的时间戳
      "tokens": 2,  // 当前令牌桶中的令牌数
      "delay": 0  // 由于限流导致的延迟(秒)
    },
    // ... 其他被限流的 IP 地址信息
    "192.168.1.100": {
      "current": 1,
      "last": 1618305495,
      "tokens": 1,
      "delay": 0
    }
  }
}

好了,到这里我们第一部分的配置就结束了,是不很简单? 然后我们进行第二部分的配置,也很简单。

前文我们第一部分的配置只是定义了一个限流的策略,我们还没应用呢呀。所以我们要在需要的地方把它用起来。

很简单,在需要限流的 location 中这样写:

location /abc/api {
       limit_req zone=mylimit;
  }

没了? 就一句?

对,没了。是不很简单?简单到我都不想解释,如果你理解了前文你就懂了,我就不解释了。毕竟你会用 AI 不是。

然后你就可以重新加载配置,或重启 nginx 了。再然后你就要耐心等待和观察,等待之前那些讨厌的恶意 ip 再次造访,顺利地话你会在 nginx 的 error 日志中看到类似这样的信息 :

... [error] ..limiting requests,excess:0.996 by zone "mylimit", client:1.2.3.4 ...

到此这篇关于nginx实现ip限流的具体示例的文章就介绍到这了,更多相关nginx ip限流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Nginx四层负载均衡的实现示例

    Nginx四层负载均衡的实现示例

    Nginx 不支持传统的四层负载均衡,但可以通过stream模块配合TCP实现类似的功能,本文主要介绍了Nginx四层负载均衡的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • Centos下编译安装Nginx教程详解

    Centos下编译安装Nginx教程详解

    这篇文章主要介绍了Centos下编译安装Nginx的教程详解,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-12-12
  • nginx实现动静分离的方法示例

    nginx实现动静分离的方法示例

    Nginx的静态处理能力很强,但是动态处理能力不足,因此,在企业中常用动静分离技术,本文就详细的介绍一下如何使用,感兴趣的可以了解一下
    2021-11-11
  • Nginx静态资源服务器的实现示例

    Nginx静态资源服务器的实现示例

    静态资源即非服务器动态生成的文件,本文主要介绍了Nginx静态资源服务器的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-08-08
  • nginx部署https网站的实现步骤(亲测)

    nginx部署https网站的实现步骤(亲测)

    本文详细介绍了使用Nginx在保持与http服务兼容的情况下部署HTTPS,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-02-02
  • Nginx 403 forbidden错误的原因以及解决方法

    Nginx 403 forbidden错误的原因以及解决方法

    yum安装nginx,安装一切正常,但是访问时报403 forbidden,下面这篇文章主要给大家介绍了关于Nginx 403 forbidden错误的原因以及解决方法,需要的朋友可以参考下
    2022-08-08
  • Nginx动态IP黑名单的实现步骤

    Nginx动态IP黑名单的实现步骤

    为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单,本文主要介绍了Nginx动态IP黑名单的实现步骤,具有一定的参考价值,感兴趣的可以了解一下
    2025-02-02
  • Nginx安装及配置详细分析

    Nginx安装及配置详细分析

    这篇文章主要介绍了Nginx在各种系统和环境中的安装及配置详细分析。
    2017-11-11
  • nginx访问路径映射资源目录的实现

    nginx访问路径映射资源目录的实现

    本文主要介绍了nginx访问路径映射资源目录,Nginx映射资源目录是指在Nginx配置文件中设定规则,使得当客户端向Nginx服务器发送请求访问某个URL时,Nginx能够将该URL映射到服务器本地的实际文件目录,感兴趣的可以了解一下
    2024-06-06
  • Nginx配置WebSocket代理的示例代码

    Nginx配置WebSocket代理的示例代码

    本文提供了关于Nginx的配置和日志记录的详细指南,介绍了如何使用whereis命令查找Nginx路径,并通过man命令查看手册,同时,详解了解Nginx访问日志的配置方法及参数含义,并分享了Nginx代理WebSocket的配置示例,感兴趣的可以了解一下
    2024-10-10

最新评论