SpringBoot-虚构线程的强强联结-接口吞吐量直线回升-效率飙升体验惊艳! (springboot)
在这篇博客中,咱们将看到如何在spring-boot中应用loom虚构线程。咱们还将在JMeter的协助下做一些负载测试,看看虚构线程和普通线程的照应期间如何。
首先,虚构线程是ProjectLoom的一局部。
此外,Loom不会减速内存计算,例如并行流,这不是Loom的指标。
咱们正在钻研如何经常使用可用的相反配件来提高运行程序吞吐量,即充沛应用CPU的后劲,为此咱们破费了少量精神。截至目前,咱们能够应用2%到3%的CPU。我在这篇博客中具体探讨了这一点:
让咱们极速设置咱们的SpringBoot名目。
<?xml?><projectxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.0</version><relativePath/></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><.version>11.0.0-M4</tomcat.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><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>
因为ProjectLoom处于预览阶段,咱们须要启用预览性能。
packageorg.anil.virtualthread;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.Springlication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;importorg.springframework.context.annotation.Bean;importjava.util.concurrent.Executors;@SpringBootApplication@Slf4jpublicclassVirtualthreadApplication{publicstaticvoidmn(String[]args){SpringApplication.run(VirtualthreadApplication.class,args);}@BeanpublicTomcatProtocolHandlerCustomizer<?>protocolHandlerVirtualThreadExecutorCustomizer(){returnprotocolHandler->{log.info("Configuring"+protocolHandler+"touseVirtualThreadPerTaskExecutor");protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());};}}
到目前为止,咱们须要为Tomcat主机性能虚构线程设置。未来,这或者会在智能性能自身中获取处置。
packageorg.anil.virtualthread;importorg.apache.commons.lang3.RandomStringUtils;importorg.apache.commons.lang3.RandomUtils;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.List;@RestControllerpublicclassHomeController{@AutowiredProductRepositoryproductRepository;@GetMapping("/thread")publicList<Product>checkThread()throwsInterruptedException{Thread.sleep(1000);returnproductRepository.findAll();}@PostMapping("/save")publicStringsaveProduct()throwsInterruptedException{for(inti=0;i<1000;i++){Productproduct=newProduct();product.setProductName(RandomStringUtils.randomAlphanumeric(5));product.setPrice(RandomUtils.nextLong(10,1000));product.setPrice(1L);productRepository.save(product);}return"anil";}}
咱们有一个GetMapping前往一切结果,咱们的数据库中有1000条数据。咱们曾经让线程休眠1秒。让咱们看看咱们的Product实体和ProductRepository。
packageorg.anil.virtualthread;importjakarta.persistence.Entity;importjakarta.persistence.GeneratedValue;importjakarta.persistence.GenerationType;importjakarta.persistence.Id;importlombok.Getter;importlombok.Setter;@Entity@Getter@SetterpublicclassProduct{@Id@GeneratedValue(strategy=GenerationType.IDENTITY)privateLongid;privateStringproductName;privateLongprice;}packageorg.anil.virtualthread;importorg.springframework.data.jpa.repository.JpaRepository;publicinterfaceProductRepositoryextendsJpaRepository<Product,Long>{}
让咱们看看咱们的application.yaml
spring:>如今,咱们首先经过注释以下行来运转运行程序,这将在普通线程上运转咱们的运行程序。packageorg.anil.virtualthread;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;importorg.springframework.context.annotation.Bean;importjava.util.concurrent.Executors;@SpringBootApplication@Slf4jpublicclassVirtualthreadApplication{publicstaticvoidmain(String[]args){SpringApplication.run(VirtualthreadApplication.class,args);}//@Bean//publicTomcatProtocolHandlerCustomizer<?>protocolHandlerVirtualThreadExecutorCustomizer(){//returnprotocolHandler->{//log.info("Configuring"+protocolHandler+"touseVirtualThreadPerTaskExecutor");//protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());//};//}}
如今让咱们设置JMeter。咱们将有1000个恳求,该恳求将在3秒内参与。并且这样的形态会继续200秒。每3秒,将触发1000个GET(/thread)恳求。咱们还参与了照应期间图侦听器。
图片
如今让咱们运转测试并期待200秒。
图片
从图中咱们可以看到,一旦Tomcat的整个线程池被应用,照应期间从3600毫秒猛增到5200毫秒。从那时起,只要当以前的线程被监禁时,它才坚持这种形态。
如今让咱们在启用虚构线程性能的状况下运转负载测试。
packageorg.anil.virtualthread;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;importorg.springframework.context.annotation.Bean;importjava.util.concurrent.Executors;@SpringBootApplication@Slf4jpublicclassVirtualthreadApplication{publicstaticvoidmain(String[]args){SpringApplication.run(VirtualthreadApplication.class,args);}@BeanpublicTomcatProtocolHandlerCustomizer<?>protocolHandlerVirtualThreadExecutorCustomizer(){returnprotocolHandler->{log.info("Configuring"+protocolHandler+"touseVirtualThreadPerTaskExecutor");protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());};}}
如今让咱们运转测试并期待200秒。
图片
显然,如今并发1000个恳求的照应期间简直略高于1000毫秒,有时甚至会到达1400毫秒,这比咱们经常使用普通线程时要好得多。
显然,当咱们须要充沛应用底层CPU时,咱们应该开局在运行程序中驳回虚构线程,突然间咱们可以看到,关于相反的配件,运行程序的吞吐量参与了很多倍。
这比切换到反响式编程要好得多,反响式编程象征着重写一切代码,这很难先学习,而后编写,甚至更难调试和剖析。
简而言之,更多用户可以经常使用该运行程序并与第一个用户同时取得照应。
Spring Boot 提升并发吞吐量的主要方法有: 1. 异步处理:Spring Boot有许多异步处理机制,如DeferredResult和CompletableFuture。 采用异步处理可以大大提高应用程序的吞吐量,因为它不会阻塞主线程,允许处理更多的请求。 2. 缓存:使用缓存可以减少对数据库的访问次数,从而提高吞吐量。 3. 优化数据库:优化数据库查询语句、增加索引等都可以提高吞吐量。 4. 使用NIO:NIO是Java提供的非阻塞IO接口,它可以有效地提高吞吐量。 5. 使用线程池:使用线程池可以减少线程创建和销毁的开销,从而提高吞吐量。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。