JEP 110: HTTP/2 Client (Incubator)
Клиент HTTP/2 (Incubator (инкубационный модуль))
| Ответственный | Michael McMahon |
| Тип | Feature |
| Область | JDK |
| Статус | Closed / Delivered |
| Выпуск | 9 |
| Компонент | core-libs / java.net |
| Обсуждение | net dash dev at openjdk dot java dot net |
| Трудоёмкость | XL |
| Длительность | XL |
| Связан с | JEP 244: TLS Application-Layer Protocol Negotiation Extension |
| JEP 321: HTTP Client API | |
| Рецензенты | Alan Bateman |
| Одобрен | Brian Goetz |
| Создан | 2014/05/12 16:26 |
| Обновлён | 2026/07/29 19:02 |
| Задача | 8042950 |
Аннотация
Определить новый API HTTP-клиента, который реализует HTTP/2 и WebSocket и может заменить устаревший API HttpURLConnection. API будет поставляться в JDK 9 как модуль Incubator, как определено в JEP 11. Это означает следующее:
-
API и реализация не будут частью Java SE.
-
API будет находиться в пространстве имён jdk.incubator.
-
По умолчанию модуль не будет разрешаться ни при компиляции, ни во время выполнения.
Мотивация
У существующего API HttpURLConnection и его реализации много проблем:
-
Базовый API
URLConnectionпроектировался с расчётом на несколько протоколов, почти все из которых сейчас уже не используются (ftp,gopherи т. д.). -
API появился раньше HTTP/1.1 и слишком абстрактен.
-
Им трудно пользоваться, у него много недокументированного поведения.
-
Он работает только в блокирующем режиме (то есть один поток на каждую пару запрос/ответ).
-
Его очень трудно сопровождать.
Цели
-
Должен быть прост в использовании в типичных случаях, в том числе должен иметь простой блокирующий режим.
-
Должен уведомлять о таких событиях, как «заголовки получены», ошибки и «тело ответа получено». Это уведомление не обязательно должно быть основано на обратных вызовах: можно использовать асинхронный механизм, например CompletableFuture.
-
Простой и лаконичный API, который покрывает 80–90 % потребностей приложений. Вероятно, это означает сравнительно небольшой API, который не обязательно открывает все возможности протокола.
-
Должен давать доступ ко всем значимым аспектам HTTP-запроса к серверу и ответа от сервера (заголовки, тело, коды состояния и т. д.).
-
Должен поддерживать стандартные и распространённые механизмы аутентификации. На первом этапе поддержка будет ограничена только аутентификацией Basic.
-
Должен позволять легко выполнить установку соединения (handshake) WebSocket.
-
Должен поддерживать HTTP/2. (Семантика HTTP/2 на уровне приложения в основном совпадает с 1.1, хотя протокол передачи данных совершенно другой.)
-
Должен уметь договариваться о переходе с 1.1 на 2 (или отказе от него) либо выбирать 2 с самого начала.
-
Должен поддерживать server push, то есть возможность сервера отправлять ресурсы клиенту без явного запроса со стороны клиента.
-
-
Должен выполнять проверки безопасности так же, как существующий сетевой API.
-
Желательно, чтобы он был удобен для использования с новыми возможностями языка, такими как лямбда-выражения.
-
Желательно, чтобы он учитывал требования встраиваемых систем, в частности не использовал постоянно работающие потоки таймеров.
-
Должен поддерживать HTTPS/TLS.
-
Требования к производительности для HTTP/1.1:
-
Производительность должна быть на уровне существующей реализации
HttpURLConnection. -
Производительность должна быть на уровне библиотеки Apache HttpClient, а также Netty и Jetty при их использовании в качестве клиентского API.
-
Потребление памяти новым API должно быть на том же уровне или ниже, чем у
HttpURLConnection, Apache HttpClient, а также Netty и Jetty при их использовании в качестве клиентского API.
-
-
Требования к производительности для HTTP/2:
-
Производительность должна быть выше, чем у HTTP/1.1, в тех аспектах, которых ожидают от нового протокола (то есть по масштабируемости и задержке), с учётом любых ограничений платформы (например, окон подтверждения TCP-сегментов).
-
Производительность должна быть на уровне Netty и Jetty при их использовании в качестве клиентского API для HTTP/2.
-
Потребление памяти новым API должно быть на том же уровне или ниже, чем при использовании
HttpURLConnection, Apache HttpClient, а также Netty и Jetty в качестве клиентского API.
-
-
Производительность будет сравниваться только для сопоставимых режимов работы, поскольку в новом API упор делается на простоту и удобство использования, а не на охват всех возможных сценариев,
-
Эта работа предназначена для JDK 9. Часть кода может быть повторно использована в Java EE в реализации HTTP/2 в Servlet 4.0 API, поэтому будут использоваться только возможности языка JDK 8 и, где это возможно, только API JDK 8.
-
Предполагается, что с учётом опыта использования API в JDK 9 его можно будет стандартизировать в Java SE в пространстве имён java.net в JDK 10. Когда это произойдёт, в рамках будущего JEP, API перестанет существовать в виде Incubator-модуля.
Что не является целью
Предполагается, что со временем этот API заменит API HttpURLConnection в новом коде, но мы не планируем сразу же переписывать старый API на основе нового. Это может быть сделано в дальнейшем.
Некоторые требования рассматривались в более ранних версиях этого JEP для JDK 8, но от них отказались, чтобы API был как можно проще:
- фильтрация запросов и ответов,
- подключаемый кэш соединений и
- общий механизм перехода на другой протокол (upgrade).
Некоторые из этих требований, например кэширование соединений, станут менее важными по мере постепенного распространения HTTP/2.
Описание
Для JDK 9 была проведена работа над прототипом, в котором для HTTP-клиента, запросов и ответов были определены отдельные классы. Шаблон «строитель» (builder) использовался, чтобы отделить изменяемые сущности от неизменяемых результатов. Для отправки и получения определены синхронный блокирующий режим и асинхронный режим на основе java.util.concurrent.CompletableFuture.
Прототип был построен на NIO SocketChannels, а асинхронное поведение реализовано с помощью Selectors и предоставляемых извне ExecutorServices.
Реализация прототипа была автономной, то есть существующий стек не менялся, чтобы обеспечить совместимость и сделать возможным поэтапный подход, при котором с самого начала не требуется поддерживать всю функциональность.
API прототипа также включал:
- раздельные запросы и ответы, как в Servlet API и API HTTP-сервера;
- асинхронное уведомление о следующих событиях:
- получены заголовки ответа,
- ошибка ответа,
- получено тело ответа и
- server push (только HTTP/2);
- HTTPS через
SSLEngine; - работу через прокси;
- cookie и
- аутентификацию.
Больше всего доработки, вероятно, потребует та часть API, которая отвечает за поддержку множественных ответов HTTP/2 (server push) и настройку HTTP/2. Реализация прототипа поддерживает почти весь HTTP/1.1, но пока не поддерживает HTTP/2.
Работа через прокси для HTTP/2 будет реализована в одном из следующих изменений.
Альтернативы
Существует ряд API и реализаций HTTP-клиента, например Jetty и Apache HttpClient. Оба они довольно тяжеловесны с точки зрения количества пакетов и классов и не используют новые возможности языка, такие как лямбда-выражения.
Тестирование
Встроенный HTTP-сервер станет подходящей основой для регрессионных тестов и тестов TCK. Функциональные тесты тоже могут его использовать, но, возможно, их придётся проводить и на реальных HTTP-серверах.