使用 JAX-RS 的 REST - 处理长时间运行的操作

2022-09-03 15:49:32

我有一个用 JAX-RS 实现的 REST 服务。某些操作需要很长时间才能完成,可能需要 15-30 分钟。对于这些情况,我的倾向是调度一个后台线程来处理长时间运行的操作,然后立即响应HTTP状态202 ACCEPTED。响应将包含一个位置标头,其中包含一个 url,客户端可以使用该 URL 来轮询进度。

此方法需要创建线程来处理长时间运行的操作,以便可以立即返回 202 ACCEPTED。我也知道,在Java EE容器中创建自己的线程通常是不好的做法!

我的问题如下:

  1. 人们是否同意这是一个正确的方法?
  2. 假设它是正确的,人们是否可以推荐一个“良好实践”解决方案,使我能够在后台调度长时间运行的操作并立即返回?

另外,为了避免管理我自己的线程,我研究了 JAX-RS 异步服务器 API。不幸的是,尽管这提高了服务器吞吐量,但它不允许我立即使用“接受”进行响应。

泽西岛声明如下:

Note that the use of server-side asynchronous processing model will not improve the 
request processing time perceived by the client. It will however increase the
throughput of the server, by releasing the initial request processing thread back to
the I/O container while the request may still be waiting in a queue for processing or    
the processing may still be running on another dedicated thread. The released I/O  
container thread can be used to accept and process new incoming request connections.

任何帮助是值得赞赏的。谢谢!


答案 1

我也知道,在Java EE容器中创建自己的线程通常是不好的做法!

尽管在大多数情况下上述情况是正确的,但在这种情况下,您别无选择。至少不要自己创建实例。让我们为您做吧。如果有的话,让它有一个足够大的池,并与所有组件共享。ThreadExecutorServiceExecutorService


答案 2

我认为泽西异步文档很好地穷尽了这个话题。下面是一个简短的片段:

@Path("/async/longRunning")
public class MyResource {

   @GET
   public void longRunningOp(@Suspended final AsyncResponse ar) {
       executor.submit(
            new Runnable() {
                public void run() {
                    executeLongRunningOp();
                    ar.resume("Hello async world!");
                } });
  }
}

当涉及到以下来自文档的引用时:

请注意,使用服务器端异步处理模型不会改善客户端感知到的请求处理时间。(...)

我覺得你誤解了一點。文档的作者试图在这里表达的是,异步处理本身不会加速事情。但是,可以使用以下命令立即返回响应:

return Response.status(Status.ACCEPTED).build();