高并发下一些常用的限流和防刷方法

本文探讨了在高并发环境下,如何通过Nginx、lua和redis实现限流与防刷。介绍了Nginx的IP限流、令牌桶算法以及结合Lua对不同接口的计数限流。此外,还提到了使用Lua和redis动态管理黑名单IP来进一步防止恶意访问。
摘要由CSDN通过智能技术生成

限流与防刷
互联网项目与传统项目不同的互联网项目是暴露在互联网中,面向的是全体网民,这时候可能出现以下两种访问形式需要我们采取一些必要措施对我们的服务进行保护。
1、大量正常用户高频访问导致服务器宕机
2、恶意用户高频访问导致服务器宕机
3、网页爬虫
对于这些情况我们需要对用户的访问进行限流访问,我们可以依次对Nginx、tomcat、接口进行限流。
Nginx是粒度最大的一层,这层的频度设置我们需要谨慎操作,这里将影响我们整个网站访问,Nginx层的频度设置应该在我们应用服务器宕机阀值之下,下面我们看下具体怎么设置
Nginx限流设置
对IP/域名限流

http {
     limit_conn_zone $binary_remote_addr zone=perip :10m; # 保存IP的缓存为10M;16000个IP地址的状态信息约1MB
     limit_conn_zone $server_name zone=perserver:10m;
     ...
     server {
       limit_conn perserver 100;# 此域名下最多有100个连接
       limit_conn perip 10;# 一个IP最多有10个连接
         ...
     }
}
# $binary_remote_addr 要限流的IP地址
# $server_name 要限流的域名
location / {
        limit_req zone=perip burst=20 nodelay;# urst排队大小,nodelay不限制单个请求间的时间
        proxy_pass http://XXX.com;
}
# 限流白名单
geo $limit {
    default   1;
    192.168.2.0/24  0;# 192.168.2.1-192.168.2.254 且子网掩码是255.255.255.0 网段不限流
    # 24 表示子网掩码 255.255.255.0
    # 16 表示子网掩码 255.255.0.0
    # 8 表示子网掩码 255.0.0.0
}

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

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

location / {
        limit_req zone=perid burst=1 nodelay;
        proxy_pass http://XXXX.com;
}

令牌算法限流(摘自https://blog.csdn.net/sunnyyoona/article/details/51228456
令牌桶算法最初来源于计算机网络。在网络传输数据时,为了防止网络拥塞,需限制流出网络的流量,使流量以比较均匀的速度向外发送。令牌桶算法就实现了这个功能,可控制发送到网络上数据的数目,并允许突发数据的发送。
这里写图片描述
算法描述:

  • 假如用户配置的平均发送速率为r,则每隔1/r秒一个令牌被加入到桶中(每秒会有r个令牌放入桶中);

  • 假设桶中最多可以存放b个令牌。如果令牌到达时令牌桶已经满了,那么这个令牌会被丢弃;

  • 当一个n个字节的数据包到达时,就从令牌桶中删除n个令牌(不同大小的数据包,消耗的令牌数量不一样),并且数据包被发送到网络;

  • 如果令牌桶中少于n个令牌,那么不会删除令牌,并且认为这个数据包在流量限制之外(n个字节,需要n个令牌。该数据包将被缓存或丢弃);

  • 算法允许最长b个字节的突发,但从长期运行结果看,数据包的速率被限制成常量r。对于在流量限制外的数据包可以以不同的方式处理:(1)它们可以被丢弃;(2)它们可以排放在队列中以便当令牌桶中累积了足够多的令牌时再传输;(3)它们可以继续发送,但需要做特殊标记,网络过载的时候将这些特殊标记的包丢弃。

注意:
令牌桶算法不能与另外一种常见算法漏桶算法相混淆。这两种算法的主要区别在于漏桶算法能够强行限制数据的传输速率,而令牌桶算法在能够限制数据的平均传输速率外,还允许某种程度的突发传输。在令牌桶算法中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。
结合Lua对不同接口计数限流
例如应用每秒限制100个请求

http {
    local shared_data = ngx.shared.dict
    shared_data:set("draw", 0)

    content_by_lua_block {
        local request_uri = ngx.var.request_uri;
        if string.sub(request_uri,1,22) == "/activity/lottery/draw" then
              local val, err = ngx.shared.dict:incr("draw", 1); #进来一个请求就加1
              if val > 100 then #限流100
                  ngx.log(ngx.ERR,"draw limit val is:"..val)
                  ngx.exit(503)
              end
              ....业务处理
        end
    }
...
  log_by_lua_block{
        local request_uri = ngx.var.request_uri;
        if string.sub(request_uri,1,22) == "/activity/lottery/draw&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值