programing

Spring Quartz 작업 실행이 겹치지 않도록 합니다.

stoneblock 2023. 10. 26. 20:36

Spring Quartz 작업 실행이 겹치지 않도록 합니다.

저는 스프링 쿼츠에서 20초마다 실행되는 자바 프로그램이 있습니다.실행하는 데 몇 초밖에 걸리지 않는 경우도 있지만 데이터가 커지면 20초 이상 실행될 것으로 확신합니다.

한 인스턴스가 실행되는 동안 Quartz가 작업을 수행/발동하지 않도록 하려면 어떻게 해야 합니까?데이터베이스에서 동일한 작업을 수행하는 작업 2개를 실행하는 것은 좋지 않습니다.동기화를 할 수 있는 방법이 있을까요?

석영 1

Job 대신 Stateful Job을 구현하기 위해 클래스를 변경하면 Quartz가 대신 처리해 줄 것입니다.Stateful Job javadoc에서:

stateful jobs는 동시 실행이 허용되지 않으므로 execute(xx) 메서드가 완료되기 전에 발생하는 새 트리거가 지연됩니다.

StatefulJob은 Job을 확장하고 새로운 메서드를 추가하지 않으므로 원하는 동작을 변경하기만 하면 됩니다.

public class YourJob implements org.quartz.Job {
    void execute(JobExecutionContext context) {/*implementation omitted*/}
}

대상:

public class YourJob implements org.quartz.StatefulJob {
    void execute(JobExecutionContext context) {/*implementation omitted*/}
}

석영2

Quartz 버전 2.0에서는StatefulJob사용되지 않습니다.이제 주석을 대신 사용하는 것이 좋습니다.

@DisallowConcurrentExecution
public class YourJob implements org.quartz.Job {
    void execute(JobExecutionContext context) {/*implementation omitted*/}
}

20초마다 발사만 하면 되는 거라면 쿼츠는 심각한 오버킬입니다.java.util.concurrent.ScheduledExecutorService그 일을 하기에 충분할 겁니다

ScheduledExecutorService또한 스케줄링을 위한 두 가지 의미론을 제공합니다."고정 속도"는 중복에 관계없이 20초마다 작업을 실행하려고 시도하는 반면, "고정 지연"은 첫 번째 작업이 끝날 때부터 다음 작업이 시작될 때까지 20초 간격을 두려고 시도합니다.중복을 방지하려면 고정 지연이 가장 안전합니다.

이 질문을 언급하는 사람이 있을 경우를 대비하여 Stateful Job은 더 이상 사용되지 않습니다.이제 주석을 대신 사용할 것을 제안합니다.

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class TestJob implements Job {

이것은 그 주석들이 의미하는 바를 설명해 줄 것입니다.

주석은 이름이 설명하는 대로 동작을 유발합니다. 작업의 여러 인스턴스가 동시에 실행되지 않도록 허용됩니다(작업이 실행() 방법에 코드가 있지만 30초마다 반복되는 트리거로 예약된 경우를 고려하십시오).그리고 실행될 때마다 JobDataMap 내용이 스케줄러의 JobStore에 다시 유지됩니다.이 예제에서는 @PersistJobDataAfterExecution 주석만 관련이 있지만 저장된 데이터의 경합 조건을 방지하려면 @DisallowCurrentExecution 주석을 함께 사용하는 것이 좋습니다.

스프링 쿼츠를 사용하면 이렇게 구성을 해야 할 것 같습니다.

    <bean id="batchConsumerJob"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="myScheduler" />
        <property name="targetMethod" value="execute" />
        <property name="concurrent" value="false" />
    </bean>

첫 번째 작업이 끝날 때까지 두 번째 작업이 차단되고 결국에는 백로그가 발생하기 때문에 동기화를 원하실지 모르겠습니다.작업을 대기열에 넣을 수 있지만 설명을 들어보면 대기열이 무한히 증가할 수 있습니다.

ReadWriteLocks를 조사하여 작업이 실행되는 동안 잠금을 설정하도록 하겠습니다.향후 작업에서는 이 잠금을 검사하고 이전 작업이 여전히 실행 중인 경우 즉시 종료할 수 있습니다.그것이 가장 신뢰할 수 있는 방법이라는 것을 경험으로 알게 되었습니다.

또한 경고를 생성하여 문제가 발생했음을 알고 시간 간격을 늘릴 수도 있습니까?

당신은 세마포를 사용할 수 있습니다.세마포를 가져가면 두 번째 작업을 버리고 다음 화재 시간까지 기다립니다.

그들을 줄로 늘어놓다

시간이 20초를 초과하는 경우에도 현재 작업을 완료하고 다음 작업을 대기열에서 가져와야 합니다.

또는 적당한 양으로 시간을 늘릴 수도 있습니다.

언급URL : https://stackoverflow.com/questions/1636556/ensure-that-spring-quartz-job-execution-doesnt-overlap