엔터프라이즈 Bean에 대한 EJB 타이머 서비스를 사용한 타이머 작성
엔터프라이즈 Bean을 사용하여 시간 기반 이벤트를 스케줄링하기 위해 EJB 타이머 서비스를 활용할 수 있습니다.
이 태스크 정보
EJB 3.1 스펙의 지원에서 비지속적 EJB 타이머를 작성할 수 있습니다. 이 제품은 또한 프로그램 방식 타이머 작성을 위한 확장 TimerService API를 지원합니다. 또한 애플리케이션이 시작할 때 타이머를 자동으로 작성하도록 EJB 컨테이너를 구성할 수 있습니다.
WebSphere® Application Server는 EJB(Enterprise JavaBeans) 타이머 서비스를 구현합니다. 사용자 비즈니스 필요에 따라, 지속적 타이머 또는 비지속적 타이머를 사용할 수 있습니다. 서버의 라이프사이클을 이상으로 타이머 존재의 보장이 필요한 타이머 기반 이벤트에 대한 타이머를 작성하려는 경우 지속적 타이머가 유용합니다. 서버가 시작하고 서버 시스템 종료 및 다시 시작을 통해 지속할 때 이전에 시작된 지속적 타이머가 자동으로 시작합니다. 예를 들어, 시스템 애플리케이션을 시작하거나 타이머 만기 시에 상태 알림을 보내기 위해 지속적 타이머를 사용할 수 있습니다. 비지속적 타이머는 타이머 조치가 온도 폴링 같은 부정적인 비즈니스 영향이 없이 생략 또는 재수행되는 중요하지 않은 상황에서 유용합니다.
프로그래밍 방식으로 타이머를 작성할 수 있습니다. 또한 Bean 클래스에서 @Schedule 어노테이션을 사용하거나 ejb-jar.xml 배치 디스크립터에서 타이머 요소를 사용하여 자동으로 타이머를 작성할 수도 있습니다. 자동으로 타이머를 작성하여 EJB 타이머 서비스 작성 메소드를 프로그래밍 방식으로 시작하기 위해 엔터프라이즈 Bean 호출에 의존하지 않고 타이머를 스케줄할 수 있습니다.
- 지속적 타이머
-
지속적 타이머는 스케줄러 서비스 태스크로서 구현됩니다. 기본적으로 내부 또는 사전 구성된 스케줄러 인스턴스가 해당 태스크를 관리하는 데 사용되며, 서버 프로세스와 연관된 Apache Derby 데이터베이스에서 지속됩니다.
내부 스케줄러 인스턴스에 기본 사용자 정의를 수행할 수 있습니다. 스케줄러 인스턴스 사용자 정의에 대한 정보는 타이머 서비스 정보 구성을 참조하십시오.
타이머의 작성 및 취소는 트랜잭션적이고 지속적입니다. 타이머가 트랜잭션 내에서 작성되고 해당 트랜잭션이 나중에 롤백되는 경우, 타이머 작성도 롤백됩니다. 비슷한 규칙이 타이머의 취소에 적용됩니다. 이전에 시작된 타이머는 애플리케이션 서버 시스템 종료 및 다시 시작 사이에 유지됩니다.
- 비지속적 타이머
-
EJB 3.1은 EJB 타이머 서비스를 기능 보강하여 지속적 타이머 외에 비지속적 EJB 타이머를 사용 가능하게 합니다. 비지속적 타이머는 지속적 타이머와 동일한 시맨틱 및 동작을 갖지만, 데이터 저장소의 오버헤드는 없습니다. 비지속적 타이머는 지속적 타이머와는 다른 라이프사이클을 갖습니다. 지속적 타이머가 애플리케이션 서버 시스템 종료 및 다시 시작 사이에서 유지되는 반면, 비지속적 타이머는 애플리케이션 서버가 활성인 동안에만 활성입니다. 지속적 타이머와는 달리, 비지속적 타이머를 찾거나 취소하는 명령이 없습니다. 비지속적 타이머는 애플리케이션 서버가 중지되거나 활성 상태에 머물지 못할 때 취소됩니다.
지속적 타이머에서와 같이 비지속적 타이머의 작성 및 취소는 트랜잭션적입니다. 타이머가 트랜잭션 내에서 작성되고 해당 트랜잭션이 나중에 롤백되는 경우, 타이머 작성도 롤백됩니다. 비슷한 규칙이 타이머의 취소에 적용됩니다.
지속적 타이머와 스레드 풀을 공유하거나 지속적 타이머와 공유되지 않는 고유한 스레드 풀을 갖도록 비지속적 타이머를 구성할 수 있습니다.
- 프로그래밍 방식으로 작성된 타이머
-
프로그래밍 방식으로 작성된 지속적 타이머는 취소되지 않는 한 애플리케이션 서버 시스템 종료 및 다시 시작 사이에서 유지됩니다. 더 이상 원하지 않는 프로그래밍 방식으로 작성된 타이머를 삭제하는 것은 애플리케이션 코드나 시스템 관리자의 책임입니다.
엔터프라이즈 Bean과 연관된 타이머를 프로그래밍 방식으로 작성하기 위해 Bean은 적용 가능한 컨텍스트 인스턴스에서 getTimerService() 메소드를 호출하여 TimerService 오브젝트에 대한 참조를 얻습니다. Bean은 또한 TimerService 메소드 중 하나(예: createTimer)를 호출하여 Bean에 대한 타이머를 지정합니다. 이 타이머 인스턴스가 이제 사용자의 Bean과 연관됩니다. TimerService 메소드는 EJB 3.1 스펙에서 설명됩니다. 이제 타이머 인스턴스를 다른 Java™ 코드로 로컬 오브젝트로서 전달할 수 있습니다. Java 코드가 타이머 인스턴스를 확보한 후, 코드는 javax.ejb.Timer 인터페이스에 의해 정의되는 메소드 중 하나(예: cancel() 또는 getTimeRemaining() 메소드)를 사용할 수 있습니다.
클러스터 환경에서 프로그래밍 방식으로 작성된 지속적 타이머는 임의의 클러스터 멤버에서 실행할 수 있지만, 프로그래밍 방식으로 작성된 비지속적 타이머는 해당 타이머가 작성된 동일한 JVM에서만 실행합니다.
- 자동으로 작성된 타이머
- EJB 3.1 스펙은 EJB 타이머 서비스를 기능 보강하여 애플리케이션이 시작할 때 Bean 호출에 의존하여 타이머 서비스 타이머 작성 메소드 중 하나를 프로그래밍 방식으로 시작하지 않고 타이머의 자동 작성이 가능하게 합니다. 타이머를 자동으로 작성하려면 @Schedule 어노테이션 또는 timeout-method 배치 디스크립터 요소를 사용하십시오. 자동으로 작성된 타이머는 애플리케이션 배치의 결과로 컨테이너에 의해 작성됩니다.
문제점 방지: CancelEJBTimers 명령도 자동으로 작성된 타이머를 취소합니다. 자동으로 작성된 타이머가 취소될 때, 다시 작성하는 유일한 방법은 애플리케이션을 설치 제거한 후 다시 설치하는 것입니다. gotcha
- 클러스터 환경의 타이머
-
클러스터 환경에서 지속적 타이머는 해당 타이머가 작성된 동일한 클러스터 멤버일 필요는 없는 하나의 클러스터 멤버에서만 실행합니다. 비지속적 타이머는 작성된 각 클러스터 멤버에서 실행합니다. 자동 비지속적 타이머는 EJB를 포함하는 각 클러스터 멤버에서 실행합니다.
자동 지속적 타이머는 포함하는 모듈이나 애플리케이션이 설치 제거될 때 지속적 저장소에서 제거됩니다. 그러므로 롤아웃 업데이트 기능을 갖는 자동 지속적 타이머를 사용하는 애플리케이션을 업데이트하지 마십시오. 그렇게 하면 클러스터가 아직 동작 중일 때 애플리케이션을 설치 제거한 후 다시 설치합니다. 이것은 다음 경우에 실패를 유발할 수 있습니다.
- 데이터베이스 항목이 제거된 후 및 데이터베이스 항목이 다시 작성되기 전에 다른 클러스터 멤버에서 실행하는 타이머가 활성화하는 경우 타이머는 실패합니다. 이 경우에 com.ibm.websphere.scheduler.TaskPending 예외가 SCHD0057W 메시지와 함께 최초 장애 데이터 캡처(FFDC)에 기록되며, 이것은 데이터베이스의 태스크 정보가 변경 또는 취소되었음을 표시합니다.
- 데이터베이스의 타이머 데이터가 업데이트된 후 업데이트되지 않은 클러스터 멤버에서 타이머가 활성화하는 경우, 타이머는 실패하거나 새 타이머 정보가 아직 클러스터 멤버에서 실행 중인 이전 애플리케이션 코드와 호환 불가능한 경우에 다른 실패를 유발할 수 있습니다.
제품에서 프록시 서버를 사용할 때, 스케줄러가 EJB 타이머 서비스에 사용할 것으로 구성되는 경우 셀 레벨에서 스케줄러를 정의하지 마십시오. 이를 수행하면 지속적 타이머가 실행되지 않습니다. 이것은 프록시 서버가 스케줄러 리스를 가져오면 발생할 수 있습니다. 프록시 서버에서 실행하는 애플리케이션이 없으므로 스케줄러가 보내는 타이머 이벤트를 처리할 애플리케이션 코드는 없습니다.
- 재시도 및 누락된 제한시간
-
EJB 타이머를 사용하는 경우 실패, 재시도 및 누락된 제한시간의 개념을 이해해야 합니다.
- 실패는 시도하지만 성공하지 못하는 제한시간 초과 예외입니다.
- 재시도는 이전에 시도했지만 실패한 제한시간 초과를 성공적으로 실행하는 추가 시도입니다.
- 누락된 실행은 시도되었어야 하지만 사용 불가능하거나 이전에 실패한 제한시간을 재시도하느라 바빴기 때문에 시도되지 않은 제한시간입니다.
재시도 동작은 다음을 반영합니다.- 서버가 실패한 제한시간을 재시도하는 추가 횟수
- 이들 서버 재시도 사이의 간격
누락된 제한시간 동작은 다음을 반영합니다.- 서버가 결국 누락된 제한시간을 시도하는지 여부
- 누락된 제한시간이 최종적으로 시도되는 경우 해당 시도가 발생하는 시기
- 누락된 제한시간 시도 사이의 간격
표 1. 재시도 및 누락된 제한시간 동작. 지속적 및 비지속적 타이머 모두에 대한 재시도 및 누락된 제한시간 동작. 특성 기본 동작 구성 가능 재시도 횟수 성공하기 위해 수행하는 만큼입니다. 지속적 타이머는 서버에서 스케줄러 실패 임계값에 도달하는 경우 일시적으로 비활성화됩니다. 자세한 정보는 실패하는 태스크 중지에 관한 주제를 참조하십시오.
예, 비지속적 타이머의 경우 재시도 사이의 간격 첫 번째 재시도 시도는 즉각적입니다. 후속 재시도 시도는 지속적 타이머의 경우 구성된 스케줄러 폴링 간격 및 비지속적 타이머의 경우 구성된 재시도 간격으로 발생합니다.
예 누락된 제한시간 복구 모든 누락된 제한시간이 복구됩니다. 아니오 누락된 제한시간이 복구되는 시기 블로킹 재시도가 중지를 시도할 때 지속적 및 비지속적 타이머가 둘 다 누락된 제한시간을 복구합니다. 또한, 지속적 타이머는 사용 불가능 서버가 다시 시작할 때 제한시간을 복구합니다. 아니오 다음 제한시간, 재시도 시도가 성공하고 누락된 제한시간이 복구된 후 원래 스케줄된 다음 시간에 아니오 구성 가능한 특성은 지속적 타이머의 경우 스케줄러 인스턴스에서 및 비지속적 타이머의 경우 비지속적 타이머 구성에서 구성됩니다.
다음 시나리오는 재시도 및 누락된 제한시간 동작이 지속적 및 비지속적 타이머 모두에 대한 제한시간에 주는 영향을 보여줍니다.
지속적 타이머 시나리오:
지속적 타이머가 작성되어 오전 10시에 처음으로 실행한 후 그 후에는 한 시간마다 실행하도록 구성됩니다. 타이머를 지원하는 스케줄러는 30초 폴 간격을 갖고 구성됩니다.
타이머는 오전 10시에 실행하고 데이터베이스가 사용 불가능하므로 실패합니다. 타이머는 즉시 재시도되고, 스케줄러가 폴링될 때 30초마다 다시 재시도되며 오후 12시 30분까지 계속 실패합니다. 그 순간에 데이터베이스가 이제 다시 온라인이기 때문에 재시도가 성공하며, 따라서 서버는 이전에 실패한 시도 재시도를 중지합니다.
이제, 서버는 누락된 제한시간을 따라 작업하기 시작합니다. 첫 번째, 오전 11시에 실행했어야 하는 제한시간을 시도하며, 이것은 오후 12시 31분에 성공합니다. 스케줄러가 30초 후에 다시 폴링될 때 오후 12시에 실행했어야 하는 제한시간을 시도하며, 이것은 오후 12시 32분에 성공합니다. 서버는 이제 현재 상태이고, 마지막 성공 후 1시간과는 반대로 오후 1시의 원래 스케줄된 시간에 다음 제한시간 초과가 발생합니다. 오후 1시 32분이었습니다. 앞으로 가면서 원래 스케줄이 유지보수됩니다. 스케줄은 마지막으로 성공한 제한시간의 시간을 기반으로 업데이트되지 않습니다.
비지속적 타이머 시나리오:
비지속적 타이머가 작성되어 오전 10시에 처음으로 실행한 후 그 후에는 한 시간마다 실행하도록 구성됩니다. 이 비지속적 타이머는 5의 재시도 횟수와 30분의 재시도 간격을 갖도록 구성됩니다.
타이머는 오전 10시에 실행하고 데이터베이스를 사용할 수 없기 때문에 실패합니다. 타이머는 즉시 재시도되고, 다시 실패합니다. 이제, 초기 즉각적 재시도를 실행했을 때 서버는 다음 재시도 시도 사이의 30분의 구성된 재시도 간격을 기다립니다. 재시도는 오전 10시 30분과 오전 11시에 발생하며 둘 다 실패합니다. 마지막으로, 4번째 재시도는 오전 11시 30분에 발생하고, 데이터베이스가 이제 다시 온라인이므로 성공합니다.
이제, 서버는 누락된 제한시간을 따라 작업하기 시작합니다. 원래 오전 11시로 스케줄되었던 제한시간이 즉시 실행되고, 오전 11시 31분에 성공합니다. 서버는 이제 현재 상태이고, 마지막 성공 후 1시간과는 반대로 오후 12시의 원래 스케줄된 시간에 다음 제한시간 초과가 발생합니다. 오후 12시 32분이었습니다.
- getNextTimeout 및 getTimeRemaining 메소드의 동작
-
지속적 및 비지속적 타이머 둘 다의 경우, Timer.getNextTimeout 메소드가 타이머가 실행하도록 스케줄된 다음 시간을 표시하는 java.util.Date 오브젝트를 리턴합니다. 간격 또는 달력 기반 타이머에 대한 제한시간 콜백 메소드에서 getNextTimeout 메소드를 호출할 때, 메소드는 다음 스케줄된 시간을 리턴합니다. 미래의 제한시간이 없는 달력 기반 타이머의 경우 메소드는 EJB 3.1 스펙에서 필요한 대로 NoMoreTimeoutsException 예외를 발행합니다. 단일 조치 타이머에 대한 제한시간 콜백 메소드에서 getNextTimeout 메소드를 호출할 때, 메소드는 원래 스케줄된 시간을 리턴합니다. 제한시간 콜백 메소드가 실패하고 재시도가 시도되고 있는 경우, getNextTimeout 메소드가 계속해서 실패한 실행이 발생하지 않은 것처럼 원래 스케줄된 시간을 리턴합니다. 모든 경우에 Timer.getTimeRemaining 메소드가 getNextTimeout 리턴 값과 현재 시스템 시간 사이의 차이를 밀리초 단위로 리턴하는데, 이것은 스케줄된 실행 시간이 과거인 경우 음의 숫자가 될 수 있습니다.
- 자동으로 작성된 타이머의 상속 동작
-
Bean 클래스의 계층에 있는 자동 타이머 메소드는 다중 타이머가 작성되게 합니다. 타이머 메소드와 연관된 타이머 수는 소스 코드에 있는 메소드의 발생 수에 의해 판별되지 않습니다. 대신, 타이머 메소드와 연관된 타이머 수는 해당 메소드에 대한 가시성을 갖는 Bean의 수로 판별됩니다. 예를 들어 다음과 같습니다.
@Stateless public class Abean { @Schedule(hour=”1”) public void timerMethod1() @Stateless public class Bbean extends Abean { @Schedule(hour=”2”) public void timerMethod2() @Stateless public class Cbean extends Bbean { @Schedule(hour=”2”) public void timerMethod2()
이전 Bean 클래스 계층에서 콜백 메소드 Abean.timerMethod1을 갖는 세 개의 자동 타이머가 작성되는데, 해당 메소드에 대한 가시성을 갖는 각 Bean 인스턴스당 하나입니다. 콜백 메소드 Bbean.timerMethod2를 갖는 하나의 타이머가 작성되고, 해당 메소드가 Bean Cbean에 의해 대체되므로 콜백 메소드 Cbean.timerMethod2를 갖는 단 하나의 타이머가 작성됩니다.
이전 예에서 Bean Abean이 컨테이너에 의해 처리될 때 콜백 메소드 Abean.timerMethod1을 갖는 하나의 자동 타이머가 작성됩니다.
Bean Bbean이 컨테이너에 의해 처리될 때, 콜백 메소드 Bbean.timerMethod2를 갖는 자동 타이머가 작성되고 콜백 메소드 Abean.timerMethod1을 갖는 또 다른 자동 타이머가 작성됩니다.
Bean Cbean이 컨테이너에 의해 처리될 때 콜백 메소드 CBean.timerMethod2를 갖는 자동 타이머가 작성됩니다. 또 다른 자동 타이머가 콜백 메소드 Abean.timerMethod1로 작성됩니다. Bbean.timerMethod2에 대한 타이머는 Bean Cbean을 처리할 때 작성되지 않습니다. Bbean.timerMethod2는 Cbean.timerMethod2 메소드에 의해 대체되기 때문에 Cbean의 클래스 계층에서 보이지 않습니다.
@Stateless 어노테이션이 클래스 Abean 및 Bbean에서 제거되어 클래스가 Cbean이 유일한 EJB인 경우 이전 예와 비슷한 다른 예를 고려하십시오. 그 경우에 작성된 유일한 자동 타이머는 Cbean에 보이는 것들입니다. 하나는 콜백 메소드 Abean.timerMethod1을 갖고, 다른 하나는 콜백 메소드 Cbean.timerMethod2를 갖습니다.
Bean이 상속된 Bean 콜백 메소드에서 동일한 코드를 공유할 수 있지만, 런타임 동작은 다형질일 수 있습니다. 예를 들어 다음과 같습니다.
public class Employee { @Schedule(hour=”1”, dayOfMonth=”-1”, info = "payroll timer") public void getSalaryIncrease() { printChecks(salary * rate()); } protected float rate() { return (float)1.01; } } public class Manager extends Employee { protected float rate() { return (float)1.15; } } public class Executive extends Manager { protected float rate() { return (float)1.30; } }
이전 예에서 각 Bean 인스턴스는 콜백 메소드 getSalaryIncrease()를 갖는 자동 타이머를 갖습니다. 각 타이머가 동일한 콜백 코드를 공유하지만, 각 Bean에 의한 급료 인상 계산에서 사용되는 비율이 다형성으로 인해 다름을 참고하십시오. 즉, 타이머 콜백 메소드는 임의의 Java 메소드와 동일한 방법으로 다형성일 수 있습니다.
프로시저
결과
지속적 또는 비지속적인 EJB 타이머를 프로그래밍 방식으로 또는 자동으로 구성했습니다.