ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Quartz] SpringBoot 에서 동적으로 properties 파일 읽어 Cron 설정 변경
    Framework/Spring 2019. 5. 21. 16:40

     

    SpringBoot 환경에서 스케쥴링을 설정하는 방법은 쉽다.
    메인 함수 위에 @EnableScheduling 어노테이션을 달고

    스케쥴링을 설정할 함수 위에 

    @Scheduled(fixedDelayString ="600000")  //600000은 ms 단위로 = 10분 

    혹은

    @Scheduled(cron = "*/10 * * * * *")  // Cron 표현식, 10초에 1번 실행

    어노테이션을 달아주기만 하면 된다.

     

    하지만 나는 Cron 표현식을 변경하여 설정해놓은 properties 파일을 변경하면 

    프로그램을 재시작하지 않아도 자동으로 적용되는 프로그램을 만들고 싶었다.

     

    여기서 사용하게 된 것이 

    commons-configuration2

    spring-boot-starter-quartz 이다.

     

    commons-configuration2 는 주기적으로 파일을 읽어와서 편하게 값을 불러올 수 있다.

    (commons-configuration2 2.3, commons-beanutils 1.9.3을 사용했다.

     

     

     

     

    ** application.properties (10초에 한 번 씩 실행)

    cron.test=0/10 * * * * ? 
    

     

     

    ** 파일에서 주기적으로 정보를 읽는 클래스

    @Component
    public class ReloadBatchConfig {
     
        private ReloadingFileBasedConfigurationBuilder<>PropertiesConfiguration> builder;
     
        @PostConstruct // 초기화가 끝난 후 자동 실행
        void init() {
     
            builder = new
            ReloadingFileBasedConfigurationBuilder<>(PropertiesConfiguration.class)
                    .configure(new Parameters().fileBased().setFile(new File("./application.properties"))); 
                   // 설정 파일 위치를 적어준다.
     
            PeriodicReloadingTrigger configReloadingTrigger = new PeriodicReloadingTrigger(
                    builder.getReloadingController(), null, 1, TimeUnit.SECONDS); 
                    //정보를 파일에서 리로드할 시간 설정 
     
            configReloadingTrigger.start();
        }
     
        public Configuration getCompositeConfiguration() {
              try {
                  return builder.getConfiguration(); //정보 읽음
              } catch (ConfigurationException e) {
                  e.printStackTrace();
              }
              return null;
          }
    }
    

     

     

     

     

     

    ** 변경할 cron 표현식에 따라 주기적으로 실행할 메소드 (@Scheduled로 실행하는 메소드와 동일)

    public class TestJob implements Job {  //  org.quartz.Job을 implements
    
    	@Override
    	public void execute(JobExecutionContext context) throws JobExecutionException {
        	//실행할 코드
        }
    }
    

     

     

    ** 파일에서 읽어온 표현식으로 메소드 실행주기를 바꿔주는 클래스

    @Component
    @PropertySource("file:./config/batch.properties")
    public class SchedulerManager {
    	
    	private  static final Logger logger = LoggerFactory.getLogger(SchedulerManager.class);
    	
        private SchedulerFactory schedulerFactory;
        public static Scheduler scheduler;
        
        @Autowired
        private ReloadBatchConfig reloadConf;
        
        @Value("${cron.test}")
        private String testTime; //초기 실행 값 설정
        
        public static String TestTime; //Cron 입력 시 Static만 가능
        
        @PostConstruct
        public void init() {
        	TestTime = testTime;
        	
        	//초기 실행할 스케줄러의 Trigger 생성
        	testTrigger = TriggerBuilder.newTrigger().withIdentity("testTriggerKey").
      	          withIdentity(new TriggerKey("testTriggerKey")).
      	          withSchedule(CronScheduleBuilder.cronSchedule(TestTime)).build();
        	
        	try {
    			start();
    		} catch (SchedulerException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
        }
        
        public void start() throws SchedulerException{
        
            schedulerFactory = new StdSchedulerFactory();
            
    		//여러 job을 실행 시 Scheduler도 따로 생성해준다.
            testScheduler = schedulerFactory.getScheduler();
            testScheduler.start();
     
    		//실행할 Job
            JobDetail testJob = JobBuilder.newJob(TestJob.class).build();
            
    		//실행
            testScheduler.scheduleJob(testJob, testTrigger);
            
        }
        
      //10초마다 batch.properties 읽어와서 배치 설정 바꿈 
      @Scheduled(fixedDelayString = "10000") 
      public void get(){
      	
    		public static String newTestTime = reloadConf.getCompositeConfiguration().getString("cron.test");
      	 
      		try {
    			//파일의 값이 변경되었을 때만 수행
      			if (testcheduler != null && !testTime.equals(newTestTime)) {
    				//변경될 cron 표현식을 쓸 새로운 Trigger 생성
      				CronTriggerImpl newTestTrigger = (CronTriggerImpl) testScheduler.getTrigger(testTrigger.getKey());
      		    	newReportTrigger.setCronExpression(newTestTime); //Trigger 값 변경
      		    	reportScheduler.rescheduleJob(testTrigger.getKey(), newTestTrigger); //주기 변경, 메소드 재실행된다.
      		    	reportTime = newReportTime; //값 비교를 위한 초기화
      			}
    
      		} catch (Exception e) {
      			// TODO Auto-generated catch block
      			logger.error("[Exception] Cron : " + e.getMessage());
      		}
      	}
      
    }
    

    프로그램 실행 중에 외부에 있는 application.properties 파일의 값을 변경하면 

    변경한 cron 표현식의 주기대로 메소드가 실행된다.

    댓글

Copyright 2019. 콩이볼 All rights reserved.