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

限流与防刷
互联网项目与传统项目不同的互联网项目是暴露在互联网中,面向的是全体网民,这时候可能出现以下两种访问形式需要我们采取一些必要措施对我们的服务进行保护。
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,
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Golang是一种开源的编程语言,它具有高效、简洁和并发性强的特点,非常适合用于构建高性能的网络应用程序。在Golang中,可以使用一些库和技术来实现IP防刷限流的功能。 一种常见的方法是使用令牌桶算法来进行限流。令牌桶算法基于一个令牌桶,其中包含了一定数量的令牌。每当有请求到达时,就会从令牌桶中取出一个令牌,如果令牌桶中没有足够的令牌,则请求会被拒绝或者延迟处理。这种方式可以有效地控制请求的速率,防止恶意刷接口或者DDoS攻击。 在Golang中,可以使用一些第三方库来实现令牌桶算法。例如,可以使用"golang.org/x/time/rate"包来实现基于令牌桶的限流功能。该包提供了Rate类型,可以用于定义每秒允许通过的请求数量,并且可以使用Allow方法来判断是否允许处理请求。 下面是一个简单的示例代码,演示了如何使用"golang.org/x/time/rate"包来实现IP防刷限流: ```go package main import ( "fmt" "net" "net/http" "time" "golang.org/x/time/rate" ) func main() { // 创建一个限流器,每秒允许通过3个请求 limiter := rate.NewLimiter(3, 1) // 创建一个HTTP服务器 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { // 获取请求的IP地址 ip, _, _ := net.SplitHostPort(r.RemoteAddr) // 判断是否允许处理请求 if limiter.Allow() { // 允许处理请求 fmt.Fprintf(w, "Hello, World!") } else { // 请求被限流 http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests) } }) // 启动HTTP服务器 http.ListenAndServe(":8080", nil) } ``` 在上面的示例代码中,我们创建了一个限流器,每秒允许通过3个请求。然后,在处理HTTP请求时,我们获取请求的IP地址,并使用限流器判断是否允许处理请求。如果允许处理请求,则返回"Hello, World!";如果请求被限流,则返回429 Too Many Requests错误。 这只是一个简单的示例,实际应用中可能需要更复杂的逻辑来判断是否需要限流,例如根据不同的IP地址或者用户身份进行不同的限制。同时,还可以结合其他技术,如缓存、分布式限流等来提高系统的稳定性和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值