[英]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线程和工作线程通常有不同的要求:
对于一个简单的应用程序,如果您使端点同步或异步并不重要; 但在一般情况下,每秒请求数量相当,具有不同特征的不同任务(处理时间,产生自己的子线程的需要,优先级),使端点异步是获得高响应系统的最佳方式有效利用资源。
默认情况下,服务器上的请求处理以同步模式工作,这意味着每个请求都在单个HTTP线程中处理。 请求处理完成后,线程将返回到线程池。 当资源方法执行花费很短的时间并且并发连接的数量相对不是很高时,这不是很重要。 在异步模式下,线程在请求处理完成之前返回到线程池。 然后在另一个称为Worker的线程中继续请求处理。 释放的I / O线程可用于接受新的传入请求。 在许多情况下,只有少数线程可以同时处理大量请求,因此可以显着减少处理传入请求所需的线程数。 通过使用更少的线程,我们既可以节省内存又可以提高性能(通过减少线程上下文切换)
这可能会让你有点困惑。看看这个链接
从客户的角度来看,服务性能有两个主要方面。 服务客户关心:
很容易只关心吞吐量,但在某个时刻,尝试实现吞吐量将开始对延迟产生负面影响。 多线程在某种程度上不是免费的 。
Netbeans提示只会提高吞吐量 ,但就像你推断的那样,它对延迟没有任何帮助 - 这完全取决于你,萌芽。 如果此时应用程序不关心吞吐量,则可以放心地忽略该提示。
所有JAX-RS服务都没有要求甚至是经验法则都是异步的 ,这只是Netbeans开发团队的一次飞跃(这是一个非常自信的飞跃,考虑到这是他们认为我们不需要的一个暗示禁用 。
Jersey确实提供了一些解决延迟限制的建议,但事实仍然是它没有魔力:服务器端操作将花费所需的时间,客户端没有选择,只能等待它完成,除非执行一些回调模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.