信息安全-威胁检测日志采集-Java服务自动阶梯限流方案

618大促流量一路狂飙,作为威胁检测安全日志通路的入口,不能让程序被打挂导致服务不可用,所以我们采取阶梯的限流模型,以确保大部分流量会被处理,而不至于让程序被打挂导致大量日志丢失。

整体思路:

  1. 预先设置阶梯的限流策略并将策略加载至内存;
  2. 当每个请求进来后在spring的AOP切面中对当前这一秒钟的请求数进行累计;
  3. 累加完成后得到当前的流量大小,将当前流量大小与限流的阶梯策略进行比较;
  4. 如果满足阶梯策略,我们对流量进行处理,要么放行,要么直接返回达到限流的目的;

 程序启动时初始化限流策略

 限流处理流程

流量累加

看下流量累加的代码

package com.ikong.demo.service.limiter;

import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

@Component
public class TrafficMonitorWindow {

    private AtomicLong time = new AtomicLong(new Date().getTime());

    private AtomicInteger count = new AtomicInteger(0);
    
    private final Integer interval = 1000;//每秒
    
    private static Object lockObj = new Object();


    /*
     * 计算每秒钟的流量
     */
    public Integer trafficIncrement() { 
        
        long now = new Date().getTime();
        
        if (now > time.get() + interval) {

            synchronized (lockObj) {

                if (now > time.get() + interval) { //如果当前时钟已经过1秒,则以当前时间点为基准,切换时钟,注意这里并不是以自然秒钟为单位,而是以有流量的那个时刻来计算的
            
                    time.compareAndSet(time.get(), now);
            
                    count.compareAndSet(count.get(), 0);
            
                }
            }
        }

        count.getAndIncrement();

        return count.get();
    }

    public Integer getCount() {

        return count.get();
    
    }
}

限流策略实体类

package com.ikong.demo.service.limiter;


public class LimitingStrategy {

    private Integer limit;//限流阈值
    private Integer rate; //丢弃率

    public Integer getLimit() {
        return limit;
    }

    public void setLimit(Integer limit) {
        this.limit = limit;
    }

    public Integer getRate() {
        return rate;
    }

    public void setRate(Integer rate) {
        this.rate = rate;
    }
}

丢弃计算

判断流量是否需要丢弃:limiter:为丢弃率,当limiter=20时,丢弃率为20%,做一个简单的随机算法,随机100以内的数,如果小于20则丢弃,否则放行

package com.ikong.demo.service.limiter;

public class TrafficDiscard {

    public boolean discard(int limiter) {

        Random random = new Random();
    
        int v = random.nextInt(100);
    
        return v < limiter ;
    }
}

丢弃策略配置


limiter.switch=true #是否限流的开关

limiter.max=40000 # 这里是限流阈值

limiter.strategys[0].limit=70 //这里是超过max=40000的70%后,将超过部分按20%丢弃率进行丢弃
limiter.strategys[0].rate=20

limiter.strategys[1].limit=80 //这里是超过max=40000的80%后,将超过部分按50%丢弃率进行丢弃
limiter.strategys[1].rate=50

limiter.strategys[2].limit=100 //这里是超过max=40000的100%后,将超过部分全部丢弃
limiter.strategys[2].rate=100

流量值高效命中策略

关键的问题我们如何高效快速定位当前流量命中哪个策略

items  = limiter.strategys;
max = limiter.max;

for (int j = 1; j < max * item.get(0).getLimit() / 100; j++) {
    cache.put(j, 0);
}

for (int i = 0; i < items.size() - 1; i++) {
    for (int j = max * items.get(i).getLimit() / 100; j < max * items.get(i + 1).getLimit() / 100; j++) {
        cache.put(j, items.get(i).getRate());
    }
}

for (int i = max; i < 150000; i++) {
    cache.put(i, items.get(items.size() - 1).getRate());
}

大体的思路:

  1. 先讲策略拆分成,[0,70),[70,80),[80,100),[100,15w),4个区间,默认单机请求量极限值不超过15w,超过服务器会宕机;
  2. 针对4个区间,每一个请求流量大小都把对应的策略放到内存中;
  3. 当计算完当前流量值后,按流量值直接在内存中取出对应的策略用于计算;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码者人生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值