Reactor 2024.0 版本列車中的 HTTP/3 支援

工程 | Violeta Georgieva | 2024 年 11 月 26 日 | ...

HTTP/3Hypertext Transfer Protocol 的最新主要版本,其規範於 2022 年 6 月最終確定。該版本旨在提高效能、可靠性和安全性。與其前身不同,HTTP/3 使用 QUIC 而不是 TCP 作為其傳輸層。QUIC 是一種基於 UDP 的多路複用安全傳輸協議,包含內建的 TLS 1.3 加密,因此 QUIC 預設加密。

要了解有關 HTTP/3 的效能和優勢的更多資訊,請檢視 什麼是 HTTP/3

有關瀏覽器採用情況的資訊,請檢視 HTTP/3 使用情況分析,其中還提供了不同瀏覽器使用的 HTTP 版本的原始資料。

Reactor Netty 1.2(Reactor 2024.0 版本列車的一部分)增加了 HTTP/3 的實驗性支援。透過這個新版本的 Reactor Netty,您的 Spring Boot 應用程式和 Spring Cloud Gateway 可以配置為支援 HTTP/3

讓我們看看如何配置 HTTP/3 支援。

配置 Reactor BOM 版本

Spring Boot 3.4 預設包含 Reactor 2024.0 版本列車!

如果您執行的是舊版本的 Spring Boot,可以透過將 Reactor BOM 升級到 2024.0 來體驗這項新功能(截至本文撰寫時,2024.0.0 是最新版本)。

Maven

<properties>
    <reactor-bom.version>2024.0.0</reactor-bom.version>
</properties>

Gradle

ext['reactor-bom.version'] = '2024.0.0'

配置 Netty HTTP3 編解碼器

您還需要新增 Netty HTTP3 編解碼器 的執行時依賴(截至本文撰寫時,0.0.28.Final 是最新版本)。

Maven

<dependencies>
    <dependency>
        <groupId>io.netty.incubator</groupId>
        <artifactId>netty-incubator-codec-http3</artifactId>
        <version>0.0.28.Final</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Gradle

dependencies {
    runtimeOnly 'io.netty.incubator:netty-incubator-codec-http3:0.0.28.Final'
}

伺服器端

配置 SSL Bundle

您首先需要提供一個包含應用程式所需配置的 SSL bundle:金鑰庫、密碼套件等。

application.properties

spring.ssl.bundle.jks.server-http3.key.alias=http3
spring.ssl.bundle.jks.server-http3.keystore.location=...
spring.ssl.bundle.jks.server-http3.keystore.password=...
...

application.yml

spring:
  ssl:
    bundle:
      jks:
        server-http3:
          key:
            alias: http3
          keystore:
            location: ...
            password: ...
          ...

配置嵌入式伺服器

Spring Boot 提供了配置嵌入式伺服器的能力。Spring Cloud Gateway 使用相同的方法來完成此任務。

您可以宣告一個 WebServerFactoryCustomizer 元件並獲取伺服器工廠的訪問許可權。為了啟用 HTTP/3 支援,您需要

預設情況下,Reactor Netty 配置為支援 HTTP/1.1,因此您需要進行更改。

預設情況下,Reactor Netty 不提供任何設定,因為這些設定與應用程式密切相關,因此您必須配置它們:空閒超時、最大流等。

之前配置的 SSL Bundle 可以透過其名稱 factory.getSslBundles().getBundle("server-http3") 從伺服器工廠獲取,並且您可以配置 Http3SslContextSpec

@Component
class Http3NettyWebServerCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

    @Override
    public void customize(NettyReactiveWebServerFactory factory) {
        factory.addServerCustomizers(server -> {
            SslBundle sslBundle = factory.getSslBundles().getBundle("server-http3");
            Http3SslContextSpec sslContextSpec =
                Http3SslContextSpec.forServer(sslBundle.getManagers().getKeyManagerFactory(), sslBundle.getKey().getPassword());

            return server
                    // Configure HTTP/3 protocol
                    .protocol(HttpProtocol.HTTP3)
                    // Configure HTTP/3 SslContext
                    .secure(spec -> spec.sslContext(sslContextSpec))
                    // Configure HTTP/3 settings
                    .http3Settings(spec -> spec
                            .idleTimeout(Duration.ofSeconds(5))
                            .maxData(10_000_000)
                            .maxStreamDataBidirectionalRemote(1_000_000)
                            .maxStreamsBidirectional(100));
        });
    }
}

REST 控制器

您最後需要新增的是一個簡單的 hello REST 控制器。REST 控制器不需要任何特定的 HTTP/3 配置!

@RestController
class Http3Controller {

    @GetMapping("/hello")
    String hello() {
        return "Hello HTTP/3!";
    }
}

現在您已準備好進行您的第一個 HTTP/3 請求

curl --http3 https://:8443/hello --verbose
* Connected to localhost (::1) port 8443
* using HTTP/3
* [HTTP/3] [0] OPENED stream for https://:8443/hello
* [HTTP/3] [0] [:method: GET]
* [HTTP/3] [0] [:scheme: https]
* [HTTP/3] [0] [:authority: localhost:8443]
* [HTTP/3] [0] [:path: /hello]
* [HTTP/3] [0] [user-agent: curl]
* [HTTP/3] [0] [accept: */*]
> GET /hello HTTP/3
> Host: localhost:8443
> User-Agent: curl
> Accept: */*
> 
* Request completely sent off
< HTTP/3 200 
< content-type: text/plain;charset=UTF-8
< content-length: 13
< 
* Connection #0 to host localhost left intact
Hello HTTP/3!

spring-webflux-http3 倉庫包含完整的示例!

客戶端

為客戶端配置 HTTP/3 支援的方式與配置伺服器端類似!

您需要

  • 指定 HTTP/3 協議。預設情況下,Reactor Netty 配置為支援 HTTP/1.1,因此您需要進行更改。
  • 指定 HTTP/3 設定。預設情況下,Reactor Netty 不提供任何設定,因為這些設定與應用程式密切相關,因此您必須配置它們:空閒超時、最大流等。
import reactor.netty.http.client.HttpClient;

HttpClient client = HttpClient.create()
        // Configure HTTP/3 protocol
        .protocol(HttpProtocol.HTTP3)
        // Configure HTTP/3 settings
        .http3Settings(spec -> spec
                .idleTimeout(Duration.ofSeconds(5))
                .maxData(10_000_000)
                .maxStreamDataBidirectionalLocal(1_000_000));

預設情況下,客戶端使用 Reactor Netty 提供的標準 HTTP/3 SSLContext。但是,如果您需要更具體的配置:信任庫、密碼套件等,您可以像為伺服器準備 SSL Bundle 一樣準備它,並且可以配置 Http3SslContextSpec

SslBundle sslBundle = factory.getSslBundles().getBundle("client-http3");
Http3SslContextSpec sslContextSpec = Http3SslContextSpec.forClient()
        // Configure TrustStore etc.
        .configure(...);
HttpClient client = HttpClient.create()
        ...
        // Configure HTTP/3 SslContext
        .secure(spec -> spec.sslContext(sslContextSpec));

WebClient

您可以使用 ReactorClientHttpConnector 配置底層的 Reactor Netty HttpClient

@Bean
WebClient http3WebClient(WebClient.Builder builder) {
    HttpClient client = ...;
    return builder.clientConnector(new ReactorClientHttpConnector(client)).build();
}

REST 控制器

您可以建立一個簡單的 REST 控制器,利用新的 HTTP/3 配置發起遠端呼叫。REST 控制器不需要任何特定的 HTTP/3 配置!

@RestController
class Http3Controller {

    private final WebClient http3WebClient;

    Http3Controller(WebClient http3WebClient) {
        this.http3WebClient = http3WebClient;
    }

    @GetMapping("/remote")
    Mono<String> remote() {
        return http3WebClient
                .get()
                .uri("https://projectreactor.io/")
                .retrieve()
                .bodyToMono(String.class);
    }
}

spring-webflux-http3 倉庫包含完整的示例。

RestClient

您可以使用 ReactorNettyClientRequestFactory 配置底層的 Reactor Netty HttpClient

@Bean
RestClient http3RestClient(RestClient.Builder builder) {
	HttpClient client = ...;
	return builder.requestFactory(new ReactorNettyClientRequestFactory(client)).build();
}

REST 控制器

您可以建立一個簡單的 REST 控制器,利用新的 HTTP/3 配置發起遠端呼叫。REST 控制器不需要任何特定的 HTTP/3 配置!

@RestController
class Http3Controller {

    private final RestClient http3RestClient;

    Http3Controller(RestClient http3RestClient) {
        this.http3RestClient = http3RestClient;
    }

    @GetMapping("/remote")
    String remote() {
        return http3RestClient
                .get()
                .uri("https://projectreactor.io/")
                .retrieve()
                .body(String.class);
    }
}

spring-webmvc-http3 倉庫包含完整的示例。

現在您已準備好進行您的第一個 HTTP/3 遠端呼叫

curl --http3 https://:8443/remote --verbose
* Connected to localhost (::1) port 8443
* using HTTP/3
* [HTTP/3] [0] OPENED stream for https://:8443/remote
* [HTTP/3] [0] [:method: GET]
* [HTTP/3] [0] [:scheme: https]
* [HTTP/3] [0] [:authority: localhost:8443]
* [HTTP/3] [0] [:path: /remote]
* [HTTP/3] [0] [user-agent: curl/8]
* [HTTP/3] [0] [accept: */*]
> GET /remote HTTP/3
> Host: localhost:8443
> User-Agent: curl/8
> Accept: */*
> 
* Request completely sent off
< HTTP/3 200 
< content-type: text/plain;charset=UTF-8
< content-length: 17138
...

Spring Cloud Gateway

您可以使用 Spring Cloud Gateway 中的 HttpClientCustomizer 配置底層的 Reactor Netty HttpClient。要使用此自定義器,您需要將其註冊到 Spring Cloud Gateway 配置中。

@Configuration
class GatewayConfiguration {

    @Bean
    HttpClientCustomizer http3HttpClientCustomizer() {
        return httpClient ->
                httpClient
                        // Configure HTTP/3 protocol
                        .protocol(HttpProtocol.HTTP3)
                        // Configure HTTP/3 settings
                        .http3Settings(spec -> spec.idleTimeout(Duration.ofSeconds(5))
                                .maxData(10_000_000)
                                .maxStreamDataBidirectionalLocal(1_000_000));
    }
}

spring-cloud-gateway-http3 倉庫包含完整的示例。

我們希望您會喜歡我們與 HTTP/3 整合的簡潔性。請在我們的 GitHub/Twitter 上提供反饋!

獲取 Spring 時事通訊

訂閱 Spring 時事通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您快速提升。

瞭解更多

獲取支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一個簡單的訂閱即可獲得。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視全部