chaos monkey for spring boot

一.源码地址

https://github.com/codecentric/chaos-monkey-spring-boot.git

二.目录结构

  1. assaults包下是四种攻击方式,分为两类ChaosMonkeyRequestAssault和ChaosMonkeyRuntimeAssault.一个时请求攻击,另一个是应用运行时攻击(可以接口调用,也可以定时任务调用)
  2. compoent包下定义了两个scope,和一个定时器,还有使用micrometer记录java应用性能的自定义三个雷
  3. condition包下是@condition的自定义条件类
  4. configuration包下 是yml配置里的接收类,下面会详细解说
  5. endpoint 都是自定义的endpoint可以监控chaosmonkey的状态以及修改它的配置
  6. events包下就封装了一个事件类MetricEvent用户micrometer
  7. wacher包下都是aop,会去切controller,service,respository等,注意一个请求如果经历三层的话,chaosmonkey会生效三次,所以最好设置service层比较好.

三.源码

(1). ExceptionAssault,AssaultException​​​​​

    @Override
    public void attack() {
        LOGGER.info("Chaos Monkey - exception");

        AssaultException assaultException = this.settings.getAssaultProperties().getException();

        // metrics
        if (metricEventPublisher != null)
            metricEventPublisher.publishMetricEvent(MetricType.EXCEPTION_ASSAULT);

        assaultException.throwExceptionInstance();
    }
调用了AssaultException的throwExceptionInstance,根据配置通过反射创建异常实例;
@JsonIgnore @SneakyThrows
public void throwExceptionInstance() {
    Exception instance;
    try {
        Class<? extends Exception> exceptionClass = getExceptionClass();
        if (arguments == null) {
            Constructor<? extends Exception> constructor = exceptionClass.getConstructor();
            instance = constructor.newInstance();
        } else {
            Constructor<? extends Exception> constructor = exceptionClass.getConstructor(this.getExceptionArgumentTypes().toArray(new Class[0]));
            instance = constructor.newInstance(this.getExceptionArgumentValues().toArray(new Object[0]));
        }
    } catch (ReflectiveOperationException e) {
        LOGGER.warn("Cannot instantiate the class for provided type: {}. Fallback: Throw RuntimeException", type);
        instance = new RuntimeException("Chaos Monkey - RuntimeException");
    }

    throw instance;
}

例如yml里配置自定义exception,就会抛出自定义异常

 assaults:
      level: 1
      latencyActive: true
      exceptionsActive: true
      exception:
        type: pl.piomin.services.customer.ZuoqiException
        arguments[0]:
          className: java.lang.String
          value: 1
      killApplicationActive: false

(2)KillAppAssault 杀掉应用

    @Override
    public void attack() {
        try {
            LOGGER.info("Chaos Monkey - I am killing your Application!");

            if (metricEventPublisher != null)
                metricEventPublisher.publishMetricEvent(MetricType.KILLAPP_ASSAULT);

            int exit = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
            Thread.sleep(5000); // wait before kill to deliver some metrics

            System.exit(exit);
        } catch (Exception e) {
            LOGGER.info("Chaos Monkey - Unable to kill the App, I am not the BOSS!");
        }
    }

(3)LatencyAssault 延迟攻击,

    @Override
    public void attack() {
        LOGGER.debug("Chaos Monkey - timeout");
        // 在配置的延迟攻击范围内随机取值
        int timeout = ThreadLocalRandom.current().nextInt(settings.getAssaultProperties().getLatencyRangeStart(),
                settings.getAssaultProperties().getLatencyRangeEnd());
        atomicTimeoutGauge.set(timeout);
        LOGGER.info("Chaos Monkey latency timr" + timeout);
        // metrics
        if (metricEventPublisher != null) {
            //发布事件
            metricEventPublisher.publishMetricEvent(MetricType.LATENCY_ASSAULT);
            metricEventPublisher.publishMetricEvent(MetricType.LATENCY_ASSAULT, atomicTimeoutGauge);
        }
        try {
            //线程睡眠随机数值
            Thread.sleep(timeout);
        } catch (InterruptedException e) {
            // do nothing
        }
    }

(4)MemoryAssault 内存攻击,引发gc,

 private void eatFreeMemory() {
        //获取最终应用剩余内存最小值,比如memoryFillIncrementFraction设置为0.15,那就会吃掉剩余内存*(1-0.15)
        int minimumFreeMemoryPercentage = calculatePercentIncreaseValue(settings.getAssaultProperties().getMemoryFillIncrementFraction());

        @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
        //定义一个集合用于内存存放
        Vector<byte[]> memoryVector = new Vector<>();
        long stolenHere = 0L;
        //计算每次放进集合的内存大小,第一次是随机获取剩余内存的0.05-memoryFillTargetFraction倍数
        int percentIncreaseValue = calculatePercentIncreaseValue(calculatePercentageRandom());
        LOGGER.info("Chaos Monkey - memory assault start, free memory: " + runtime.freeMemory()/1024/1024+"M");
        LOGGER.info("Chaos Monkey - memory assault start, percentIncreaseValue: " + percentIncreaseValue/1024/1024+"M");
        //当内存攻击开启,且剩余内存大于配置的最小值,且剩余内存大于该放进集合的内存
        while (isActive() && runtime.freeMemory() >= minimumFreeMemoryPercentage && runtime.freeMemory() > percentIncreaseValue) {
            // only if ChaosMonkey in general is enabled, triggers a stop if the attack is canceled during an experiment
            // increase memory random percent steps
            memoryVector.add(createDirtyMemorySlice(percentIncreaseValue));
            stolenHere += percentIncreaseValue;
            long newStolenTotal = stolenMemory.addAndGet(percentIncreaseValue);
            metricEventPublisher.publishMetricEvent(MetricType.MEMORY_ASSAULT_MEMORY_STOLEN, newStolenTotal);
            //每次内存提升的间隔
            waitUntil(settings.getAssaultProperties().getMemoryMillisecondsWaitNextIncrease());
            percentIncreaseValue = calculatePercentIncreaseValue(settings.getAssaultProperties().getMemoryFillTargetFraction());
            LOGGER.info("Chaos Monkey - memory assault, percentIncreaseValue: " + percentIncreaseValue/1024/1024+"M");
        }
        LOGGER.info("Chaos Monkey - memory assault end, free memory: " + runtime.freeMemory()/1024/1024);
        // Hold memory level and cleanUp after, only if experiment is running
        if (isActive()) {
            LOGGER.info("Memory fill reached, now sleeping and holding memory"+runtime.totalMemory()/1024/1024+"M");
            LOGGER.info("Memory fill reached, now sleeping and holding memory");
            //内存攻击后的持续时间
            waitUntil(settings.getAssaultProperties().getMemoryMillisecondsHoldFilledMemory());
        }

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值