SpringBoot+虚拟线程,接口吞吐量成倍增加,太爽了!

我们将看到如何在spring-boot中利用loom虚拟线程 。我们还将在JMeter的帮助下做一些负载测试,看看虚拟线程和普通线程的响应时间如何 。
首先 , 虚拟线程是 Project Loom 的一部分 。
此外 , Loom 不会加速内存计算,例如并行流,这不是 Loom 的目标 。
我们正在研究如何使用可用的相同硬件来提高应用程序吞吐量,即充分利用 CPU 的潜力,为此我们花费了大量精力 。截至目前,我们能够利用 2% 到 3% 的 CPU 。我在这篇博客中详细讨论了这一点:
https://medium.com/@anil.JAVA.story/project-loom-virtual-threads-part-1-b17e327c8ba7
“我认为 Loom 项目将会消灭响应式编程”——Brian Goetz(Java 语言架构师)
让我们快速设置我们的 Spring Boot 项目 。
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.0</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>org.anil</groupId><artifactId>virtualthread</artifactId><version>0.0.1-SNAPSHOT</version><name>virtualthread</name><description>virtualthread</description><properties><java.version>20</java.version><Tomcat.version>11.0.0-M4</tomcat.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><!-- https://mvnrepository.com/artifact/MySQL/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope><version>8.0.33</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><scope>compile</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><compilerArgs><arg>--enable-preview</arg></compilerArgs><source>20</source><target>20</target></configuration></plugin></plugins></build></project>由于 Project Loom 处于预览阶段,我们需要启用预览功能 。
package org.anil.virtualthread;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;import org.springframework.context.annotation.Bean;import java.util.concurrent.Executors;@SpringBootApplication@Slf4jpublic class VirtualthreadApplication {public static void mAIn(String[] args) {SpringApplication.run(VirtualthreadApplication.class, args);}@Beanpublic TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {return protocolHandler -> {log.info("Configuring " + protocolHandler + " to use VirtualThreadPerTaskExecutor");protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());};}}到目前为止 , 我们需要为 Tomcat 服务器配置虚拟线程设置 。将来 , 这可能会在自动配置本身中得到解决 。
package org.anil.virtualthread;import org.apache.commons.lang3.RandomStringUtils;import org.apache.commons.lang3.RandomUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestControllerpublic class HomeController {@AutowiredProductRepository productRepository;@GetMapping("/thread")public List<Product> checkThread() throws InterruptedException {Thread.sleep(1000);return productRepository.findAll();}@PostMapping("/save")public String saveProduct() throws InterruptedException {for(int i=0; i< 1000; i++){Product product = new Product();product.setProductName(RandomStringUtils.randomAlphanumeric(5));product.setPrice(RandomUtils.nextLong(10,1000));product.setPrice(1L);productRepository.save(product);}return "anil";}}


推荐阅读