openjdk.ruOpenJDK на русском

JEP 418: Internet-Address Resolution SPI

SPI для разрешения интернет-адресов

ОтветственныйAleksej Efimov
ТипFeature
ОбластьSE
СтатусClosed / Delivered
Выпуск18
Компонентcore-libs / java.net
Обсуждениеnet dash dev at openjdk dot java dot net
ДлительностьS
РецензентыAlan Bateman, Brian Goetz, Chris Hegarty, Daniel Fuchs
ОдобренBrian Goetz
Создан2021/03/16 16:43
Обновлён2022/09/09 10:29
Задача8263693

Аннотация

Определить интерфейс поставщика услуг (service-provider interface, SPI) для разрешения имён хостов и адресов, чтобы java.net.InetAddress мог использовать не только встроенный резолвер платформы, но и другие резолверы.

Что не является целью

  • Разработка альтернативного резолвера для включения в JDK не является целью. По умолчанию по-прежнему будет использоваться встроенный резолвер JDK.

  • Поддержка в SPI операций разрешения сверх тех, которые нужны API InetAddress, не является целью.

  • Определение неблокирующих или асинхронных API разрешения не является целью.

Мотивация

API java.net.InetAddress преобразует имена хостов в адреса Internet Protocol (IP) и обратно. Сейчас API использует собственный резолвер операционной системы, который обычно настроен на совместное использование локального файла hosts и системы доменных имён (Domain Name System, DNS).

Причины определить интерфейс поставщика услуг для разрешения имён и адресов:

  • Проект Loom. Сейчас операция разрешения через API InetAddress блокируется в вызове операционной системы. Для Virtual Threads (виртуальные потоки) проекта Loom, работающих в пользовательском режиме, это проблема: пока операция разрешения не завершится, нижележащие платформенные потоки не могут обслуживать другие потоки Virtual Threads. Альтернативный резолвер мог бы реализовать клиентский протокол DNS напрямую, без блокировки.

  • Новые сетевые протоколы. SPI для резолверов позволил бы беспрепятственно интегрировать новые протоколы разрешения, например DNS поверх QUIC, TLS или HTTPS.

  • Настройка. SPI для резолверов дал бы фреймворкам и приложениям более тонкий контроль над результатами разрешения и позволил бы встраивать в существующие библиотеки собственный резолвер.

  • Тестирование. При прототипировании и тестировании часто нужно управлять результатами разрешения имён хостов и адресов, например при создании mock-объектов для компонентов, которые используют API InetAddress.

Описание

API InetAddress определяет несколько методов для операций поиска:

  • InetAddress::getAllByName выполняет прямой поиск: сопоставляет имени хоста набор IP-адресов.

  • InetAddress::getByName тоже выполняет прямой поиск: сопоставляет имени хоста первый адрес из его набора адресов.

  • InetAddress::getCanonicalHostName выполняет обратный поиск: сопоставляет IP-адресу полное доменное имя. Например:

    var addressBytes = new byte[] { (byte) 192, 0, 43, 7};
    var resolvedHostName = InetAddress.getByAddress(addressBytes)
                                      .getCanonicalHostName();
  • InetAddress::getHostName при необходимости тоже выполняет обратный поиск.

По умолчанию InetAddress выполняет поиск с помощью собственного резолвера операционной системы. Результат поиска, положительный или отрицательный, может кэшироваться, чтобы не выполнять повторный поиск того же хоста.

Интерфейс поставщика услуг

API InetAddress будет находить поставщика резолвера с помощью загрузчика сервисов. Если поставщик не найден, как и раньше будет использоваться встроенная реализация.

Новые классы в пакете java.net.spi:

  • InetAddressResolverProvider — абстрактный класс, определяющий сервис, который находит java.util.ServiceLoader. По сути, InetAddressResolverProvider — это фабрика резолверов. Созданный резолвер будет установлен как общесистемный, и InetAddress будет передавать ему все запросы на поиск.

  • InetAddressResolver — интерфейс, определяющий методы для базовых операций прямого и обратного поиска. Экземпляр этого интерфейса получают из экземпляра InetAddressResolverProvider.

  • InetAddressResolver.LookupPolicy — класс, экземпляры которого описывают характеристики запроса на разрешение, в том числе запрошенный тип адреса и порядок, в котором должны возвращаться адреса.

  • InetAddressResolverProvider.Configuration — интерфейс, описывающий встроенную конфигурацию платформы для операций разрешения. Он даёт доступ к имени локального хоста и встроенному резолверу. Собственные поставщики резолверов используют его, чтобы начальным образом построить резолвер или частично передавать запросы на разрешение собственному резолверу операционной системы.

Альтернативы

Без SPI, подобного предложенному здесь, приложениям придётся и дальше использовать существующие обходные решения.

  • Приложение может искать сетевые имена и адреса с помощью Java Naming and Directory Interface (JNDI) и его поставщика DNS. Этот подход может быть полезен приложениям, которым нужен тонкий контроль над поиском в DNS, но он не связан с InetAddress, поэтому его использование вместе с сетевым API платформы требует дополнительных усилий.

  • Приложение может напрямую использовать библиотеки резолвера операционной системы через Java Native Interface (JNI) или foreign function API из проекта Panama. Однако, как и в случае JNDI, этот подход не связан с InetAddress, поэтому пользоваться им неудобнее.

  • Приложение может с помощью нестандартного системного свойства JDK jdk.net.hosts.file настроить InetAddress так, чтобы имена хостов сопоставлялись IP-адресам по заданному файлу, а не через собственный резолвер операционной системы. Эта возможность полезна для тестирования, но не является универсальным решением, поскольку полный список имён хостов не всегда известен заранее.

Тестирование

Мы разработаем новые тесты для SPI резолверов.

Мы разработаем экспериментальные поставщики резолверов (proof of concept), чтобы продемонстрировать и проверить, что с помощью SPI можно разрабатывать и развёртывать альтернативные реализации, которые используются вместо встроенной реализации JDK. Как минимум один из этих поставщиков мы сделаем доступным, чтобы на его основе можно было разрабатывать более полные реализации.