Spring Boot 启用 HTTP2
1、概览
HTTP/2 是广泛使用的 HTTP/1.1 协议的后续协议,它通过采用多路复用和 Header 压缩等新功能提高了网络性能。
本文将带你了解如何配置 Spring Boot 应用,以在嵌入式 Tomcat 服务器上启用 HTTP/2。
2、HTTP/2
超文本传输协议(HTTP)是一种在互联网上获取资源的应用协议。HTTP/1.1 于 1997 年 1 月发布,二十多年来为大多数网络提供服务。该版本发现了在某些情况下导致性能缓慢的问题。
HTTP/2 克服了 HTTP/1.1 中的性能问题,具有以下特点:
- 多路复用 - HTTP/1.1 使用多个连接发送多个请求;多路复用允许通过单个连接发送请求,从而减少资源消耗和延迟
- Header 压缩 - 如果不进行压缩,由于 TCP 启动速度较慢,通常需要多次往返才能发送 Header;压缩 Header 后,Header 的发送往返次数会减少,大部分时间都能在一次往返内完成
- 二进制 - 与使用文本编码数据的 HTTP/1.1 相比,HTTP/2 以二进制格式发送数据,以减少解析开销并缩小报文大小。
3、先决条件
HTTP/2 可以通过明文或 TLS 运行。大多数 Web 浏览器不支持明文 HTTP/2,因此建议通过 TLS 运行。
首先要在嵌入式 Web 服务器上启用 SSL。
在控制台中运行以下 keytool
命令来生成一个 keystore
,用于存储 SSL/TLS 使用的密钥和证书,并将其放入嵌入式 Tomcat 中。
$ keytool -genkeypair -alias http2-alias -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650
keytool
会要求我们输入密码,稍后需要将其添加到 Spring Boot 配置中。完成该过程后,keytool 将生成 keystore.p12 文件。
将把该文件复制到 Spring Boot 应用程序下的 resources
文件夹中。
现在,在 application.yml
中添加以下属性,以在嵌入式 Tomcat 中启用 HTTPS:
server:
ssl:
enabled: true
key-store: classpath:keystore.p12
key-store-password: <your-password> # 替换为你定义的 Keystore 密码
key-store-type: PKCS12
key-alias: http2-alias
4、检查响应中的 HTTP 协议版本
默认情况下,Spring Boot 嵌入式 Tomcat 不会启用 HTTP/2 协议来服务请求。
创建一个简单的 Spring Boot REST 端点来验证一下:
@RestController
public class Http2Controller {
@GetMapping("/http2/echo")
public String getChatbotResponse(@RequestParam String message) {
return message;
}
}
该端点只接受一个请求参数信息,并将其发送回响应体。
启动应用后,就可以在控制台中执行下面的 curl
命令,使用 -http2
参数,通过 HTTP/2 调用端点:
$ curl -I --http2 http://localhost:8080/http2/echo?message=hello
参数 -I
会显示更多信息,如响应中的 HTTP 协议版本。从打印的输出中,可以看到应用返回了:
HTTP/1.1 200
或者,可以使用 Postman 来验证协议版本。Postman 从 11.8 版开始支持 HTTP/2 协议,其中发送 HTTP 请求的协议版本仍为 HTTP/1.1 默认版本。可以在设置选项卡中更改协议版本:
请求发送后,可以从 Postman 控制台的原始日志中找到 HTTP 协议版本:
即使以 HTTP/2 发送请求,curl 和 Postman 也会返回 HTTP/1.1 响应。
5、Spring Boot 启用 HTTP/2
在 Spring Boot 应用中启用 HTTP/2 有两种方法。
第一个方法是定义一个配置类,将 Http2Protocol
类添加到 Tomcat HTTP connector 中:
@Configuration
public class Http2Config {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> getWebServerFactoryCustomizer() {
return factory -> {
Connector httpConnector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
httpConnector.setPort(8080);
factory.addConnectorCustomizers(connector -> connector.addUpgradeProtocol(new Http2Protocol()));
factory.addAdditionalTomcatConnectors(httpConnector);
};
}
}
该配置类可自定义嵌入式 Tomcat 服务器,并通过向 HTTP connector 添加 Http2Protocol
升级来启用 HTTP/2 支持。
除了现有的使用 SSL 运行 HTTP/2 的端口 8443 外,该配置还打开了一个额外的 HTTP 运行端口 8080。如果不想暴露额外的端口,可以使用其他方法启用 HTTP/2。
第二种方法更简单。只需在 application.yml 中将 server.http2.enabled
属性设置为 true
:
server:
http2:
enabled: true
在应用其中任何一种方法后重启应用,就可以执行相同的 curl 命令来查询 REST 端点;我们可以收到以下响应,显示 HTTP/2 已启用:
HTTP/2 200
如果再次向 Postman 发送请求,就会看到如下响应:
6、总结
HTTP/1.1 长期以来一直是传递 HTTP 请求的主流协议,而 HTTP/2 提供了更好的资源效率并减少了延迟。这是一个巨大的进步,使其成为现代 Web 应用的重大升级。
Ref:https://www.baeldung.com/spring-boot-http2-tomcat