chaos monkey for spring boot (二)

四.源碼二

  1. ChaosMonkeyScheduler 

      在ChaosMonkeyConfiguration中,如果要啓動定時器,要有taskScheduler這個bean,否則無法啓動

   @Bean
    public ChaosMonkeyScheduler scheduler(@Nullable TaskScheduler scheduler, ChaosMonkeyRuntimeScope runtimeScope) {
        ScheduledTaskRegistrar registrar = null;
        if (scheduler != null) {
            registrar = new ScheduledTaskRegistrar();
            registrar.setTaskScheduler(scheduler);
        }
        return new ChaosMonkeyScheduler(registrar, assaultProperties, runtimeScope);
    }
    public ChaosMonkeyScheduler(ScheduledTaskRegistrar scheduler, AssaultProperties config, ChaosMonkeyRuntimeScope runtimeScope) {
        this.scheduler = scheduler;
        this.config = config;
        this.runtimeScope = runtimeScope;

        if (scheduler == null) {
            LOGGER.warn("No ScheduledTaskRegistrar available in application context, scheduler is not functional");
        }

        reloadConfig();
    }

    public void reloadConfig() {
        //獲取cron表達式
        String cronExpression = config.getRuntimeAssaultCronExpression();
        boolean active = !"OFF".equals(cronExpression);

        if (currentTask != null) {
            LOGGER.info("Cancelling previous task");
            currentTask.cancel();
            currentTask = null;
        }

        if (active) {
            //如果應用裏沒有tasksheduler這個bean則拋錯
            if (scheduler == null) {
                // We might consider an exception here, since the user intent could clearly not be serviced
                LOGGER.error("No scheduler available in application context, will not process schedule");
            } else {
                //把ChaosMonkeyRuntimeScope下的攻擊全部交給定時任務,但是隻有兩種方式內存和殺死應用兩種攻擊
                CronTask task = new CronTask(runtimeScope::callChaosMonkey, cronExpression);
                currentTask = scheduler.scheduleCronTask(task);
            }
        }
    }

2.AssaultProperties

public class AssaultProperties implements Serializable {
    @Value("${level : 5}")
    @Min(value = 1)
    @Max(value = 10000)
    //級別,表示概率,比如level爲1,那麼1/(level+1)的概率
    private int level;

    @Value("${latencyRangeStart : 1000}")
    @Min(value = 1)
    @Max(value = Integer.MAX_VALUE)
    //延遲時間範圍起始值
    private int latencyRangeStart;

    @Value("${latencyRangeEnd : 3000}")
    @Min(value = 1)
    @Max(value = Integer.MAX_VALUE)
    //延遲時間範圍結束值
    private int latencyRangeEnd;

    @Value("${latencyActive : true}")
    //延遲攻擊是否生效
    private boolean latencyActive;

    @Value("${exceptionsActive : false}")
    //異常攻擊是否生效
    private boolean exceptionsActive;

    @AssaultExceptionConstraint
    //自定義異常
    private AssaultException exception;

    @Value("${killApplicationActive : false}")
    //是否kill應用
    private boolean killApplicationActive;

    @Value("${memoryActive : false}")
    //內存攻擊是否生效
    private volatile boolean memoryActive;

    @Value("${memoryMillisecondsHoldFilledMemory : 90000}")
    @Min(value = 1500)
    @Max(value = Integer.MAX_VALUE)
    //內存攻擊持續時間
    private int memoryMillisecondsHoldFilledMemory;

    @Value("${memoryMillisecondsWaitNextIncrease : 1000}")
    @Min(value = 100)
    @Max(value = 30000)
    //每次上升內存間隔時間
    private int memoryMillisecondsWaitNextIncrease;

    @Value("${memoryFillIncrementFraction : 0.15}")
    @DecimalMax("1.0")
    @DecimalMin("0.0")
    //每次上升剩餘內存百分比
    private double memoryFillIncrementFraction;

    @Value("${memoryFillTargetFraction : 0.25}")
    @DecimalMax("0.95")
    @DecimalMin("0.05")
    private double memoryFillTargetFraction;

    @Value("${runtime.scope.assault.cron.expression:OFF}")
    //定時任務cron表達式
    private String runtimeAssaultCronExpression;

    @Value("${watchedCustomServices:#{null}}")
    //監聽的服務
    private List<String> watchedCustomServices;
}

3.WatcherProperties

public class WatcherProperties implements Serializable {
    //是否對cotroller進行切面
    @Value("${controller:false}")
    private boolean controller;
    //是否對restController進行切面
    @Value("${restController:false}")
    private boolean restController;
    //是否對service進行切面
    @Value("${service:true}")
    private boolean service;
    //是否對repository進行切面
    @Value("${repository:false}")
    private boolean repository;
    //是否對component進行切面
    @Value("${component:false}")
    private boolean component;
}

4.ChaosMonkeyConfiguration

public class ChaosMonkeyConfiguration {
    private static final Logger LOGGER = LoggerFactory.getLogger(ChaosMonkeyConfiguration.class);
    private final ChaosMonkeyProperties chaosMonkeyProperties;
    private final WatcherProperties watcherProperties;
    private final AssaultProperties assaultProperties;

    public ChaosMonkeyConfiguration(ChaosMonkeyProperties chaosMonkeyProperties, WatcherProperties watcherProperties,
                                    AssaultProperties assaultProperties) {
        this.chaosMonkeyProperties = chaosMonkeyProperties;
        this.watcherProperties = watcherProperties;
        this.assaultProperties = assaultProperties;

        try {
            String chaosLogo = StreamUtils.copyToString(new ClassPathResource("chaos-logo.txt").getInputStream(), Charset.defaultCharset());
            LOGGER.info(chaosLogo);
        } catch (IOException e) {
            LOGGER.info("Chaos Monkey - ready to do evil");
        }

    }

    @Bean
    @ConditionalOnClass(name = "io.micrometer.core.instrument.MeterRegistry")
    public Metrics metrics() {
        return new Metrics();
    }


    @Bean
    public MetricEventPublisher publisher() {
        return new MetricEventPublisher();
    }

    @Bean
    //配置ChaosMonkeySettings,所有配置都在這
    public ChaosMonkeySettings settings() {
        return new ChaosMonkeySettings(chaosMonkeyProperties, assaultProperties, watcherProperties);
    }

    @Bean
    //配置延遲攻擊bean
    public LatencyAssault latencyAssault() {
        return new LatencyAssault(settings(), publisher());
    }

    @Bean
    //配置異常攻擊bean
    public ExceptionAssault exceptionAssault() {
        return new ExceptionAssault(settings(), publisher());
    }

    @Bean
    //配置殺死應用bean
    public KillAppAssault killAppAssault() {
        return new KillAppAssault(settings(), publisher());
    }

    @Bean
    //配置內存攻擊bean
    public MemoryAssault memoryAssault() {
        return new MemoryAssault(Runtime.getRuntime(), settings(), publisher());
    }

    @Bean
    //配置請求作用域
    public ChaosMonkeyRequestScope chaosMonkeyRequestScope(List<ChaosMonkeyRequestAssault> chaosMonkeyAssaults, List<ChaosMonkeyAssault> allAssaults) {
        return new ChaosMonkeyRequestScope(settings(), chaosMonkeyAssaults, allAssaults, publisher());
    }

    @Bean
    //定時任務,注意自己注入taskScheduler bean
    public ChaosMonkeyScheduler scheduler(@Nullable TaskScheduler scheduler, ChaosMonkeyRuntimeScope runtimeScope) {
        ScheduledTaskRegistrar registrar = null;
        if (scheduler != null) {
            registrar = new ScheduledTaskRegistrar();
            registrar.setTaskScheduler(scheduler);
        }
        return new ChaosMonkeyScheduler(registrar, assaultProperties, runtimeScope);
    }

    @Bean
    //運行時作用域
    public ChaosMonkeyRuntimeScope chaosMonkeyRuntimeScope(List<ChaosMonkeyRuntimeAssault> chaosMonkeyAssaults) {
        return new ChaosMonkeyRuntimeScope(settings(), chaosMonkeyAssaults);
    }

    @Bean
    @Conditional(AttackControllerCondition.class)
    //配置controller切面
    public SpringControllerAspect controllerAspect(ChaosMonkeyRequestScope chaosMonkeyRequestScope) {
        return new SpringControllerAspect(chaosMonkeyRequestScope, publisher());
    }

    @Bean
    @Conditional(AttackRestControllerCondition.class)
    //配置restController切面
    public SpringRestControllerAspect restControllerAspect(ChaosMonkeyRequestScope chaosMonkeyRequestScope) {
        return new SpringRestControllerAspect(chaosMonkeyRequestScope, publisher());
    }

    @Bean
    @Conditional(AttackServiceCondition.class)
    //配置service切面
    public SpringServiceAspect serviceAspect(ChaosMonkeyRequestScope chaosMonkeyRequestScope) {
        return new SpringServiceAspect(chaosMonkeyRequestScope, publisher());
    }

    @Bean
    @Conditional(AttackComponentCondition.class)
    //配置component切面
    public SpringComponentAspect componentAspect(ChaosMonkeyRequestScope chaosMonkeyRequestScope) {
        return new SpringComponentAspect(chaosMonkeyRequestScope, publisher());
    }

    @Bean
    @Conditional(AttackRepositoryCondition.class)
    //配置respository切面
    public SpringRepositoryAspect repositoryAspect(ChaosMonkeyRequestScope chaosMonkeyRequestScope) {
        return new SpringRepositoryAspect(chaosMonkeyRequestScope, publisher());
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnEnabledEndpoint
    //配置restEndPoint,提供對外web服務
    public ChaosMonkeyRestEndpoint chaosMonkeyRestEndpoint(ChaosMonkeyRuntimeScope runtimeScope, ChaosMonkeyScheduler scheduler) {
        return new ChaosMonkeyRestEndpoint(settings(), runtimeScope, scheduler);
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnEnabledEndpoint
    public ChaosMonkeyJmxEndpoint chaosMonkeyJmxEndpoint() {
        return new ChaosMonkeyJmxEndpoint(settings());
    }

}

五.yml配置

chaos:
  monkey:
    #是否開啓混沌工程
    enabled: true
    assaults:
      #攻擊級別,表示概率,具體也就是1/(level+1)
      level: 1
      #開啓延遲攻擊
      latencyActive: true
      #開啓異常攻擊
      exceptionsActive: true
      #自定義異常
      exception:
        #指定自定義
        type: pl.piomin.services.customer.ZuoqiException
        arguments[0]:
          className: java.lang.String
          value: "這是自定義異常"
      #開啓kill應用攻擊
      killApplicationActive: true
      #開啓定時任務,需要taskSh
      runtime-assault-cron-expression: 5/20 * * * * ?
      #延遲時間範圍結束
      latency-range-end: 2000
      #延遲時間範圍開始
      latency-range-start: 100
      #開啓內存攻擊
      memory-active: true
      #內存攻擊時剩餘內存比例,例如內存攻擊前freeMemory爲200M,攻擊後會剩200*0.2
      memory-fill-increment-fraction: 0.2
      #內存攻擊持續時間
      memory-milliseconds-hold-filled-memory: 1500
      #內存攻擊每次吃掉的內存比例,例如內存攻擊前freeMemory爲200M,在達到200*0.2M前,每次吃掉內存
      memory-fill-target-fraction: 0.05
      #內存攻擊每次吃掉的內存間隔時間
      memory-milliseconds-wait-next-increase: 100
      #watchedCustomServices: [ "pl.piomin.services.customer.controller.CustomerController.findById"]
  }
    watcher:
      #監控配置
      repository: true
      restController: false
      
management:
  endpoint:
    chaosmonkey:
      enabled: true
  endpoints:
    web:
      exposure:
        include: health,info,chaosmonkey

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章