黑名单限流

黑名单机制的重要性

  1. 区分临时限流和永久限制:

    临时限流:当请求速率超过设定的阈值时,系统会暂时拒绝请求,并记录被拒绝的次数。
    黑名单机制:当被拒绝的次数达到预设的黑名单阈值时,系统会将该请求来源加入黑名单,并在一段时间内禁止其访问。

  2. 防止恶意攻击:

    黑名单机制可以有效防止恶意用户或脚本持续高频次地访问系统,从而保护系统免受DDoS攻击或其他形式的滥用。

  3. 提高系统稳定性:

    通过区分临时限流和永久限制,系统可以更平滑地处理流量波动,避免因突发流量导致系统崩溃。

import com.google.common.util.concurrent.RateLimiter;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

@Aspect
@Component
public class RateLimiterAspect {

    private final ConcurrentHashMap<String, RateLimiter> limiters = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, Integer> blacklists = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, Long> blacklistExpiry = new ConcurrentHashMap<>();

    @Around("@annotation(RateLimiterAccessInterceptor)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RateLimiterAccessInterceptor annotation = method.getAnnotation(RateLimiterAccessInterceptor.class);

        String key = annotation.key();
        double permitsPerSecond = annotation.permitsPerSecond();
        double blacklistCount = annotation.blacklistCount();
        String fallbackMethod = annotation.fallbackMethod();

        // 检查是否在黑名单中
        if (isBlacklisted(key)) {
            return invokeFallbackMethod(joinPoint, fallbackMethod);
        }

        RateLimiter rateLimiter = limiters.computeIfAbsent(key, k -> RateLimiter.create(permitsPerSecond));

        if (rateLimiter.tryAcquire()) {
            return joinPoint.proceed();
        } else {
            blacklists.put(key, blacklists.getOrDefault(key, 0) + 1);
            if (blacklists.get(key) >= blacklistCount) {
                // 加入黑名单逻辑
                addToBlacklist(key);
                return invokeFallbackMethod(joinPoint, fallbackMethod);
            }
            return invokeFallbackMethod(joinPoint, fallbackMethod);
        }
    }

    private boolean isBlacklisted(String key) {
        Long expiryTime = blacklistExpiry.get(key);
        if (expiryTime != null && System.currentTimeMillis() < expiryTime) {
            return true;
        }
        // 如果黑名单过期,移除黑名单记录
        blacklistExpiry.remove(key);
        blacklists.remove(key);
        return false;
    }

    private void addToBlacklist(String key) {
        blacklistExpiry.put(key, System.currentTimeMillis() + 24 * 60 * 60 * 1000); // 黑名单有效期24小时
    }

    private Object invokeFallbackMethod(ProceedingJoinPoint joinPoint, String fallbackMethod) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Class<?> clazz = method.getDeclaringClass();
        Method fallback = clazz.getMethod(fallbackMethod, signature.getParameterTypes());
        return fallback.invoke(joinPoint.getTarget(), joinPoint.getArgs());
    }
}

package cn.bugstack.types.annotations;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface RateLimiterAccessInterceptor {

    /** 用哪个字段作为拦截标识,未配置则默认走全部 */
    String key() default "all";

    /** 限制频次(每秒请求次数) */
    double permitsPerSecond();

    /** 黑名单拦截(多少次限制后加入黑名单)0 不限制 */
    double blacklistCount() default 0;

    /** 拦截后的执行方法 */
    String fallbackMethod();

}

  1. 黑名单检查:

    isBlacklisted(key):检查请求来源是否在黑名单中。如果在黑名单中且未过期,则直接调用fallbackMethod。

  2. 限流逻辑:

    rateLimiter.tryAcquire():尝试获取一个令牌。如果成功,表示请求未被限流,继续执行方法;如果失败,表示请求被限流。
    blacklists.put(key, blacklists.getOrDefault(key, 0) + 1):将被限流的请求次数加1,并记录在blacklists中。 if (blacklists.get(key) >= blacklistCount):检查被限流的请求次数是否达到预设的黑名单阈值。如果达到阈值,执行加入黑名单逻辑,并调用fallbackMethod方法进行处理。

  3. 加入黑名单逻辑:

    addToBlacklist(key):将请求来源加入黑名单,并设置黑名单过期时间(如24小时)。

总结
黑名单机制在限流失败后仍然有其重要性,因为它可以区分临时限流和永久限制,防止恶意攻击,并提高系统稳定性。通过在限流逻辑中加入黑名单检查和加入黑名单的逻辑,可以更灵活地应对不同程度的流量冲击,保护系统免受滥用和攻击。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@淡 定

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

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

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

打赏作者

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

抵扣说明:

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

余额充值