nginx+lua+redis防刷和限流的实现

 更新时间:2023年09月05日 10:03:36   作者:laolu0837  
本文将介绍如何使用nginx lua redis实现防刷和限流,首先,我们将了解防刷和限流的基本概念和必要性,然后,我们将详细介绍如何使用nginx lua redis实现防刷和限流,感兴趣的可以了解一下

防刷的概念:

防刷的目的是为了防止有些IP来爬去我们的网页,获取我们的价格等信息。不像普通的搜索引擎,这种爬去行为我们经过统计最高每秒300次访问,平均每秒266次访问。

由于我们的网站的页面都在CDN上,导致我们的CDN流量会定时冒尖。为了防止这种情况,打算将网页页面的访问从CDN切回主站。同时开启防刷功能,目前设置一秒200次访问即视为非法,会阻止10分钟的访问。

限流的概念:

限流的目的是在大促或者流量突增期间,我们的后端服务假设某个接口能够扛住的的QPS为10000,这时候同时有20000个请求进来,经过限流模块,会先放10000个请求,其余的请求会阻塞一段时间。不简单粗暴的返回404,让客户端重试,同时又能起到流量销峰的作用。

目前防刷模块已经经过ab的压测。

限流模块经过测试后发现,请求几乎很平均的按照限流的模式进行分布,不过会有接近1%的请求超时。因为极端情况下,一个请求总是被阻塞。(目前想到的解决方案:一个请求被阻塞多次后就放行,不再需要判断当前总请求数。)

redis部署方式:
单docker实例,由marathon负责调度,无需开启rdb和aof

风险:
 redis挂了。 处理方式:直接放行。 同时,我们的mesos能够保证redis在秒级内重启。
在限流模块的时候采用了redis的eval命令来进行原子的执行,而防刷模块没有。

下面放出代码,请各位大拿指正。close_redis的代码抄自开涛的博客中相关内容。

防刷代码

-- access_by_lua_file '/opt/ops/lua/access_limit.lua'
local function close_redis(red)
    if not red then
        return
    end
    --释放连接(连接池实现)
    local pool_max_idle_time = 10000 --毫秒
    local pool_size = 100 --连接池大小
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
    if not ok then
        ngx_log(ngx_ERR, "set redis keepalive error : ", err)
    end
end
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ip = "redis-ip"
local port = redis-port
local ok, err = red:connect(ip,port)
if not ok then
    return close_redis(red)
end
local clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
   clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
   clientIP = ngx.var.remote_addr
end
local incrKey = "user:"..clientIP..":freq"
local blockKey = "user:"..clientIP..":block"
local is_block,err = red:get(blockKey) -- check if ip is blocked
if tonumber(is_block) == 1 then
   ngx.exit(ngx.HTTP_FORBIDDEN)
   return close_redis(red)
end
res, err = red:incr(incrKey)
if res == 1 then
   res, err = red:expire(incrKey,1)
end
if res > 200 then
    res, err = red:set(blockKey,1)
    res, err = red:expire(blockKey,600)
end
close_redis(red)

限流代码

-- access_by_lua_file '/opt/ops/lua/access_flow_control.lua'
local function close_redis(red)
    if not red then
        return
    end
    --释放连接(连接池实现)
    local pool_max_idle_time = 10000 --毫秒
    local pool_size = 100 --连接池大小
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
    if not ok then
        ngx_log(ngx_ERR, "set redis keepalive error : ", err)
    end
end
local function wait()
   ngx.sleep(1)
end
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ip = "redis-ip"
local port = redis-port
local ok, err = red:connect(ip,port)
if not ok then
    return close_redis(red)
end
local uri = ngx.var.uri -- 获取当前请求的uri
local uriKey = "req:uri:"..uri
res, err = red:eval("local res, err = redis.call('incr',KEYS[1]) if res == 1 then local resexpire, err = redis.call('expire',KEYS[1],KEYS[2]) end return (res)",2,uriKey,1)
while (res > 10)
do 
   local twait, err = ngx.thread.spawn(wait)
   ok, threadres = ngx.thread.wait(twait)
   if not ok then
      ngx_log(ngx_ERR, "wait sleep error: ", err)
      break;
   end
   res, err = red:eval("local res, err = redis.call('incr',KEYS[1]) if res == 1 then local resexpire, err = redis.call('expire',KEYS[1],KEYS[2]) end return (res)",2,uriKey,1)
end
close_redis(red)

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

相关文章

  • nginx配置域名访问时域名后出现两个斜杠//的解决方法

    nginx配置域名访问时域名后出现两个斜杠//的解决方法

    最近这两天重新写了一下我的个人网站,在阿里云新买了一台服务器,配置好以后出现了一个问题,就是输入域名后域名地址会自动在后面追加两个斜杆,需要的朋友可以参考下
    2020-07-07
  • Nginx服务器配置HTTPS nginx.config 配置文件(教程)

    Nginx服务器配置HTTPS nginx.config 配置文件(教程)

    下面小编就为大家分享一篇Nginx服务器配置HTTPS nginx.config 配置文件(教程),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • Nginx高可用配置实战教程之负载均衡 + 健康检查 + 动态扩展

    Nginx高可用配置实战教程之负载均衡 + 健康检查 + 动态扩展

    本文通过电商商品服务集群的实战案例,详细介绍了从零搭建Nginx高可用架构的全过程,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2017-08-08
  • Nginx反向代理springboot的jar包过程解析

    Nginx反向代理springboot的jar包过程解析

    这篇文章主要介绍了Nginx反向代理springboot的jar包过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • Nginx配置多个HTTPS域名的方法

    Nginx配置多个HTTPS域名的方法

    本篇文章主要介绍了Nginx配置多个HTTPS域名的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • 设置Nginx允许上传文件的大小的代码详解

    设置Nginx允许上传文件的大小的代码详解

    这篇文章主要给大家介绍了关于设置Nginx允许上传文件的大小的方法,文中通过示例代码介绍的非常详细,对大家学习Nginx有一定的参考学习价值,需要的朋友们下面来一起学习吧
    2024-01-01
  • 教你如何快速在CentOS7中安装Nginx

    教你如何快速在CentOS7中安装Nginx

    今天我们就只图快不图细的讲解一下如何在CentOS7系统下快速安装Nginx,本文通过图文并茂的形式给大家展示,感兴趣的朋友一起看看吧
    2021-09-09
  • nginx编译安装及常用参数详解

    nginx编译安装及常用参数详解

    这篇文章主要介绍了nginx编译安装及常用参数详解,一种是基于ansible role实现编译安装nginx以及编译安装参数详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • 阿里云Nginx配置https实现域名访问项目(图文教程)

    阿里云Nginx配置https实现域名访问项目(图文教程)

    这篇文章主要介绍了阿里云Nginx配置https实现域名访问项目(图文教程),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • 宝塔nginx部署前端页面刷新报404错误解决办法

    宝塔nginx部署前端页面刷新报404错误解决办法

    使用nginx部署前端项目是一篇非常详细的教程,旨在帮助初学者使用Nginx来部署前端项目,这篇文章主要给大家介绍了关于宝塔nginx部署前端页面刷新报404错误的解决办法,需要的朋友可以参考下
    2024-03-03

最新评论