Java 异步 JAX-RS 的目的是什么
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21146651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the purpose of asynchronous JAX-RS
提问by Majid Azimi
I'm reading "RESTful Java with JAX-RS 2.0" book. I'm completely confused with asynchronous JAX-RS, so I ask all questions in one. The book writes asynchronous server like this:
我正在阅读“带有 JAX-RS 2.0 的 RESTful Java”一书。我完全对异步 JAX-RS 感到困惑,所以我将所有问题合二为一。这本书写异步服务器是这样的:
@Path("/customers")
public class CustomerResource {
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_XML)
public void getCustomer(@Suspended final AsyncResponse asyncResponse,
@Context final Request request,
@PathParam(value = "id") final int id) {
new Thread() {
@Override
public void run() {
asyncResponse.resume(Response.ok(new Customer(id)).build());
}
}.start();
}
}
Netbeans creates asynchronous server like this:
Netbeans 像这样创建异步服务器:
@Path("/customers")
public class CustomerResource {
private final ExecutorService executorService = java.util.concurrent.Executors.newCachedThreadPool();
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_XML)
public void getCustomer(@Suspended final AsyncResponse asyncResponse,
@Context final Request request,
@PathParam(value = "id") final int id) {
executorService.submit(new Runnable() {
@Override
public void run() {
doGetCustomer(id);
asyncResponse.resume(javax.ws.rs.core.Response.ok().build());
}
});
}
private void doGetCustomer(@PathParam(value = "id") final int id) {
}
}
Those that do not create background threads use some locking methods to store response objects for further processing. This example is for sending stock quotes to clients:
那些不创建后台线程的使用一些锁定方法来存储响应对象以供进一步处理。此示例用于向客户发送股票报价:
@Path("qoute/RHT")
public class RHTQuoteResource {
protected List<AsyncResponse> responses;
@GET
@Produces("text/plain")
public void getQuote(@Suspended AsyncResponse response) {
synchronized (responses) {
responses.add(response);
}
}
}
responses
object will be shared with some background jobs and it will send quote to all clients when it is ready.
responses
对象将与一些后台作业共享,并在准备好时将报价发送给所有客户端。
My questions:
我的问题:
- In example 1 and 2 web server thread(the one that handle request) dies and we create another background thread. The whole idea behind asynchronous server is to reduce idle threads. These examples are not reducing idle threads. One threads dies and another one born.
- I thought creating unmanaged threads inside container is a bad idea. We should only use managed threads using concurrency utilities in Java EE 7.
- Again one of ideas behind async servers is to scale. Example 3 does not scale, does it?
- 在示例 1 和 2 中,Web 服务器线程(处理请求的线程)死亡,我们创建了另一个后台线程。异步服务器背后的整个想法是减少空闲线程。这些示例并没有减少空闲线程。一根线死去,另一根诞生。
- 我认为在容器内创建非托管线程是个坏主意。我们应该只在 Java EE 7 中使用使用并发实用程序的托管线程。
- 同样,异步服务器背后的想法之一是扩展。示例 3 无法扩展,是吗?
采纳答案by Donal Fellows
Executive Summary:You're over-thinking this.
执行摘要:你想多了。
In example 1 and 2 web server thread(the one that handle request) dies and we create another background thread. The whole idea behind asynchronous server is to reduce idle threads. These examples are not reducing idle threads. One threads dies and another one born.
在示例 1 和 2 中,Web 服务器线程(处理请求的线程)死亡,我们创建了另一个后台线程。异步服务器背后的整个想法是减少空闲线程。这些示例并没有减少空闲线程。一根线死去,另一根诞生。
Neither is particularly great, to be honest. In a production service, you wouldn't hold the executor in a private field like that but instead would have it as a separately configured object (e.g., its own Spring bean). On the other hand, such a sophisticated example would be rather harder for you to understand without a lot more context; applications that consist of systems of beans/managed resources have to be built to be that way from the ground up. It's also not very important for small-scale work to be very careful about this, and that's a lotof web applications.
老实说,两者都不是特别好。在生产服务中,您不会像这样将 executor 保存在私有字段中,而是将其作为单独配置的对象(例如,它自己的 Spring bean)。另一方面,如果没有更多的上下文,这样一个复杂的例子会让你更难理解。由 bean/托管资源系统组成的应用程序必须从头开始构建。对于小规模的工作来说,非常小心这一点也不是很重要,那是很多Web 应用程序。
The gripping handis that the recovery from server restart is actually not something to worry about too much in the first place. If the server restarts you'll probably lose all the connections anyway, and if those AsyncResponse
objects aren't Serializable
in some way (no guarantee that they are or aren't), you can't store them in a database to enable recovery. Best to not worry about it too much as there's not much you can do! (Clients are also going to time out after a while if they don't get any response back; you can't hold them indefinitely.)
令人抓狂的是,从服务器重启中恢复实际上并不是首先需要担心的事情。如果服务器重新启动,您无论如何都可能会丢失所有连接,并且如果这些AsyncResponse
对象不是Serializable
以某种方式存在(不能保证它们是或不是),则您无法将它们存储在数据库中以启用恢复。最好不要太担心,因为你无能为力!(如果客户没有得到任何回复,他们也会在一段时间后超时;你不能无限期地保留他们。)
I thought creating unmanaged threads inside container is a bad idea. We should only use managed threads using concurrency utilities in Java EE 7.
我认为在容器内创建非托管线程是个坏主意。我们应该只在 Java EE 7 中使用使用并发实用程序的托管线程。
It's an example! Supply the executor from outside however you want for your fancy production system.
这是一个例子!从外部为您花哨的生产系统提供您想要的执行器。
Again one of ideas behind async servers is to scale. Example 3 does not scale, does it?
同样,异步服务器背后的想法之一是扩展。示例 3 无法扩展,是吗?
It's just enqueueing an object on a list, which isn't a very slow operation at all, especially when compared with the cost of all the networking and deserializing/serializing going on. What it doesn't show is the other parts of the application which take things off that list, perform the processing, and yield the result back; they could be poorly implemented and cause problems, or they could be done carefully and the system work well.
它只是将一个对象排入列表中,这根本不是一个非常慢的操作,尤其是与所有网络和反序列化/序列化的成本相比时。它没有显示的是应用程序的其他部分,这些部分从列表中删除内容,执行处理并返回结果;它们可能执行不力并导致问题,或者它们可以小心执行并且系统运行良好。
If you can do it better in your code, by all means do so. (Just be aware that you can't store the work items in the database, or at least you can't know for sure that you can do that, even if it happens to be actually possible. I doubt it though; there's likely information about the TCP network connection in there, and that's never easy to store and restore fully.)
如果您可以在代码中做得更好,请务必这样做。(请注意,您无法将工作项存储在数据库中,或者至少您无法确定是否可以这样做,即使它碰巧实际上是可能的。不过我对此表示怀疑;可能有信息关于那里的 TCP 网络连接,并且完全存储和恢复绝非易事。)
回答by Jan Marti?ka
I share your view expressed in question 1. Let me just add a little detail that the webserver thread doesn't die, it typically comes from a pool and frees itself for another web request. But that doesn't really change much in terms of efficiency of async processing. In those examples, async processing is merely used to pass the processing from one thread pool to another. I don't see any point at all in that.
我同意您在问题 1 中表达的观点。让我添加一点细节,即网络服务器线程不会死亡,它通常来自池并为另一个网络请求释放自己。但这在异步处理的效率方面并没有真正改变。在这些示例中,异步处理仅用于将处理从一个线程池传递到另一个线程池。我看不出这有任何意义。
But there is one use-case where I think async makes sense, eg. when you want to register multiple clients to wait for an event and send a response to all of them once the event occurs. It is described in this article: http://java.dzone.com/articles/whats-new-jax-rs-20
但是有一个用例我认为异步是有意义的,例如。当您想要注册多个客户端以等待事件并在事件发生后向所有客户端发送响应时。它在这篇文章中有描述:http: //java.dzone.com/articles/whats-new-jax-rs-20
回答by user183037
The throughput of the service improves if different thread pools manage request I/O and request processing. Freeing up the request-I/O thread managed by the container allows it to receive the next request, prepare it for processing and feed into the request-processing-thread-pool when a request-processing-thread has been released.
如果不同的线程池管理请求 I/O 和请求处理,则服务的吞吐量会提高。释放由容器管理的请求 I/O 线程允许它接收下一个请求,为处理做好准备,并在请求处理线程被释放时送入请求处理线程池。