Сегодня утром я увидел статью о сравнении производительности виртуальных потоков Spring Boot и Webflux и подумал, что она довольно хороша. Содержание длинное, поэтому я не буду его переводить. Вместо этого я сосредоточусь на том, чтобы познакомить вас с основным содержанием этой статьи, чтобы вы могли ее быстро прочитать.
сценарии тестирования
Автор использует сценарий, максимально приближенный к реальности:
- Извлечь JWT из заголовка авторизации
- Проверьте JWT и извлеките из него адрес электронной почты пользователя.
- Используйте электронную почту пользователя для выполнения запроса в MySQL.
- Вернуть запись пользователя
технология тестирования
Здесь необходимо сравнить два основных технических момента:
- Spring Boot с виртуальными потоками. Это приложение Spring Boot, работающее не в традиционных физических потоках, а в виртуальных потоках. Эти легкие потоки упрощают сложные задачи разработки, обслуживания и отладки параллельных приложений с высокой пропускной способностью. Хотя виртуальные потоки по-прежнему выполняются в потоках базовой операционной системы, они значительно повышают эффективность. Когда виртуальный поток сталкивается с блокирующей операцией ввода-вывода, среда выполнения Java временно приостанавливает ее, освобождая соответствующий поток операционной системы для обслуживания других виртуальных потоков. Это элегантное решение оптимизирует распределение ресурсов и повышает общую скорость реагирования приложений.
- Spring Boot Webflux: Spring Boot WebFlux — это среда реактивного программирования в экосистеме Spring, которая использует библиотеку Project Reactor для реализации неблокирующего, управляемого событиями программирования. Поэтому он особенно подходит для приложений, которым требуется высокий уровень параллелизма и низкая задержка. Опираясь на реактивный подход, он позволяет разработчикам эффективно обрабатывать большое количество одновременных запросов, сохраняя при этом гибкость интеграции с различными источниками данных и протоколами связи.
Будь то Webflux или виртуальные потоки, оба они предназначены для обеспечения высокой параллельной работы программ, так кто же лучше? Давайте посмотрим на конкретные тесты.
тестовая среда
Операционная среда и инструменты
- MacBook Pro M1 с памятью 16 ГБ.
- Ява 20
- Весенняя загрузка 3.1.3
- Включите режим предварительного просмотра, чтобы получить всю мощь виртуальных потоков.
- Зависимые сторонние библиотеки: jjwt, mysql-connector-java.
- Инструмент тестирования: Bombardier
- База данных: MySQL
подготовка данных
- Подготовьте список из 100 000 JWT в Bombardier, чтобы случайным образом выбрать из них JWT и поместить их в информацию авторизации HTTP-запроса.
- Создайте таблицу пользователей в MySQL со следующей структурой таблицы:
mysql> desc users;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| email | varchar(255) | NO | PRI | NULL | |
| first | varchar(255) | YES | | NULL | |
| last | varchar(255) | YES | | NULL | |
| city | varchar(255) | YES | | NULL | |
| county | varchar(255) | YES | | NULL | |
| age | int | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
- Подготовьте 100 000 пользовательских данных для таблицы пользователей.
тестовый код
Программа Spring Boot с виртуальными потоками
application.properties
Конфигурационный файл:
server.port=3000
spring.datasource.url= jdbc:mysql://localhost:3306/testdb?useSSL=false
spring.datasource.username= testuser
spring.datasource.password= testpwd
spring.jpa.hibernate.ddl-auto= update
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
User
Класс сущности (чтобы сделать статью более краткой, DD опускает здесь геттер и сеттер):
@Entity
@Table(name = "users")
public class User {
@Id
private String email;
private String first;
private String last;
private String city;
private String county;
private int age;
}
Основной класс приложения:
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
@Bean
public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
return protocolHandler -> {
protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
};
}
}
Обеспечивает операции CRUD UserRepository
:
import org.springframework.data.repository.CrudRepository;
import com.example.demo.User;
public interface UserRepository extends CrudRepository<User, String> {
}
Классы , предоставляющие интерфейсы API UserController
:
@RestController
public class UserController {
@Autowired
UserRepository userRepository;
private SignatureAlgorithm sa = SignatureAlgorithm.HS256;
private String jwtSecret = System.getenv("JWT_SECRET");
@GetMapping("/")
public User handleRequest(@RequestHeader(HttpHeaders.AUTHORIZATION) String authHdr) {
String jwtString = authHdr.replace("Bearer","");
Claims claims = Jwts.parser()
.setSigningKey(jwtSecret.getBytes())
.parseClaimsJws(jwtString).getBody();
Optional<User> user = userRepository.findById((String)claims.get("email"));
return user.get();
}
}
Программа Spring Boot Webflux
application.properties
Конфигурационный файл:
server.port=3000
spring.r2dbc.url=r2dbc:mysql://localhost:3306/testdb
spring.r2dbc.username=dbser
spring.r2dbc.password=dbpwd
User
Entity (здесь DD также опускает конструктор, геттер и сеттер):
public class User {
@Id
private String email;
private String first;
private String last;
private String city;
private String county;
private int age;
// 省略了构造函数、getter、setter
}
Основной класс приложения:
@EnableWebFlux
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
Обеспечивает операции CRUD UserRepository
:
public interface UserRepository extends R2dbcRepository<User, String> {
}
Обеспечивает проверку бизнес-класса пользователя по ID UserService
:
@Service
public class UserService {
@Autowired
UserRepository userRepository;
public Mono<User> findById(String id) {
return userRepository.findById(id);
}
}
Классы , предоставляющие интерфейсы API UserController
:
@RestController
@RequestMapping("/")
public class UserController {
@Autowired
UserService userService;
private SignatureAlgorithm sa = SignatureAlgorithm.HS256;
private String jwtSecret = System.getenv("JWT_SECRET");
@GetMapping("/")
@ResponseStatus(HttpStatus.OK)
public Mono<User> getUserById(@RequestHeader(HttpHeaders.AUTHORIZATION) String authHdr) {
String jwtString = authHdr.replace("Bearer","");
Claims claims = Jwts.parser()
.setSigningKey(jwtSecret.getBytes())
.parseClaimsJws(jwtString).getBody();
return userService.findById((String)claims.get("email"));
}
}
Результаты теста
Далее следует самое интересное: автор протестировал оба технических решения с 5 миллионами запросов. Оцениваемые различные уровни одновременного подключения включают: 50, 100 и 300.
Конкретные результаты заключаются в следующем:
Наконец, автор пришел к выводу, что Spring Boot Webflux лучше, чем Spring Boot с виртуальными потоками.
Кажется, внедрение виртуальных потоков не так хорошо, как уже используемый Webflux? Интересно, проводили ли вы какие-либо соответствующие исследования? Если да, пожалуйста, напишите нам в области сообщений~
Что делать, если вы столкнулись с трудностями во время учебы? Вы можете присоединиться к нашей высококачественной группе обмена технологиями Spring , чтобы участвовать в обменах и обсуждениях для лучшего обучения и прогресса! Чтобы увидеть больше руководств по Spring Boot, нажмите здесь! Добро пожаловать, собирайте и пересылайте на поддержку! Если вас интересует исходный текст этого контента, вы также можете нажать здесь, чтобы просмотреть его .
JetBrains выпускает Rust IDE: RustRover Java 21 / JDK 21 (LTS) GA Учитывая такое количество разработчиков Java в Китае, должна появиться среда разработки приложений экологического уровня .NET 8. Производительность значительно улучшена и намного опережает .NET 8. NET 7. PostgreSQL 16 выпущен бывшим членом команды Rust, о котором я глубоко сожалею и попросил удалить мое имя. Вчера я завершил удаление Nue JS из внешнего интерфейса. Автор сказал, что я создам новую веб-экосистему. NetEase Fuxi отреагировала на смерть сотрудника, которому «угрожал отдел кадров из-за ОШИБКИ».Жэнь Чжэнфэй: Мы приближаемся к четвертой промышленной революции, Apple — учитель Huawei, новый продукт Vercel «v0»: генерировать код интерфейса пользовательского интерфейса на основе текстДобро пожаловать на мою публичную учетную запись: Programmer DD. Будьте первым, кто узнает о последних новостях отрасли, делится подробной технической информацией и получает высококачественные учебные ресурсы.