繁体   English   中英

Java EE 中的每个 REST 端点都应该是异步的吗?

[英]Should every REST endpoint be asynchronous in Java EE?

使用 Netbeans 并编写任意 REST 端点时,NetBeans 始终显示警告,指出该方法可以转换为异步方法。

例如,我创建了以下方法:

@GET
@Path("/test")
public String hello() {
    return "Hello World!";
}

NetBeans 然后显示警告,见下文:

转换为异步

单击工具提示会生成以下代码:

private final ExecutorService executorService = java.util.concurrent.Executors.newCachedThreadPool();

@GET
@Path(value = "/test")
public void hello(@Suspended final AsyncResponse asyncResponse) {
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            asyncResponse.resume(doHello());
        }
    });
}

private String doHello() {
    return "Hello World!";
}

创建 PUT 或 POST 方法时也是如此。 由于 NetBeans 在实现 REST 端点时总是显示警告,这告诉我编写同步端点被认为是错误/不好的做法。 那么,每个 REST 端点都应该是异步的吗? 为什么?

同步

  • 该工作在与IO相同的线程中完成。 所有线程都在同一个池中。
  • 接受请求需要100毫秒; 做这项工作需要900毫秒; 总共1秒。
  • 如果您希望能够接受 100个请求/秒,则需要100个IO线程。
  • 如果您希望能够满足 100个请求/秒,则需要相同的100个IO线程。

异步

  • 这项工作是在与IO不同的线程中完成的。 您有两个不同的线程池。
  • 接受请求仍需要100毫秒; 总共100毫秒。
  • 如果您希望能够接受 100 req / s,则池中只需要10个IO线程。
  • 工作仍需要900毫秒; 总共900毫秒。
  • 如果您希望能够满足 100个请求/秒,则需要90个工作线程。

两种情况下的初始线程数是相同的,是的。
但是,IO线程和工作线程通常有不同的要求:

  • 希望您的IO线程保持活动状态,以便更快地处理请求?
    • 使用sync / one pool,您必须为所有100个线程执行此操作; 使用异步/多个池,您只能为10个IO线程执行此操作。
  • 有些任务需要更长时间吗?
    • 通过同步,您必须增加IO池大小以保持同步; 使用async,您仍然可以使用10个IO线程获取100 req / s并且增加Worker线程池的大小,或者返回503 / 429/269以指示重载,或者甚至创建具有不同属性的多个Worker线程池以更好适合你的工作量; 说到哪......
  • 想要从不同类型的任务使用不同类型的线程池中受益吗?
    • 在异步模式下,您可以自由地创建具有不同配置的多个池,并使用最适合每个任务的池,同时保持IO线程池的独立性。 在只有一个池的同步模式下,你就是不能这样做。

对于一个简单的应用程序,如果您使端点同步或异步并不重要; 但在一般情况下,每秒请求数量相当,具有不同特征的不同任务(处理时间,产生自己的子线程的需要,优先级),使端点异步是获得高响应系统的最佳方式有效利用资源。

默认情况下,服务器上的请求处理以同步模式工作,这意味着每个请求都在单个HTTP线程中处理。 请求处理完成后,线程将返回到线程池。 当资源方法执行花费很短的时间并且并发连接的数量相对不是很高时,这不是很重要。 在异步模式下,线程在请求​​处理完成之前返回到线程池。 然后在另一个称为Worker的线程中继续请求处理。 释放的I / O线程可用于接受新的传入请求。 在许多情况下,只有少数线程可以同时处理大量请求,因此可以显着减少处理传入请求所需的线程数。 通过使用更少的线程,我们既可以节省内存又可以提高性能(通过减少线程上下文切换)

这可能会让你有点困惑。看看这个链接

从客户的角度来看,服务性能有两个主要方面。 服务客户关心:

  1. 吞吐量 ,即您的服务可以处理多少个并发请求?

  2. 延迟 ,即一个请求在获得响应之前必须等待多长时间?

很容易只关心吞吐量,但在某个时刻,尝试实现吞吐量将开始对延迟产生负面影响。 多线程在某种程度上不是免费的

Netbeans提示只会提高吞吐量 ,但就像你推断的那样,它对延迟没有任何帮助 - 这完全取决于你,萌芽。 如果此时应用程序不关心吞吐量,则可以放心地忽略该提示。

所有JAX-RS服务都没有要求甚至是经验法则都是异步的 ,这只是Netbeans开发团队的一次飞跃(这是一个非常自信的飞跃,考虑到这是他们认为我们不需要的一个暗示禁用

Jersey确实提供了一些解决延迟限制的建议,但事实仍然是它没有魔力:服务器端操作将花费所需的时间,客户端没有选择,只能等待它完成,除非执行一些回调模式。

暂无
暂无

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

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