検索

48.5.2. タイムアウトおよびタイムアウトハンドラー

download PDF

概要

非同期処理モデルには、REST 呼び出しにタイムアウトを指定するサポートがあります。デフォルトでは、タイムアウトになると HTTP エラー応答がクライアントに送信されます。ただし、タイムアウトハンドラーコールバックを登録するオプションもあります。これにより、タイムアウトイベントへの応答をカスタマイズできます。

ハンドラーなしでタイムアウトを設定する例

タイムアウトハンドラーを指定せずに単純な呼び出しタイムアウトを定義するには、以下の例のように 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 クラスの任意の時間単位を使用して、タイムアウト値を指定できることに注意してください。上記の例では、要求をエグゼキュータースレッドプールに送信するコードは提示されていません。タイムアウトの動作をテストするだけであれば、リソースメソッド本文に async.SetTimeout への呼び出しのみを含めると、タイムアウトは呼び出しごとにトリガーされます。

AsyncResponse.NO_TIMEOUT の値は無限のタイムアウトを表します。

デフォルトのタイムアウト動作

デフォルトでは、呼び出しタイムアウトがトリガーされると、JAX-RS ランタイムが ServiceUnavailableException 例外を発生させ、ステータス 503 で HTTP エラーの応答を返します。

TimeoutHandler インターフェイス

タイムアウトの動作をカスタマイズする場合は、TimeoutHandler インターフェイスを実装してタイムアウトハンドラーを定義する必要があります。

// Java
package javax.ws.rs.container;

public interface TimeoutHandler {
    public void handleTimeout(AsyncResponse asyncResponse);
}

実装クラスで handleTimeout メソッドを上書きする場合は、タイムアウトを処理する次の方法のいずれかを選択できます。

  • asyncResponse.cancel メソッドを呼び出すことで、レスポンスを取り消します。
  • レスポンス値で asyncResponse.resume メソッドを呼び出すことで、レスポンスを送信します。
  • asyncResponse.setTimeout メソッドを呼び出すことで、待機期間を延長します。たとえば、さらに 10 秒間待つには、 asyncResponse.setTimeout(10, TimeUnit.SECONDS) を呼び出しできます。

ハンドラーでタイムアウトを設定する例

タイムアウトハンドラーで呼び出しタイムアウトを定義するには、以下の例のように 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 タイムアウトハンドラーのインスタンスを登録します。

タイムアウトハンドラーを使用した応答の取り消し

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 オブジェクト上で cancel を呼び出す効果は、クライアントに HTTP 503 (Service unavailable) エラーの応答を送信することです。任意で、cancel メソッド (int または java.util.Date の値) の引数を指定できます。これは応答メッセージで Retry-After: HTTP ヘッダーを設定するために使用されます。ただし、クライアントは多くの場合で Retry-After: ヘッダーを無視します。

Runnable インスタンスでの取り消し済みの応答への対応

エグゼキュータースレッドプールで処理のためにキューに格納された Runnable インスタンスとして、一時停止されたリクエストをカプセル化した場合、スレッドプールがリクエストを処理するまでに AsyncResponse がキャンセルされる可能性があります。このため、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 ...
                    // ...
                }
            }
        });

    }
    ...
}
Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

© 2024 Red Hat, Inc.