48.5.2. 超时和超时处理程序


概述

异步处理模型还支持在 REST 调用时实现超时。默认情况下,超时会导致将 HTTP 错误响应发送到客户端。但是,您还可以选择注册超时处理器回调,它可让您自定义对超时事件的响应。

设置没有处理程序的超时示例

要定义简单的调用超时,但不指定 timeout 处理程序,在 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 值代表无限超时。

默认超时

默认情况下,如果触发调用超时,JAX-RS 运行时会引发 ServiceUnavailableException 异常,并发送 HTTP 错误响应,其状态为 503

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 Handler 方法和 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 timeout 处理程序实例,以处理调用超时。

使用超时处理程序取消响应

CancelTimeoutHandlerImpl timeout 处理程序定义如下:

// 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 (服务不可用)错误响应。您可以选择为 cancel 方法指定参数( intjava.util.Date 值),该值将用于在响应消息中设置 Retry-After: HTTP 标头。但是,客户端通常忽略 Retry-After: 标头。

在可运行的实例中处理取消响应

如果您将暂停请求封装为可运行的实例,它会在 executor 线程池中排队处理,您可能会发现线程池围绕处理请求时已取消 AsyncResponse 已取消。因此,您很难将一些代码添加到可运行的实例,使它能处理已取消的 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

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.