Синхронизировать HTTP-запрос (HttpURLConnection) с высоким уровнем параллелизма?

#java #spring #spring-boot #push-notification

#java #весна #весенняя загрузка #push-уведомление

Вопрос:

Я использую HttpURLConnection в своем приложении Java (Spring) для отправки HTTP-запросов на внешние сторонние серверы. Мне нужно около 1000 http-запросов в секунду.

Однако IMHO HttpURLConnection является синхронным, поэтому один поток может выполнить только один http-запрос, и только после завершения этого запроса этот поток может выполнить следующий запрос. Поэтому это кажется неэффективным, и я подозреваю, что это даже невозможно обработать (пожалуйста, поправьте меня, если я ошибаюсь, например, это на самом деле очень эффективно).

Интересно, есть ли хороший способ справиться с этим? ИМХО я буду использовать пул потоков (исполнитель), содержащий, скажем, 100 потоков.

PS Я не могу использовать какие-либо другие библиотеки, такие как HttpClient , поскольку этот пакет SDK предоставляется третьей стороной :/

Большое спасибо!

Комментарии:

1. Почему HttpClient отключен от таблицы, но HttpURLConnection все еще доступен? Как насчет необработанных сокетов?

2. @Charlie К сожалению, я использую сторонние библиотеки (например, XiaoMi Push), и у меня нет их исходного кода, только файл jar: ( Они выбирают HttpURLConnection.

Ответ №1:

1. Вы правы насчет запроса в одном потоке.Это упоминается в документе HttpURLConnection

 * Each HttpURLConnection instance is used to make a single request
 * but the underlying network connection to the HTTP server may be
 * transparently shared by other instances. Calling the close() methods
 * on the InputStream or OutputStream of an HttpURLConnection
 * after a request may free network resources associated with this
 * instance but has no effect on any shared persistent connection.
 * Calling the disconnect() method may close the underlying socket
 * if a persistent connection is otherwise idle at that time.
 *
  

Это означает, что вы могли бы использовать openConnection для получения нового экземпляра HttpURLConnection, затем выполнить запрос и закрыть его.Базовое сетевое подключение к HTTP-серверу может быть прозрачно совместно использовано другим экземпляром.

Комментарии:

1. Итак, есть предложения о том, как сделать это эффективно: / Спасибо!

Ответ №2:

Socket и SocketChannel s может быть хорошим вариантом, хотя вам придется «свернуть свой собственный» HTTP, что будет очень непросто, если вам придется иметь дело с HTTPS. Они являются частью стандартной JRE и также могут использоваться асинхронно. При переходе в асинхронный режим вы сталкиваетесь с каким-то сложным кодом, потому что с Selector API немного сложно работать, но он определенно будет быстрым и с низкими накладными расходами.

Возможно, вы сможете использовать пользовательский SSLSocketFactory для настройки сокета, чтобы у вас был прямой доступ к сокету для получения SocketChannel.

Комментарии:

1. Извините, я не могу коснуться кода, используя HttpURLConnection, который находится глубоко внутри какой-то сторонней библиотеки:(