1. 前言

最近在学响应式编程的时候,突然让我想到,新的编程范式就一定会比传统的编程范式好吗?响应式编程的性能提升在哪个方面的呢?

文章以下内容翻译来源于:Spring Benchmark – Web MVC vs Webflux

作者粗略的比较了传统的Spring MVC和WebFlux的性能特点,因为比较的内容只是一个简单的hello world接口,而现实生活中的业务请求复杂度会高很多。

原文博客时间在2022年8月,还是比较有参考价值的。

2. 正文

在Java的世界中,每个处理过程从设计上来说都是一个基于CPU线程的概念,通过阻塞操作和命令式代码来实现。因此,最初的Java Web服务器采用了每个请求一个线程的方式,遵循Servlet规范。然而,基于线程的编程方式存在一些限制,因为CPU一次只能处理有限数量的线程,大约在一万个左右。

在当今的商业环境中,某些与互联网相连的业务应用需要支持百万级的吞吐量,这已经成为一个关键需求。如果我们继续采用每个请求一个线程的方式,CPU就需要活跃地运行大量线程来处理请求。但是云主机通常提供1-2个CPU,甚至只有不到1个CPU的资源。因此,出现了基于异步事件循环、非阻塞的Web服务器,以较少的线程处理并发,并且能够在较少的硬件资源下进行扩展。

我一直想尝试使用异步Web服务器构建Java Web服务应用,但直到现在仍然没有机会,因为在我的工作场所,我们并没有处理那么高的流量。

因此,我进行了一个快速尝试,比较了基于每个请求一个线程的引擎和基于异步Web服务器的性能差异。我使用了Spring Web MVC和Spring WebFlux进行简单快速的比较。Spring Web MVC基于Servlet Web服务器,而WebFlux基于异步的Netty。

以下是我用于运行比较的框架版本、库和工具:

我在一台装有英特尔第12代 Core i7 处理器(20个CPU线程)的机器上运行了测试。

3. 项目结构

首先,创建一个父项目来存放通用库的版本。

<project ....>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>web</module>
        <module>webflux</module>
        <module>gatling</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.example</groupId>
    <artifactId>spring-web-vs-webflux</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>18</maven.compiler.source>
        <maven.compiler.target>18</maven.compiler.target>
        <java.version>18</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>