简体   繁体   English

异步JAX-RS的目的是什么

[英]What is the purpose of asynchronous JAX-RS

I'm reading "RESTful Java with JAX-RS 2.0" book. 我正在阅读“使用JAX-RS 2.0的RESTful Java”一书。 I'm completely confused with asynchronous JAX-RS, so I ask all questions in one. 我完全混淆了异步JAX-RS,所以我把所有问题都集中在一起。 The book writes asynchronous server like this: 这本书写了这样的异步服务器:

@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: 我的问题:

  1. In example 1 and 2 web server thread(the one that handle request) dies and we create another background thread. 在示例1和2 Web服务器线程(处理请求的线程)死亡,我们创建另一个后台线程。 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. 一个线程死亡,另一个线程诞生。
  2. 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中使用并发实用程序来使用托管线程。
  3. Again one of ideas behind async servers is to scale. 异步服务器背后的一个想法是扩展。 Example 3 does not scale, does it? 例3没有缩放,是吗?

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. 在示例1和2 Web服务器线程(处理请求的线程)死亡,我们创建另一个后台线程。 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. 一个线程死亡,另一个线程诞生。

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 (eg, its own Spring bean). 在生产服务中,您不会将执行程序保存在这样的私有字段中,而是将其作为单独配置的对象(例如,它自己的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. 由bean /托管资源系统组成的应用程序必须从头开始构建。 It's also not very important for small-scale work to be very careful about this, and that's a lot of web applications. 对于小规模的工作而言,要非常小心这一点并不是很重要,这就是很多 Web应用程序。

The gripping hand is 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. 如果服务器重新启动,您可能会丢失所有连接,并且如果这些AsyncResponse对象在某种程度上不可Serializable (不保证它们是否可用),则无法将它们存储在数据库中以启用恢复。 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.) (如果他们没有得到任何回复,客户也会在一段时间后超时;你不能无限期地持有它们。)

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网络连接,这绝不容易完全存储和恢复。)

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. 我分享你在问题1中表达的观点。让我简单地添加一个网络服务器线程不会死的细节,它通常来自一个池,并为另一个Web请求释放自己。 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. 我完全没有看到任何意义。

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

The throughput of the service improves if different thread pools manage request I/O and request processing. 如果不同的线程池管理请求I / O和请求处理,则服务的吞吐量会提高。 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线程允许它接收下一个请求,准备处理并在请求处理线程释放时提供给请求处理线程池。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM