当前位置: 首页 > 后端技术 > Java

[翻译]Javaweb应用和虚拟线程

时间:2023-04-01 15:24:26 Java

简介Loom项目的目标是为JRE带来易用、高吞吐、轻量级的并发。Loom的一个特性是虚拟线程。在本文中,我们将探讨在部署在Tomcat上的简单Web应用程序上使用虚拟线程意味着什么。高吞吐量/轻量级第一个实验是将使用Tomcat的标准线程池的开销与使用虚拟线程的执行程序的开销进行比较。本文末尾给出了测试环境。使用每秒平均请求数检查不同响应大小和请求并发性的性能。结果如下图所示。结果表明,一般来说,创建新的虚拟线程来处理请求的开销小于从线程池中获取平台线程的开销。在线程池测试中看到的一个意外结果是,对于较小的响应主体,2个并发用户平均每秒发出的请求少于单个用户。调查发现,在任务传递给Executor和Executor调用任务的run()方法之间发生了额外的延迟。这种差异在4个并发用户时减少,在8个并发用户时几乎消失。在高并发级别,当并发任务多于可用处理器内核时,虚拟线程执行器再次显示出更高的性能。这在具有较小响应体的测试中更为明显。根据图中的测试,(译者注:当responsebody小于4k时,并发越大越明显。如果小于16K,会有一定的提升。如果更大,它与标准线程池没有太大区别易于使用第二个实验将使用标准线程池的Servlet异步I/O获得的性能与使用基于虚拟线程的执行器的简单阻塞I/O获得的性能进行比较.虚拟线程的潜在好处是简单性。相对于等效的Servlet异步读取,阻塞读写比写入要简单很多,尤其是在考虑错误处理的时候。Servlet异步I/O经常被用来访问一些有明显延迟的外部服务在服务类中为此测试Web应用程序与基于虚拟线程的执行程序一起使用的servlet以阻塞方式访问服务,而与标准线程池一起使用的servlet使用Servlet异步API访问服务。不涉及网络IO,但这不应该影响结果。否正如预期的那样,初始测试显示阻塞方法和异步方法之间没有可测量的差异,因为时间主要由5秒延迟决定。为了探索没有延迟影响的差异,将延迟减少到零,并进行了一组与吞吐量测试类似的测试。结果如下图所示:同样,我们看到虚拟线程通常性能更高,差异在低并发性和并发性超过可用于测试的处理器内核数量时最为明显。分析基于虚拟线程的执行器和Tomcat的标准线程池之间的差异并不像从上图中最初看起来那么明显。这些测试旨在检查与每种方法相关的开销,并不代表实际应用程序。在实际应用程序中,与完成请求所需的时间相比,测试中显示的差异可能微不足道。第一个因素:Tomcat的标准线程池和基于虚拟线程的执行器性能差异的主要因素是在线程池队列中添加和移除任务的竞争。通过优化Tomcat使用的当前实现,可以减少标准线程池队列中的锁争用并提高吞吐量。第二个因素:上下文切换。这可能是对第二个实验中出现的性能差异的一种解释,因为虚拟线程的上下文切换比标准线程池中的线程更便宜,因此并发性超过了可用的处理器内核数量。结论使用基于虚拟线程的执行器是Tomcat标准线程池的可行替代方案。就容器开销而言,切换到虚拟线程执行器的好处微乎其微。经历阻塞的Web应用程序(例如Tomcat上的经典SpringMVC应用程序),并且尚未切换到Servlet异步API、反应式编程或其他异步API,应该通过切换到基于虚拟线程的执行器来看到一些可扩展性的改进。根据Web应用程序的不同,这些改进可以在不更改Web应用程序代码的情况下实现。切换到使用Servlet异步API、反应式编程或其他异步API的Web应用程序不太可能通过切换到基于虚拟线程的执行器来观察到可测量的差异(正面或负面),除非单机所需的QPS特别高。大的。从长远来看,虚拟线程的最大好处似乎是更简单的应用程序代码。当前需要使用Servlet异步API、反应式编程或其他异步API的一些用例将能够使用阻塞IO和虚拟线程来满足。需要注意的是,应用程序通常需要多次调用不同的外部服务。这是虚拟线程最有效的并行实现。尽管ProjectReactor等框架对此提供了一流的支持,但JRE的等效解决方案(结构化并发)还处于孵化器阶段,只是为了协调多个Futures而设计,并没有以最方便的方式相互声明或结合他们。最后,Loom项目仍处于预览模式。现在考虑在生产中使用虚拟线程还为时过早,但现在是将ProjectLoom和虚拟线程纳入您的计划的时候了,这样您就可以在虚拟线程在JRE中正式可用时做好准备。测试环境没有翻译,原文地址:https://spring.io/blog/2023/0...