#java #c #linux #tcp #operating-system
Вопрос:
Допустим, у нас есть веб-клиент Java, такой как spring RestTemplate
. Он может быть настроен с таймаутом чтения:
RestTemplateBuilder() .setReadTimeout(Duration.ofMillis(1000)) .build()
Если выполняется вызов http и сервер медленно отвечает, будет выдано исключение: java.net.SocketTimeoutException
Вопрос в следующем: что происходит с базовым TCP-соединением, когда наступает тайм-аут?
Из того, что я могу сказать RestTemplate
, использует SocketInputStream
ниже, который, в свою очередь, использует родной poll
язык в Linux. poll
принимает параметр тайм-аута, но закрывает ли он соединение при наступлении тайм-аута? Если нет, то что произойдет с ответом, когда он будет получен?
Как поведение тайм-аутов отличается между Http1 и Http2 (которые поддерживают мультиплексирование по одному TCP-соединению)?
Комментарии:
1. На уровне сокета во время ожидания ничего не происходит, кроме возврата вызова. Вы можете представить себе цикл опроса, в котором вы время от времени проверяете поступление данных, используя тайм-аут, чтобы убедиться, что вы не блокируетесь на «слишком долгое» ожидание. Это поддается проверке простым экспериментом.
2. @user16632363 значит, соединение осталось висеть? Когда он закрывается, если нет ответа? после истечения срока действия «сохранить жизнь»? И что, если есть ответ после тайм-аута, он отбрасывается?
3. Я далек от эксперта, но я думаю, что в программном обеспечении потребительского класса вызов сокета либо не блокируется, либо, если он блокируется, запускается другой поток для проверки времени ожидания. Когда наступает тайм-аут, сокет просто отбрасывается (с закрытием), и, если сервер ответит позже, он просто отправляется на сетевую карту клиента и отбрасывается. ОС не проверяет поступление пакетов, так как соединение закрыто, поэтому она просто ничего не делает. Возможно, ОС все еще получает пакеты, хотя. Я не так уверен, так как я никогда не писал драйвер Ethernet/WIFI.
4. Это не «оставлено в подвешенном состоянии». Опрос с истекшим временем ожидания оставляет сокет и базовое TCP-соединение в том же состоянии, в котором вы вообще не вызывали опрос. Полученные данные остаются в сокете до тех пор, пока не будут получены. Сокет закрывается, когда вы вызываете close.