【问题标题】:What is the purpose of asynchronous JAX-RS异步 JAX-RS 的目的是什么
【发布时间】:2015-11-01 10:08:37
【问题描述】:

我正在阅读“带有 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 像这样创建异步服务器:

@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) {
    }
}

那些不创建后台线程的人使用一些锁定方法来存储响应对象以供进一步处理。此示例用于向客户发送股票报价:

@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 对象将与一些后台作业共享,并在准备好时将报价发送给所有客户端。

我的问题:

  1. 在示例 1 和 2 中,Web 服务器线程(处理请求的线程)死了 我们创建另一个后台线程。背后的整个想法 异步服务器是为了减少空闲线程。这些例子是 不减少空闲线程。一个线程死了,另一个线程诞生了。
  2. 我认为在容器内创建非托管线程是个坏主意。 我们应该只使用使用并发实用程序的托管线程 Java EE 7。
  3. 同样,异步服务器背后的一个想法是扩展。示例 3 无法扩展,是吗?

【问题讨论】:

    标签: java web-services rest asynchronous jax-rs


    【解决方案1】:

    执行摘要:你想多了。


    在示例 1 和 2 中,Web 服务器线程(处理请求的线程)死了,我们创建了另一个后台线程。异步服务器背后的整个想法是减少空闲线程。这些示例并没有减少空闲线程。一个线程死了,另一个线程诞生了。

    说实话,两者都不是特别好。在生产服务中,您不会将执行程序保存在这样的私有字段中,而是将其作为单独配置的对象(例如,它自己的 Spring bean)。另一方面,如果没有更多上下文,您将很难理解这样一个复杂的示例。必须从头开始构建由 bean/托管资源系统组成的应用程序。对于小规模的工作来说,非常小心这一点也不是很重要,这是很多的网络应用程序。

    The gripping hand 是服务器重启后的恢复其实一开始就不用太担心。如果服务器重新启动,无论如何您可能会丢失所有连接,并且如果那些 AsyncResponse 对象不是 Serializable 在某些方面(不保证它们是或不是),您不能将它们存储在数据库以启用恢复。最好不要太担心它,因为你无能为力! (如果客户没有得到任何回复,他们也会在一段时间后超时;您不能无限期地持有他们。)

    我认为在容器内创建非托管线程是个坏主意。我们应该只在 Java EE 7 中使用使用并发实用程序的托管线程。

    这是一个例子!为您的精美生产系统提供所需的外部执行器。

    同样,异步服务器背后的一个想法是扩展。示例 3 无法扩展,是吗?

    它只是将一个对象排入列表中,这根本不是一个非常慢的操作,尤其是与所有网络和反序列化/序列化的成本相比。它没有显示的是应用程序的其他部分,它们从列表中删除内容、执行处理并返回结果;它们可能执行不力并导致问题,或者它们可以小心执行并且系统运行良好。

    如果您可以在代码中做得更好,一定要这样做。 (请注意,您不能将工作项存储在数据库中,或者至少您不能确定是否可以这样做,即使它碰巧实际上是可能的。不过我对此表示怀疑;可能有信息关于那里的 TCP 网络连接,而这从来都不容易完全存储和恢复。)

    【讨论】:

      【解决方案2】:

      我同意你在问题 1 中表达的观点。让我补充一点细节,即网络服务器线程不会死掉,它通常来自池并为另一个网络请求释放自己。但这在异步处理的效率方面并没有真正改变。在这些示例中,异步处理仅用于将处理从一个线程池传递到另一个线程池。我看不出有什么意义。

      但是有一个用例我认为异步是有意义的,例如。当您想要注册多个客户端以等待事件并在事件发生后向所有客户端发送响应时。在这篇文章中有描述:http://java.dzone.com/articles/whats-new-jax-rs-20

      【讨论】:

        【解决方案3】:

        如果不同的线程池管理请求 I/O 和请求处理,则服务的吞吐量会提高。释放由容器管理的 request-I/O 线程允许它接收下一个请求,为处理做好准备,并在请求处理线程被释放时馈入 request-processing-thread-pool。

        【讨论】:

          猜你喜欢
          • 2011-06-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-07
          • 2017-12-04
          • 2017-07-26
          • 2022-12-15
          相关资源
          最近更新 更多