自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SpringBoot+虛擬線程,接口吞吐量成倍增加,太爽了!

開發(fā)
我們正在研究如何使用可用的相同硬件來提高應(yīng)用程序吞吐量,即充分利用 CPU 的潛力,為此我們花費(fèi)了大量精力。

我們將看到如何在spring-boot中利用loom虛擬線程。我們還將在JMeter的幫助下做一些負(fù)載測試,看看虛擬線程和普通線程的響應(yīng)時(shí)間如何。

首先,虛擬線程是 Project Loom 的一部分。

此外,Loom 不會(huì)加速內(nèi)存計(jì)算,例如并行流,這不是 Loom 的目標(biāo)。

我們正在研究如何使用可用的相同硬件來提高應(yīng)用程序吞吐量,即充分利用 CPU 的潛力,為此我們花費(fèi)了大量精力。截至目前,我們能夠利用 2% 到 3% 的 CPU。我在這篇博客中詳細(xì)討論了這一點(diǎn):

https://medium.com/@anil.java.story/project-loom-virtual-threads-part-1-b17e327c8ba7

“我認(rèn)為 Loom 項(xiàng)目將會(huì)消滅響應(yīng)式編程”——Brian Goetz(Java 語言架構(gòu)師)

讓我們快速設(shè)置我們的 Spring Boot 項(xiàng)目。

<?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 處于預(yù)覽階段,我們需要啟用預(yù)覽功能。

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
@Slf4j
public class VirtualthreadApplication {

    public static void main(String[] args) {
        SpringApplication.run(VirtualthreadApplication.class, args);
    }

    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> {
            log.info("Configuring " + protocolHandler + " to use VirtualThreadPerTaskExecutor");
            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
        };
    }

}

到目前為止,我們需要為 Tomcat 服務(wù)器配置虛擬線程設(shè)置。將來,這可能會(huì)在自動(dòng)配置本身中得到解決。

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;

@RestController
public class HomeController {

    @Autowired
    ProductRepository 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";
    }
}

我們有一個(gè)GetMapping返回所有結(jié)果,我們的數(shù)據(jù)庫中有 1000 條數(shù)據(jù)。我們已經(jīng)讓線程休眠 1 秒。讓我們看看我們的Product實(shí)體和ProductRepository。

package org.anil.virtualthread;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String productName;
    private Long price;
}
package org.anil.virtualthread;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product,Long> {
}

讓我們看看我們的 application.yaml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    maxIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    hikari:
      connection-timeout: 60000
      maximum-pool-size: 10
      minimum-idle: 5
    url: jdbc:mysql://localhost:3306/todos
    testWhileIdle: true
    username: root
    password: root1234
    validationQuery: SELECT 1
  flyway:
    baseline-version: 0
    enabled: true
    validate-on-migrate: false
  jpa:
    database: mysql
    generate-ddl: true
    hibernate:
      ddl-auto: none
      format_sql: true
    show-sql: true

現(xiàn)在,我們首先通過注釋以下行來運(yùn)行應(yīng)用程序,這將在普通線程上運(yùn)行我們的應(yīng)用程序

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
@Slf4j
public class VirtualthreadApplication {

    public static void main(String[] args) {
        SpringApplication.run(VirtualthreadApplication.class, args);
    }

//    @Bean
//    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
//        return protocolHandler -> {
//            log.info("Configuring " + protocolHandler + " to use VirtualThreadPerTaskExecutor");
//            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
//        };
//    }
}

現(xiàn)在讓我們設(shè)置JMeter。我們將有 1000 個(gè)請求,該請求將在 3 秒內(nèi)增加。并且這樣的狀態(tài)會(huì)持續(xù)200秒。每 3 秒,將觸發(fā) 1000 個(gè) GET (“/thread”) 請求。我們還添加了響應(yīng)時(shí)間圖偵聽器。

現(xiàn)在讓我們運(yùn)行測試并等待 200 秒。

從圖中我們可以看到,一旦Tomcat的整個(gè)線程池被利用,響應(yīng)時(shí)間從3600毫秒猛增到5200毫秒。從那時(shí)起,只有當(dāng)以前的線程被釋放時(shí),它才保持這種狀態(tài)。

現(xiàn)在讓我們在啟用虛擬線程功能的情況下運(yùn)行負(fù)載測試。

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
@Slf4j
public class VirtualthreadApplication {

    public static void main(String[] args) {
        SpringApplication.run(VirtualthreadApplication.class, args);
    }

    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> {
            log.info("Configuring " + protocolHandler + " to use VirtualThreadPerTaskExecutor");
            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
        };
    }

}

現(xiàn)在讓我們運(yùn)行測試并等待 200 秒。

顯然,現(xiàn)在并發(fā) 1000 個(gè)請求的響應(yīng)時(shí)間幾乎略高于 1000 毫秒,有時(shí)甚至?xí)_(dá)到 1400 毫秒,這比我們使用普通線程時(shí)要好得多。

顯然,當(dāng)我們需要充分利用底層 CPU 時(shí),我們應(yīng)該開始在應(yīng)用程序中采用虛擬線程,突然間我們可以看到,對于相同的硬件,應(yīng)用程序的吞吐量增加了很多倍。

這比切換到反應(yīng)式編程要好得多,反應(yīng)式編程意味著重寫所有代碼,這很難先學(xué)習(xí),然后編寫,甚至更難調(diào)試和分析。

簡而言之,更多用戶可以使用該應(yīng)用程序并與第一個(gè)用戶同時(shí)獲得響應(yīng)。

責(zé)任編輯:張燕妮 來源: 互聯(lián)網(wǎng)架構(gòu)小馬哥
相關(guān)推薦

2022-07-13 10:36:13

智能工廠網(wǎng)絡(luò)安全

2021-08-28 10:33:33

數(shù)據(jù)中心IDC5G

2024-09-12 15:24:29

2024-09-09 14:12:38

2024-06-06 16:15:00

2021-12-24 10:47:49

Kubernetes容器化微服務(wù)

2020-09-22 20:14:51

人工智能

2012-03-30 15:56:39

ibmdw

2020-12-13 09:40:11

物聯(lián)網(wǎng)物聯(lián)網(wǎng)安全加密方法

2023-11-03 18:23:34

虛擬線程服務(wù)器

2024-06-28 09:39:58

2011-09-02 13:54:24

Windows優(yōu)化寬帶

2024-11-14 15:00:00

線程架構(gòu)吞吐量

2022-08-12 08:38:08

攜程小程序Taro跨端解決方案

2024-06-06 08:46:37

2012-12-11 16:41:52

服務(wù)器虛擬化

2014-08-27 10:13:25

降維算法

2022-08-01 14:15:17

大數(shù)據(jù)元宇宙

2021-10-21 17:56:07

Gartner人工智能云原生

2013-04-19 09:45:20

AMPLabHadoopHDFS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號