JEP 110:HTTP/2 客户端(孵化器)
概括
定义一个新的 HTTP 客户端 API,该 API 实现 HTTP/2 和 WebSocket,并且可以替换旧HttpURLConnection
API。该 API 将作为孵化器模块提供,如JEP 11中所定义,与 JDK 9 一起提供。这意味着:
-
API 和实现不会成为 Java SE 的一部分。
-
该 API 将位于 jdk.incubtor 命名空间下。
-
默认情况下,该模块不会在编译或运行时解析。
动机
现有的HttpURLConnection
API及其实现存在很多问题:
-
基本
URLConnection
API 在设计时考虑了多种协议,几乎所有协议现在都已失效(ftp
、gopher
等)。 -
该 API 早于 HTTP/1.1,并且过于抽象。
-
它很难使用,有许多未记录的行为。
-
它仅在阻塞模式下工作(即每个请求/响应一个线程)。
-
维护起来非常困难。
目标
-
必须易于在常见情况下使用,包括简单的阻止模式。
-
必须提供事件通知,例如“收到标头”、错误和“收到响应正文”。此通知不一定基于回调,而是可以使用像 CompletableFuture 这样的异步机制。
-
简单简洁的API,可满足80-90%的应用需求。这可能意味着 API 占用空间相对较小,不一定会暴露协议的所有功能。
-
必须向服务器公开 HTTP 协议请求的所有相关方面以及服务器的响应(标头、正文、状态代码等)。
-
必须支持标准和通用的身份验证机制。这最初仅限于基本身份验证。
-
必须能够轻松设置 WebSocket 握手。
-
必须支持HTTP/2。 (HTTP/2 的应用程序级语义与 1.1 基本相同,尽管有线协议完全不同。)
-
必须能够协商从 1.1 升级到 2(或不能),或者从一开始就选择 2。
-
必须支持服务器推送,即服务器能够在无需客户端显式请求的情况下将资源推送给客户端。
-
-
必须执行与现有网络 API 一致的安全检查。
-
应该对新的语言功能(例如 lambda 表达式)友好。
-
应适合嵌入式系统要求,特别是避免永久运行的计时器线程。
-
必须支持 HTTPS/TLS。
-
HTTP/1.1 的性能要求:
-
性能必须与现有
HttpURLConnection
实施相媲美。 -
当用作客户端 API 时,性能必须与 Apache HttpClient 库以及 Netty 和 Jetty 相当。
-
HttpURLConnection
当用作客户端 API 时,新 API 的内存消耗必须等于或低于Apache HttpClient、Netty 和 Jetty。
-
-
HTTP/2 的性能要求:
-
尽管有任何平台限制(例如,TCP 段确认窗口),但在新协议所期望的方面(即可扩展性和延迟),性能必须优于 HTTP/1.1。
-
当用作 HTTP/2 的客户端 API 时,性能必须与 Netty 和 Jetty 相当。
-
HttpURLConnection
当用 作客户端 API 时,新 API 的内存消耗必须与使用 、Apache HttpClient 以及 Netty 和 Jetty时的内存消耗相当或更低。
-
-
性能比较只会在可比较的操作模式下进行,因为新的 API 将强调简单性和易用性,而不是涵盖所有可能的用例,
-
这项工作适用于 JDK 9。Java EE 在 Servlet 4.0 API 中实现 HTTP/2 时可能会重复使用某些代码,因此将仅使用 JDK 8 语言功能以及 API(如果可能)。
-
目的是凭借在 JDK 9 中使用 API 的经验,可以在 JDK 10 中的 java.net 命名空间下标准化 Java SE 中的 API。当这种情况发生时,作为未来 JEP 的一部分,API将不再作为孵化器模块存在。
非目标
该 API 的目的是最终替换HttpURLConnection
新代码的 API,但我们并不打算立即使用新 API 重新实现旧 API。这可能会在未来的工作中发生。
JDK 8 的 JEP 的早期版本考虑了一些要求,但为了使 API 尽可能简单,这些要求被省略:
- 请求/响应过滤,
- 可插拔连接缓存,以及
- 通用升级机制。
随着 HTTP/2 的逐渐采用,其中一些要求(例如连接缓存)将变得不那么重要。
描述
JDK 9 已经完成了一些原型设计工作,其中为 HTTP 客户端、请求和响应定义了单独的类。构建器模式用于将可变实体与不可变产品分开。为发送和接收定义了同步阻塞模式,还定义了基于 java.util.concurrent.CompletableFuture 的异步模式。
该原型构建在 NIO SocketChannel 上,并通过 Selectors 和外部提供的 ExecutorServices 实现异步行为。
原型实现是独立的,即现有堆栈没有更改,以确保兼容性并允许采用分阶段方法,其中并非所有功能必须在开始时得到支持。
原型 API 还包括:
- 分离请求和响应,如 Servlet 和 HTTP 服务器 API;
- 以下事件的异步通知:
- 收到响应标头,
- 响应错误,
- 收到响应正文,并且
- 服务器推送(仅限 HTTP/2);
- HTTPS,通过
SSLEngine
; - 代理;
- 饼干;和
- 验证。
API 最可能需要进一步工作的部分是支持 HTTP/2 多响应(服务器推送)和 HTTP/2 配置。原型实现支持几乎所有 HTTP/1.1,但尚不支持 HTTP/2。
HTTP/2 代理将在以下更改中实现。
备择方案
存在许多现有的 HTTP 客户端 API 和实现,例如Jetty和Apache HttpClient。就包和类的数量而言,这两者都相当重量级,并且它们没有利用新的语言功能,例如 lambda 表达式。
测试
内部 HTTP 服务器将为回归和 TCK 测试提供合适的基础。功能测试也可以使用它,但它们可能需要针对真实的 HTTP 服务器进行测试。