Мы уже затронули важность тайм-аутов и описали самые важные связанные ручки JDBC. Следующий аспект тайм-аутов, на котором я хотел бы остановиться, — это использование клиентов API. В частности, HTTP-клиенты, которые на сегодняшний день являются наиболее популярными. Мы рассмотрим несколько популярных библиотек HTTP-клиентов и их конфигурацию в отношении тайм-аутов.
Время ожидания HttpURLConnection
HttpURLConnection
доступен с тех пор, как JDK 1.1 получил возможность тайм-аута сетевого взаимодействия в версии JDK 5. 2 доступных тайм-аута setConnectionTimeout
, setReadTimeout
определяют, как долго ждать до установления соединения и как долго ждать данных с сервера соответственно. Значения по умолчанию: бесконечность ‼️.
Время ожидания Apache HttpClient
HttpClient из пакета Apache HttpComponents был стандартным выбором для связи по протоколу http. Это зрелый проект с богатым API, который устраняет многие HttpURLConnection
недостатки, например. пул соединений. Многие из API устарели, например. DefaultHttpClient
, org.apache.http.params.CoreConnectionPNames
поэтому нужно быть осторожным при установке тайм-аутов, которые они возвращают к системным значениям по умолчанию на уровне сокета.
Доступны 3 настройки времени ожидания:
val requestConfig = RequestConfig.custom() // Determines the timeout in milliseconds until a connection is established. .setConnectTimeout(5_000) // Defines the socket timeout in milliseconds, // which is the timeout for waiting for data or, put differently, // a maximum period inactivity between two consecutive data packets). .setSocketTimeout(5_000) // Returns the timeout in milliseconds used when requesting a connection // from the connection manager. .setConnectionRequestTimeout(2_000) .build()
requestConfig
можно использовать по умолчанию для экземпляра HttpClient
:
val httpClient = HttpClients.custom() .setDefaultRequestConfig(requestConfig) .build()
Также есть возможность настроить каждый запрос отдельно:
val get = HttpGet("http://httpbin.org/get").apply { config = requestConfig } httpClient.execute(get)
OkHttp
OkHttp — мой любимый клиент HTTP и HTTP/2 для приложений Android и Java. Он эффективен и имеет хорошие настройки по умолчанию. Доступны 3 настройки времени ожидания:
val client = OkHttpClient.Builder() // Sets the default connect timeout for new connections. .connectTimeout(5, TimeUnit.SECONDS) // Sets the default read timeout for new connections. .readTimeout(10, TimeUnit.SECONDS) // Sets the default write timeout for new connections. .writeTimeout(20, TimeUnit.SECONDS) .build()
Все connectTimeout
, readTimeout
и writeTimeout
по умолчанию равны 10 секундам 👍.
Тайм-ауты XMLHttpRequest и Fetch API
XMLHttpRequest
является стандартной основой сетевого взаимодействия веб-приложений уже более 10 лет. В настоящее время он заменяется Fetch API, но он по-прежнему остается и будет оставаться самым популярным в течение нескольких лет. В XMLHttpRequest
доступна только одна конфигурация timeout
:
Свойство XMLHttpRequest.timeout представляет собой тип long без знака, представляющий количество миллисекунд, которое может занять запрос, прежде чем он будет автоматически завершен. Значение по умолчанию – 0, что означает отсутствие тайм-аута.
По умолчанию бесконечен ‼️
Поскольку значение по умолчанию не настроено, мы должны тщательно установить тайм-аут в нашем коде! Может возникнуть соблазн подумать, что тайм-аут на стороне клиента не так важен по сравнению с тайм-аутом на сервере. Мягко говоря, это сомнительное отношение. Мы должны иметь в виду, что существует жесткое ограничение на количество подключений браузера к одному домену, что очень важно, если мы используем HTTP 1.*. Когда мы достигнем максимального количества одновременно открытых подключений, любое новое XMLHttpRequest
будет стоять в очереди на неопределенный срок. Значение ограничения варьируется в браузерах, и недавний RCF ослабляет его. HTTP/2 решает проблему с мультиплексированием соединений, тем не менее его распространение все еще невелико. По данным w3techs это около 20% на сегодняшний день. Значение тайм-аута, используемое в XMLHttpRequest
, еще более важно в одностраничных приложениях. В SPA XMLHttpRequest
без тайм-аута может существовать до тех пор, пока сервер и промежуточные сетевые стороны позволяют эффективно блокировать все последующие сетевые вызовы.
Fetch API призван заменить XMLHttpRequest
. Таким образом, печально, что возможность тайм-аута запроса еще не стала стандартом. В настоящее время не существует стандартного способа установить тайм-аут. Есть несколько активных проблем GitHub: Добавить параметр тайм-аута, Добавить параметр для автоматического отклонения обещания выборки по истечении определенного времени, которые охватывают возможные решения. Было предложение по отменяемым обещаниям, которое было отозвано после много обсуждений и отсутствия консенсуса. Совершенно новый способ, недавно реализованный Edge и Firefox, позволяет прерывать вызов Fetch API 🎉 через стандартизированную DOM AbortController
. Надеюсь, он скоро войдет в стандарт Fetch API.
const controller = new AbortController(); const signal = controller.signal; setTimeout(() => controller.abort(), 5000); fetch(url, { signal }).then(response => { return response.text(); }).then(text => { console.log(text); });
Время ожидания сеанса URL
URLSession
является преемником NSURLConnection
, который лежит в основе большинства, если не всех http-клиентов iOS, например. Аламофайр. Существует 2 основных значения времени ожидания для настройки, оба из которых имеют значения по умолчанию, доступные через URLSessionConfiguration.default
:
let sessionConfig = URLSessionConfiguration.default sessionConfig.timeoutIntervalForRequest = 20.0 sessionConfig.timeoutIntervalForResource = 40.0 let session = URLSession(configuration: sessionConfig)
К счастью, настроены значения по умолчанию:
timeoutIntervalForRequest
:
Это свойство определяет интервал времени ожидания запроса для всех задач в сеансах на основе этой конфигурации. Интервал времени ожидания запроса определяет, как долго (в секундах) задача должна ждать получения дополнительных данных, прежде чем сдаться. Таймер, связанный с этим значением, сбрасывается всякий раз, когда поступают новые данные. Значение по умолчанию — 60.
timeoutIntervalForResource
:
Это свойство определяет интервал времени ожидания ресурса для всех задач в сеансах на основе этой конфигурации. Интервал времени ожидания ресурса определяет, как долго (в секундах) ждать передачи всего ресурса, прежде чем отказаться от него. Значение по умолчанию — 7 дней.
Обратите внимание, что timeoutIntervalForResource
— это тайм-аут более высокого уровня, чем то, что мы рассматривали в других HTTP-клиентах. Он включает в себя повторные попытки и / или тайм-ауты запросов, поэтому имеет большое значение по умолчанию.
Резюме
Многие HTTP-клиенты не имеют хорошей конфигурации тайм-аута по умолчанию. Следовательно, если вы заботитесь об использовании ресурсов вашего приложения и стабильности системы, вы должны тщательно просмотреть и настроить тайм-ауты, где это применимо. Отрадно видеть, что современные HTTP-клиенты, например. OkHttp и URLSession имеют короткий, но разумный вариант по умолчанию.
Первоначально опубликовано на brightinventions.pl
Пётр Мионсковски,поклонник TDD, стремящийся узнать что-то новое
Личный блог Электронная почта Twitter Github Stackoverflow
Эта статья кросспостирована с личным блогом автора.