Сравнительный анализ Spring WebFlux и Spring MVC

Java Spring
Сравнительный анализ Spring WebFlux и Spring MVC

Учебная комната Cabbage Java охватывает основные знания

1. Что такое Spring WebFlux

Следующая картинка взята с официального сайта Spring Boot:

В сочетании с приведенным выше рисунком, прежде чем понять Spring WebFlux, давайте сравним, что такое Spring MVC, что более полезно для нас, чтобы понять WebFlux.Определение Spring MVC в правой части рисунка выглядит следующим образом:

Spring MVC is built on the Servlet API and uses a synchronous blocking I/O architecture whth a one-request-per-thread model.

Spring MVC построен на API-интерфейсе сервлетов и использует модель синхронного блокирующего ввода-вывода Что такое модель синхронного блокирующего ввода-вывода? То есть каждый запрос соответствует потоку для обработки..

После понимания Spring MVC давайте поговорим о Spring WebFlux:

В левой части изображения выше официальное определение выглядит следующим образом:

Spring WebFlux is a non-blocking web framework built from the ground up to take advantage of multi-core, next-generation processors and handle massive numbers of concurrent connections.

Spring WebFlux — это асинхронная неблокирующая веб-инфраструктура, которая может полностью использовать аппаратные ресурсы многоядерных процессоров для обработки большого количества одновременных запросов..

Во-вторых, преимущества WebFlux и повышение производительности?

WebFlux использует внутри себя реактивное программирование, основанное на библиотеке Reactor, основанное на асинхронности и управляемом событиями, что позволяет нам повысить пропускную способность и масштабируемость системы без увеличения аппаратных ресурсов.

Видя это, думаете ли вы, что WebFlux может заставить программу работать быстрее? Чтобы немного оценить, например, после того, как я использую WebFlux, сократится ли время ответа на запрос интерфейса?

Извините, ответ нет! Вот официальное слово:

Reactive and non-blocking generally do not make applications run faster.

WebFlux не улучшает время отклика интерфейса, он только улучшает пропускную способность и масштабируемость..

3. Сценарии применения WebFlux

Как упоминалось выше, Spring WebFlux — это асинхронная и неблокирующая веб-инфраструктура, поэтому она особенно подходит для приложений в службах с интенсивным вводом-выводом, таких как шлюзы микросервисов.

PS: Интенсивный ввод-вывод включает:Интенсивный дисковый ввод-вывод, интенсивный сетевой ввод-вывод, шлюз микросервисов интенсивно использует сетевой ввод-вывод, а использование асинхронной неблокирующей модели программирования может значительно повысить пропускную способность шлюза при переадресации нисходящих сервисов.

В-четвертых, выбрать WebFlux или Spring MVC?

Прежде всего, вам нужно четко указать, что:WebFlux не является заменой Spring MVC.! , хотя WebFlux также может быть запущен в контейнере сервлетов (это должен быть контейнер сервлетов 3.1+), но WebFlux в основном используется в асинхронной неблокирующей модели программирования, тогда как Spring MVC является синхронной блокировкой, если вы в настоящее время находитесь в Фреймворк Spring MVC Если вы используете множество асинхронных решений, то WebFlux — это то, что вам нужно, в противном случае использование Spring MVC — ваш первый выбор.

В микросервисной архитектуре Spring MVC и WebFlux могут быть смешаны, как уже упоминалось, для тех служб с интенсивным вводом-выводом (таких как шлюзы), для достижения которых мы можем использовать WebFlux.

WebFlux или Spring MVC — это не проблема!

Мы не можем притворяться ради силы, технологии ради технологии и учитывать крутую кривую обучения при переходе на неблокирующее реактивное программирование, стоимость обучения членов команды и многие другие факторы.

Словом, в нужной сцене выбирайте наиболее подходящую технологию.

Пять сходств и различий

На приведенном выше рисунке вы можете с первого взгляда увидеть сходства и различия между Spring MVC и Spring WebFlux:

Та же точка:

  • Вы можете использовать аннотации Spring MVC, такие как@Controller, что нам удобно для свободного конвертирования между двумя веб-фреймворками;
  • Может использовать контейнер Tomcat, Jetty, Undertow Servlet (Servlet 3.1+);

будь осторожен:

  • Поскольку Spring MVC является типом синхронной блокировки, разработчикам удобнее писать функциональный код, отлаживать тесты и т. д. Вообще говоря, если Spring MVC соответствует сценариям, старайтесь не использовать WebFlux;
  • WebFlux по умолчанию использует Netty в качестве сервера;
  • WebFlux не поддерживает MySql;

6. Краткий обзор того, как WebFlux распределяет запросы

Друзья, которые использовали Spring MVC, должны знать, что передним контроллером Spring MVC является DispatcherServlet, а WebFlux — DispatcherHandler, который реализует интерфейс WebHandler:

public interface WebHandler {
    Mono<Void> handle(ServerWebExchange var1);
}

Давайте взглянем на метод handle в классе DispatcherHandler, который обрабатывает запросы:

    public Mono<Void> handle(ServerWebExchange exchange) {
        return this.handlerMappings == null ? this.createNotFoundError() : Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> {
            return mapping.getHandler(exchange);
        }).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> {
            return this.invokeHandler(exchange, handler);
        }).flatMap((result) -> {
            return this.handleResult(exchange, result);
        });
    }
  • ①: информация об ответе каждого HTTP-запроса, включая параметры и т. д., помещается в объект ServerWebExchange;
  • ②: Определите, пуст ли весь набор сопоставлений сопоставления интерфейсов, и если он пуст, будет создана ошибка «Не найдено»;
  • ③: Получить соответствующий обработчикMapping в соответствии с конкретным адресом запроса;
  • ④: вызов определенного бизнес-метода, который является методом интерфейса, который мы определили;
  • ⑤: Обработать возвращенный результат;

7. Быстрый старт

7.1 Добавление зависимостей webflux

Создайте новый проект Spring Boot и добавьте зависимость webflux в файл pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

7.2 Определение интерфейса

Создайте новый пакет контроллера для размещения классов внешнего интерфейса, а затем создайте класс WebFluxController для определения двух интерфейсов:

@RestController
public class WebFluxController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello, WebFlux !";
    }

    @GetMapping("/user")
    public Mono<UserDO> getUser() {
        UserDO user = new UserDO();
        user.setName("白菜");
        user.setDesc("白菜Java自习室");
        return Mono.just(user);
    }

}

@Data
public class UserDO {

    /**
     * 姓名
     */
    private String name;
    /**
     * 描述
     */
    private String desc;

}

В приведенных выше классах контроллеров мы используем все аннотации Spring MVC, которые определяют два интерфейса:

  • GET-запрос/helloИнтерфейс, возвращает строку Hello, WebFlux !.
  • Определен другой запрос GET/userметод, который возвращает объект User в формате JSON.

Обратите внимание, что объект User обернут объектом Mono, вы можете спросить, почему бы не вернуть его напрямую?

В WebFlux Mono — это неблокирующий способ записи, только таким образом вы можете воспользоваться преимуществами неблокирующих + асинхронных функций WebFlux.

В WebFlux кроме Mono есть еще Flux, разница в следующем:

  • Mono: возвращает 0 или 1 элемент, то есть один объект.
  • Flux: возвращает N элементов, которые являются объектом списка List.

7.3 Тестовый интерфейс

Запустите проект и посмотрите вывод консоли:

Когда выходные данные в консоли содержат оператор Netty, запущенный на порту (ах): 8080, это означает, что служба Netty была запущена по умолчанию.

первый справа/helloИнтерфейс инициирует вызов:

GET http://localhost:8080/hello
Accept: application/json
GET http://localhost:8080/hello

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 16

Hello, WebFlux !

Response code: 200 (OK); Time: 681ms; Content length: 16 bytes

снова правильно/userПротестируйте интерфейс:

GET http://localhost:8080/user
Accept: application/json
GET http://localhost:8080/user

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 46

{
  "name": "白菜",
  "desc": "白菜Java自习室"
}

Response code: 200 (OK); Time: 148ms; Content length: 32 bytes