如何基于阈值百分比与请求数增强混沌工程API请求攻击触发逻辑
混沌工程攻击逻辑增强实现方案
1. 新增可配置属性与全局变量
首先将两个新增参数做成可配置项,同时引入线程安全的计数变量,保证多请求场景下逻辑准确:
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; @Component public class ChaosMethodInterceptor implements MethodInterceptor { // 原有混沌开关配置 @Value("${chaos.profile.enabled:false}") private boolean chaosProfileEnabled; // 新增可配置参数,默认值对应需求里的10、50% @Value("${chaos.assault.request-limit:10}") private int requestLimit; @Value("${chaos.assault.threshold-percentage:50}") private int thresholdPercentage; // 窗口请求计数器 private final AtomicInteger currentRequestCount = new AtomicInteger(0); // 存储当前窗口需要触发攻击的请求位置 private Set<Integer> triggerPositions = new HashSet<>(); private final Object windowLock = new Object(); // 原有攻击类注入 @Resource private ExceptionAssault exceptionAssault; }
2. 重写invoke核心逻辑
实现固定窗口内按比例随机触发的逻辑,这里采用预生成触发位置的方案,保证每个窗口刚好命中设定的攻击数量,不会出现比例偏差:
@Override public Object invoke(MethodInvocation invocation) throws Throwable { // 保留原有逻辑:混沌开关未开启直接走业务流程 if (!chaosProfileEnabled) { return invocation.proceed(); } int currentSeq = currentRequestCount.incrementAndGet(); int maxTriggerCount = (int) (requestLimit * thresholdPercentage / 100.0); // 窗口请求数达到阈值,重置窗口生成新的随机触发位置 if (currentSeq > requestLimit) { synchronized (windowLock) { // 双重校验避免多线程同时重置窗口 if (currentRequestCount.get() > requestLimit) { currentRequestCount.set(1); currentSeq = 1; triggerPositions.clear(); // 预生成当前窗口需要触发攻击的请求序号 ThreadLocalRandom random = ThreadLocalRandom.current(); while (triggerPositions.size() < maxTriggerCount) { triggerPositions.add(random.nextInt(requestLimit) + 1); } } else { currentSeq = currentRequestCount.incrementAndGet(); } } } // 当前请求落在触发位置则执行攻击 if (triggerPositions.contains(currentSeq)) { exceptionAssault.execute(); } // 无论是否触发攻击都继续执行业务逻辑,若要攻击后中断可在此处直接抛出异常 return invocation.proceed(); }
3. 注意事项
- 上述实现是单实例级别计数,若需要多实例全局统一触发比例,可将计数和触发位置存储到Redis中即可
- 如果不需要严格保证每个窗口刚好命中固定数量,可以简化逻辑,直接每次请求生成0-99的随机数,小于阈值且当前窗口触发次数未达上限就触发,性能会更高
- 若使用Spring Cloud配置中心,可在配置类上加
@RefreshScope实现参数动态刷新,无需重启服务即可调整攻击比例和窗口大小
内容的提问来源于stack exchange,提问作者Praveen
相关产品推荐
相关产品推荐

