48.5.2. 시간 초과 및 시간 제한 핸들러
48.5.2.1. 개요
비동기 처리 모델은 REST 호출 시 시간 초과도 지원합니다. 기본적으로 시간 초과로 인해 HTTP 오류 응답이 클라이언트로 다시 전송됩니다. 그러나 시간 초과 처리기 콜백을 등록하는 옵션도 있으므로 시간 초과 이벤트에 대한 응답을 사용자 지정할 수 있습니다.But you also have the option of registering a timeout handler callback, which enables you to customize the response to a timeout event.
48.5.2.2. 처리기 없이 타임아웃 설정 예
시간 초과를 지정하지 않고 간단한 호출 타임아웃을 정의하려면 다음 예제와 같이 AsyncResponse
오브젝트에서 setTimeout
메서드를 호출합니다.
// Java // Java ... import java.util.concurrent.TimeUnit; ... import javax.ws.rs.GET; import javax.ws.rs.NotFoundException; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.container.AsyncResponse; import javax.ws.rs.container.Suspended; import javax.ws.rs.container.TimeoutHandler; @Path("/bookstore") public class BookContinuationStore { ... @GET @Path("/books/defaulttimeout") public void getBookDescriptionWithTimeout(@Suspended AsyncResponse async) { async.setTimeout(2000, TimeUnit.MILLISECONDS); // Optionally, send request to executor queue for processing // ... } ... }
java.util.concurrent.TimeUnit
클래스에서 언제든지 시간 단위를 사용하여 시간 초과 값을 지정할 수 있습니다. 위 예제는 요청을 executor 스레드 풀로 보내는 코드를 표시하지 않습니다. 시간 제한 동작을 테스트하려는 경우 리소스 메서드 본문에 async.SetTimeout
호출만 포함하고 모든 호출에 시간 초과가 트리거될 수 있습니다.
AsyncResponse.NO_TIMEOUT
값은 무한한 타임아웃을 나타냅니다.
48.5.2.3. 기본 타임아웃 동작
기본적으로 호출 타임아웃이 트리거되면 JAX-RS 런타임에서 ServiceUnavailableException
예외를 발생시키고 상태 503
을 사용하여 HTTP 오류 응답을 반환합니다.
48.5.2.4. TimeoutHandler 인터페이스
시간 제한 동작을 사용자 정의하려면 TimeoutHandler
인터페이스를 구현하여 시간 초과 처리기를 정의해야 합니다.
// Java package javax.ws.rs.container; public interface TimeoutHandler { public void handleTimeout(AsyncResponse asyncResponse); }
구현 클래스에서 handleTimeout
메서드를 재정의하면 시간 제한을 처리하기 위해 다음 방법 중 하나를 선택할 수 있습니다.
-
asyncResponse.cancel
메서드를 호출하여 응답을 취소합니다. -
response 값을 사용하여
asyncResponse.resume
메서드를 호출하여 응답을 보냅니다. -
asyncResponse.setTimeout
메서드를 호출하여 대기 기간을 확장합니다. (예를 들어, 10초 이상 기다리려면asyncResponse.setTimeout(10, TimeUnit.SECONDS)
을 호출할 수 있습니다.
48.5.2.5. 처리기를 사용하여 시간 제한 설정 예
시간제한 처리기를 사용하여 호출 시간을 정의하려면 다음 예제와 같이 AsyncResponse
개체에서 setTimeout
메서드 및 setTimeoutHandler
메서드를 모두 호출합니다.
// Java ... import javax.ws.rs.GET; import javax.ws.rs.NotFoundException; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.container.AsyncResponse; import javax.ws.rs.container.Suspended; import javax.ws.rs.container.TimeoutHandler; @Path("/bookstore") public class BookContinuationStore { ... @GET @Path("/books/cancel") public void getBookDescriptionWithCancel(@PathParam("id") String id, @Suspended AsyncResponse async) { async.setTimeout(2000, TimeUnit.MILLISECONDS); async.setTimeoutHandler(new CancelTimeoutHandlerImpl()); // Optionally, send request to executor queue for processing // ... } ... }
여기서 이 예제에서는 호출 타임아웃을 처리하기 위해 CancelTimeoutHandlerImpl
타임아웃 핸들러의 인스턴스를 등록합니다.
48.5.2.6. 시간 초과 처리기를 사용하여 응답을 취소
CancelTimeoutHandlerImpl
시간제한 핸들러는 다음과 같이 정의됩니다.
// Java ... import javax.ws.rs.container.AsyncResponse; ... import javax.ws.rs.container.TimeoutHandler; @Path("/bookstore") public class BookContinuationStore { ... private class CancelTimeoutHandlerImpl implements TimeoutHandler { @Override public void handleTimeout(AsyncResponse asyncResponse) { asyncResponse.cancel(); } } ... }
AsyncResponse
오브젝트에 대한 호출 취소
효과는 HTTP 503 (서비스 사용할 수 없음
) 오류 응답을 클라이언트에 보내는 것입니다. 응답 메시지에 Retry-After:
HTTP 헤더를 설정하는 데 사용되는 cancel
메서드( int
또는 java.util.Date
값)에 대한 인수를 선택적으로 지정할 수 있습니다. 그러나 클라이언트는 종종 Retry-After:
헤더를 무시합니다.
48.5.2.7. 실행 가능한 인스턴스에서 취소된 응답 처리
실행 가능 스레드 풀에서 처리를 위해 대기 중인 실행 가능한 인스턴스로 캡슐화된 경우 스레드 풀이 요청을 처리하는 시점에 AsyncResponse가 취소되었음을 확인할 수 있습니다.If you have encapsulated a suspended request as a Runnable
instance, which is queued for processing in an executor thread pool, you might find that the AsyncResponse
has been canceled by the time the thread pool gets around to processing the request. 이러한 이유로 Runnable
인스턴스에 일부 코드를 추가하여 취소된 AsyncResponse
개체에 대처할 수 있습니다. 예를 들면 다음과 같습니다.
// Java ... @Path("/bookstore") public class BookContinuationStore { ... private void sendRequestToThreadPool(final String id, final AsyncResponse response) { executor.execute(new Runnable() { public void run() { if ( !response.isCancelled() ) { // Process the suspended request ... // ... } } }); } ... }