我使用JAX-RS实现了REST服务。有些操作需要很长时间才能完成,可能需要15-30分钟。对于这些情况,我倾向于派遣后台线程来处理长时间运行的操作,然后立即响应HTTP状态202 ACCEPTED。响应将包含一个带有URL的位置标头,客户端可以使用该标头来轮询进度。
此方法需要创建线程来处理长时间运行的操作,以便可以立即返回202 ACCEPTED。我也知道在Java EE容器中创建自己的线程通常是不好的做法!
我的问题如下:
另外,为了避免管理我自己的线程,我查看了JAX-RS异步服务器api。不幸的是,虽然这提高了服务器吞吐量,但它不允许我立即用ACCEPTED响应。
泽西岛声明如下:
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.
感谢任何帮助。谢谢!
答案 0 :(得分:4)
我也知道在Java EE容器中创建自己的线程通常是不好的做法!
虽然在大多数情况下都是如此,但在这个案例中你没有选择。至少不要自己创建Thread
实例。让ExecutorService
为你做。如果有的话,让这个ExecutorService
有一个足够大的池并与你的所有组件共享。
答案 1 :(得分:2)
我认为Jersey Async docs很好地用尽了这个话题。这是一个简短的片段:
@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();
答案 2 :(得分:0)
我会创建一个方法,它会立即返回响应,其中包含进程ID和完成时间。计算从后台开始,并在完成后缓存一段时间。然后,客户端尝试检索具有特定ID的信息并获得相关响应。