2010-07-23 9 views
9

Quartz Scheduler를 사용하여 작업을 예약하는 응용 프로그램이 있습니다. 응용 프로그램은 현재 Quartz 버전 1.6.2를 실행 중입니다. 내 JobStore는 오라클 데이터베이스가 백업 한 org.quartz.impl.jdbcjobstore.JobStoreTX입니다. 클러스터링은 켜져 있지만 데이터베이스를 사용하는 스케줄러는 하나뿐입니다.Quartz Job이 트리거 된 순서대로 대기하도록 만들 수 있습니까?

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 
org.quartz.threadPool.threadCount = 5 
org.quartz.threadPool.threadPriority = 5 

내 작업은 장기 실행, 그래서 그것은 트리거가 새로운 일자리를 해고 할 때 실행 5 일 (내 THEAD 풀에서 허용되는 최대)를 가지고 매우 흔한 일 다음과 같이 내 석영 스레드가 구성됩니다. 새로 트리거 작업은 불발 나는 다음과 같이 로그 메시지를 참조하십시오 실행중인 작업이 완료

2011-05-20 04:09:30,097 INFO [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName1 misfired job DEFAULT.DEFAULT at: 04:09:30 05/20/2011. Should have fired at: 04:08:29 05/20/2011 
2011-05-20 04:09:30,120 INFO [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName1 misfired job DEFAULT.DEFAULT at: 04:09:30 05/20/2011. Should have fired at: 04:09:30 05/20/2011 
2011-05-20 04:09:30,125 INFO [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName2 misfired job DEFAULT.DEFAULT at: 04:09:30 05/20/2011. Should have fired at: 04:08:30 05/20/2011 
2011-05-20 04:09:30,138 INFO [QuartzScheduler_scheduler-servername-111305822374881_MisfireHandler] o.q.p.h.LoggingTriggerHistoryPlugin - Trigger DEFAULT.JobName2 misfired job DEFAULT.DEFAULT at: 04:09:30 05/20/2011. Should have fired at: 04:09:30 05/20/2011 
2011-05-20 04:11:29,998 INFO [QuartzScheduler_scheduler-servername-111305822376676_MisfireHandler] o.q.impl.jdbcjobstore.JobStoreTX - Handling 2 trigger(s) that missed their scheduled fire-time. 

되면, 불발 작업 중 하나를 집어 정상적으로 실행 얻을 것이다. 그러나 Quartz는 작업이 원래 실행될 예정이었던 순서에 관계없이 임의로 실화 된 작업을 선택하는 것으로 보입니다. 이상적으로 말하자면, 나는 원래 화재 시간을 기준으로 그들이 달렸다고 가정 된 순서대로 데리러오고 싶습니다.

Quartz ThreadPool의 공간을 사용할 수있게되면 대기중인 (실화되지 않은) 작업이 트리거 된 순서대로 실행되도록 할 수 있습니까?

답변

2

석영이 놓친 방아쇠를 처리 할 때 화재가 발생하면 방아쇠의 nextFireTime을 업데이트합니다. 기본적으로 트리거는 nextFireTime이 과거 60 초를 초과하면 누락 된 것으로 간주됩니다. 누락 된 트리거는 nextFireTime 및 우선 순위에 따라 선택되어야하지만 일부 트리거가 업데이트되었거나 다른 트리거가 없기 때문에 무작위로 보입니다.

나는 org.quartz.jobStore.misfireThreshold 속성을 늘릴 것을 제안합니다. http://www.quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigRAMJobStore.html을 참조하십시오 (이 등록 정보는 모든 JobStores에서 동일합니다). 이렇게하면 트리거가 다시 예약 될 가능성이 줄어 듭니다.

+0

저는 새로운 일자리를 얻었고 수년 동안 석영을 사용하지 않았기 때문에 이것을 테스트 할 수 없었습니다. 그리고 이것이 작동하는지 테스트 프로젝트를 설정하는 데 귀찮은 일이 아니 었습니다. 그러나 나는 5 년 된 질문에 답하기 위해 귀찮게 노력 했으므로 대답이 도움이 될 것 같아 인상적이다. :) –

+0

비슷한 문제가있어서 검색 중이 었습니다. 스택 오버플로. 결국 나는 코드를 파헤 치고 나 자신을 알아 냈다. 그러나 누군가 다른 사람이 미래에 답을 찾고있는 경우에 대비하여 여기를 남겨 둘 것이라고 생각했다. – samblake

+0

@JonQuarfoth 결국 당신을 위해 무엇이 효과가 있었습니까? 나는 수천 개의 일자리를 계획하고 있는데, 내가 원하는 위치에서 다른 위치로 옮겨야 할 때 그 일은 오래 갈 것입니다. 그 모양은 100GB 정도 될 수 있습니다. Quartz 클러스터링을 사용하여 마스터 스케줄이 작업을 수행 할 때 슬레이브가 해당 작업을 계속 수행 할 것이고 결국에는 슬레이브 중 하나가 선택한 작업에 관심이 있기 때문에 불을 놓치지 않을 것입니다. . 어쩌면 엄청나게 큰 실화 문턱 값을 설정할 수 있습니다. 네가 그것에 대해 어떻게 생각하는지 알려줘. 감사. – Coder

0

석영을보고있는 thread pool은 공정하지 않은 wait()/notify() 루프를 사용하며 여러 스레드가 대기 중일 때 임의로 새 스레드를 선택합니다.

공정한 ThreadPool 인스턴스를 사용할 수 있습니다. SimpleThreadPool에서 코드를 복사하지만 nextRunnableLock을 둘러싼 잠금을 java.util.ReentrantLock으로 바꾸고 true를 공정한 생성자로 전달합니다. 수정 된 SimpleThreadPool에서 synchronized 대신 ReentrantLock.lock()/unlock()을 사용하고 wait/notify 대신 ReentrantLock.newCondition(). signal()/await()를 사용하면 문제가 해결 될 수 있습니다.

+0

풀의 스레드에는 할당 된 작업이 없으므로 사용자가 말하는 공정성이 중요하지 않습니다. 어떤 스레드가 우선 무료이든, 다음 작업을 실행합니다. – jhouse

+0

공평성은 스레드 풀, runInThread 및 blockForAvailableThreads 외부 스레드는 모두 불공정하게 대기한다고 생각합니다. "내 스레드 풀이 초과되었을 때"라고 말한 것은 무엇입니까? – sbridges

+0

runInThread() 및 blockForAvailableThreads()는 모두 동일한 스레드에서 호출됩니다. 이러한 메서드의 결과를 기다리는 스레드가 여러 개 없으므로 'fairness' wait()/notify()는 중요하지 않습니다. (단 하나의 스레드 만 서비스/스레드 풀을 사용합니다). – jhouse

2

실격 시나리오 (작업자 스레드보다 실행 준비가 된 작업이 많은 시나리오)가 실행되고있는 것처럼 들립니다. 연기 시간이 지난 후에 각각의 행동 방식을 변경하려면 트리거의 오 실링 명령 및/또는 우선 순위 속성을 설정하십시오.

또한 실화로 간주되기 전에 트리거가 실행되기를 기다리는 트리거가 "늦게"될 수있는 시간을 변경하는 실화 임계 값을 늘릴 수 있습니다 (실화 명령이 적용되었습니다)).

Quartz ThreadPool의 공간을 사용할 수있게되면 대기중인 (실화되지 않은) 작업이 트리거 된 순서대로 실행되도록 할 수 있습니까?

"아무 것도하지 않음"지침은 발사 시간을 그대로 남겨 둡니다.

+0

분명히 실화 시나리오입니다. 저는 그 점에 대해 좀 더 구체적으로 질문을 업데이트했습니다. 실격 된 명령이 원래 발사 된 순서대로 집어 들게하는 실화 명령이 있습니까? –

+3

MISFIRE_INSTRUCTION_DO_NOTHING 실격을위한 javadoc은 다음과 같이 읽습니다. "실격 상황에서 CronTrigger가 다음 시간으로 다음 시간으로 업데이트하려고 할 때 스케줄러에게 현재 시간 이후에 업데이트되지만, 지금 해고되고 싶지 않다. " 어쩌면 내가 오해 할 수도 있지만, 그 일은 마치 발사를 건너 뛰고 다음에 그것이 작동 될 때까지 아무것도하지 않는 것처럼 들린다. 이것은 내가 원하는 것이 아닙니다. 사용할 수있는 스레드가있는 즉시 작업을 실행하고 싶지만 여러 개의 잘못된 작업이있는 경우 가장 오래 기다리는 작업이 먼저 실행됩니다. –

0

CronTrigger의 경우 updateAfterMisfire() 메서드는 new Date() 사례 MISFIRE_INSTRUCTION_FIRE_ONCE_NOW 정책에서 작업을 다시 예약 할 수 있습니다.

여러 작업이 잘못하면 컴퓨터가 빠르게 실행되기 때문에 여러 작업이 동시에 실패 할 수 있습니다 (동일한 밀리 초).

결과적으로 우선 순위가 정의되어 있지 않으면 스케쥴러는 키 또는 전체 이름에 따라 NextFireTime과 동일한 첫 번째 다음 작업을 선택합니다.

updateAfterMisfire() 메서드는 예를 들어 Thread.sleep(25)을 사용하여 고유 한 date으로 작업을 다시 예약해야합니다.

관련 문제