nginx做白名单和限流的完整过程

 更新时间:2024年02月19日 09:21:28   作者:SunArmy  
​ 我们都知道nginx里面是可以用lua脚本做一些稍微复杂些的逻辑处理的,要使用lua脚本需要编译lua解释器,时间有限我直接用了openresty,它集成了lua和nginx,这篇文章主要介绍了nginx做白名单和限流,需要的朋友可以参考下

在我们生产环境中使用到了地图服务,每个月有免费请求次数,近一个月请求次数突然暴涨,导致直接开启付费模式,一个月上百刀的花销着实难扛,根据实际我们的业务使用情况,远达不到付费标准,故考虑做白名单和限流措施,基于以上情况并遇到春节急需快速处理,所以选择了最简单方便的方式,通过nginx做限流

​ 我们都知道nginx里面是可以用lua脚本做一些稍微复杂些的逻辑处理的,要使用lua脚本需要编译lua解释器,时间有限我直接用了openresty,它集成了lua和nginx

一、openresty是什么?

OpenResty是一个基于Nginx的高性能Web平台,用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。具备下列特点:

具备Nginx的完整功能
基于Lua语言进行扩展,集成了大量精良的 Lua 库、第三方模块,允许使用Lua自定义业务逻辑、自定义库

二、OpenResty的安装

1、添加OpenResty仓库

# 由于公共库中找不到openresty,所以需要添加openresty的源仓库
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo

# 注意,如果上面命令提示不存在,那就先安装一下
yum install -y yum-utils

2. 安装OpenResty

# 安装openresty
yum install -y openresty
# 安装OpenResty管理工具,帮助我们安装第三方的Lua模块
yum install -y openresty-opm

3、目录结构

​ 默认安装在/usr/local/openresty

看到里面有一个nginx目录,进去可以看到跟我们平常用的nginx是一模一样的,OpenResty就是在Nginx基础上集成了一些Lua模块

到这里我们就安装好了

4. 启动和运行

OpenResty底层是基于Nginx的,查看OpenResty目录的nginx目录,结构与windows中安装的nginx基本一致:

所以这个里面的nginx和平常的nginx是一样的

1)nginx配置文件

worker_processes 1;
events {
    worker_connections 1024;
}
http {
    server{
        listen 999;
        server_name  localhost;
        location /mapbox/ {
            access_by_lua_file "/usr/local/openresty/nginx/lua_script/rule.lua";
            proxy_pass https://api.mapbox.com/;
            proxy_ssl_server_name on;
        }
    }
}

2)lua脚本文件(白名单加限流)

通过两个redis的key,map_request_limitation:存放令牌数量,map_request_white_list:白名单列表;白名单的IP,无需限流,只有白名单之外的才需要限流

-- 其实这两个值可以从redis取  甚至可以给每个qrcode设置单独的速率和容积
-- 但如果想监听桶的状态  需要持续的请求, 只有每次请求后才重新计算并更新桶状态 否则桶状态不变
local tokens_per_second = 0.2  -- 生成速率 /s
local max_tokens = 10  -- 最大溶剂
local current_time = ngx.now()
local path = ngx.var.uri
local redis_key = "map_request_limitation"
local redis_key_white_list = "map_request_white_list"
local client_ip = ngx.var.remote_addr
-- local redis_key = "path:" .. path
-- 连接Redis
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
    ngx.log(ngx.ERR, "Redis连接失败: ", err)
    return ngx.exit(500)
end
-- 权限校验
local res, err = red:auth("123456")
if not res then
    ngx.say("failed to authenticate: ", err)
    return
end
-- 发送 Lua 脚本(保证redis原子性操作)
local script = [[
    local redis_key = KEYS[1]
    local redis_white_list_key = KEYS[2]
    local tokens_per_second = tonumber(ARGV[1])
    local max_tokens = tonumber(ARGV[2])
    local current_time = tonumber(ARGV[3])
    local client_ip = ARGV[4]
    -- ip是否存在列表中
    local is_in_whitelist, err = redis.call('sismember', redis_white_list_key, client_ip)
    if is_in_whitelist == 1 then
        return 1
    end
    -- 获取上次访问时间和令牌数量
    local res = redis.call('HMGET', redis_key, 'last_access_time', 'tokens')
    local last_access_time
    local last_tokens
    if res[1] and res[2] then
	last_tokens = res[2]
	last_access_time =  res[1]
    end
    -- 计算时间间隔
    local time_passed = current_time - (tonumber(last_access_time) or 0)
    -- 计算新的令牌数量
    last_tokens = last_tokens and tonumber(last_tokens) or max_tokens
    local new_tokens = math.min(max_tokens, last_tokens + time_passed * tokens_per_second)
    -- 判断令牌数量是否足够
    if new_tokens >= 1 then
        -- 消耗令牌
        redis.call('HMSET', redis_key, 'last_access_time', current_time, 'tokens', new_tokens - 1)
        return 1
    else
        return 0
    end
]]
-- 执行脚本
local result = red:eval(script, 2, redis_key, redis_key_white_list,tokens_per_second, max_tokens,current_time,client_ip)
if result == 1 then
    -- 成功
    ngx.log(ngx.INFO, "成功")
else
    -- 令牌不足
    ngx.status = ngx.HTTP_TOO_MANY_REQUESTS
    ngx.say("OVERLOAD!!!!",result)
    return ngx.exit(ngx.HTTP_TOO_MANY_REQUESTS)
end
-- 返还redis连接到连接池
local ok, err = red:set_keepalive(10000, 100)
if not ok then
    ngx.log(ngx.ERR, err)
end

启动之后当通过这个999端口访问之后,我们在redis里面可以看到以下两个key,白名单可以自行添加,即时生效

到此这篇关于nginx做白名单和限流的文章就介绍到这了,更多相关nginx白名单和限流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Nginx已编译的nginx-添加新模块

    Nginx已编译的nginx-添加新模块

    这篇文章主要介绍了Nginx已编译的nginx-添加新模块,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Nginx限制IP并发数与下载速度的方法

    Nginx限制IP并发数与下载速度的方法

    这篇文章主要介绍了Nginx中限制IP并发数与下载速度的方法,用到了limit_zone、limit_rate和limit_conn模块,有需要的朋友参考下
    2014-01-01
  • Nginx手动编译、安装超详细教程

    Nginx手动编译、安装超详细教程

    Nginx安装除了编译以外,我们还可以直接用操作系统上自带的工具比如说yum、apt-get直接安装,这篇文章主要介绍了Nginx手动编译、安装超超详解,需要的朋友可以参考下
    2023-09-09
  • Nginx负载均衡配置简单配置方法

    Nginx负载均衡配置简单配置方法

    Nginx作为负载均衡服务器,用户请求先到达nginx,再由nginx根据负载配置将请求转发至不同的Web服务器。下面通过本文给大家分享Nginx负载均衡配置简单配置方法,需要的的朋友参考下吧
    2017-08-08
  • prometheus监控nginx的两种方式

    prometheus监控nginx的两种方式

    这篇文章主要介绍了两种不同的Nginx监控方法,第一种是nginx自带的tub_status模块进行监控,第二种是用vts监控工具进行监控,都是基于prometheus、grafana结合第三方模块或监控工具搭建,文中通过图文结合的方式介绍的非常详细,需要的朋友可以参考下
    2024-05-05
  • 通过Nginx的proxy_set_header设置请求头无效的解决

    通过Nginx的proxy_set_header设置请求头无效的解决

    这篇文章主要介绍了通过Nginx的proxy_set_header设置请求头无效的解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • 在Nginx服务器上配置Google反向代理的基本方法

    在Nginx服务器上配置Google反向代理的基本方法

    这篇文章主要介绍了在Nginx服务器上配置Google反向代理的基本方法,文中使用到了SSL来加密反向代理,需要的朋友可以参考下
    2015-12-12
  • nginx安装图解_动力节点Java学院整理

    nginx安装图解_动力节点Java学院整理

    这篇文章主要为大家详细介绍了nginx安装的图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • shell脚本定时统计Nginx下access.log的PV并发送给API保存到数据库

    shell脚本定时统计Nginx下access.log的PV并发送给API保存到数据库

    这篇文章主要介绍了shell脚本定时统计Nginx下access.log的PV并发送给API保存到数据库的实现方法 ,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • Nginx服务器中浏览器本地缓存和虚拟机的相关设置

    Nginx服务器中浏览器本地缓存和虚拟机的相关设置

    这篇文章主要介绍了Nginx服务器中浏览器本地缓存和虚拟机的相关设置,是Nginx服务器搭建过程中的基本配置,需要的朋友可以参考下
    2015-08-08

最新评论