Nginx proxy_read_timeout против proxy_connect_timeout


15

Я начал использовать Nginx в качестве обратного прокси-сервера для набора серверов, которые предоставляют какую-то услугу.

Служба может быть довольно медленной (иногда она работает на Java, а JVM иногда застревает в «полной сборке мусора», которая может занять несколько секунд), поэтому я установил proxy_connect_timeoutзначение 2 секунды, что даст Nginx достаточно времени для расчета выяснилось, что служба зависла на GC и не будет отвечать вовремя, и она должна передать запрос на другой сервер.

Я также установил, proxy_read_timeoutчтобы обратный прокси-сервер не зависал, если самой службе требуется слишком много времени для вычисления ответа - опять же, он должен переместить запрос на другой сервер, который должен быть достаточно свободным, чтобы вернуть своевременный ответ.

Я запустил некоторые тесты и ясно вижу, что все proxy_connect_timeoutработает правильно, поскольку некоторые запросы возвращаются точно в то время, которое указано для времени ожидания соединения, поскольку служба застревает и не принимает входящие соединения (служба использует Jetty в качестве встроенного контейнер сервлетов). proxy_read_timeoutТакже работает, как я могу видеть запросы, возврат после тайм - аута указан там.

Проблема заключается в том, что я ожидал бы увидеть некоторые запросы по истечении proxy_read_timeout + proxy_connect_timeoutили почти через некоторое время, если служба застряла и не будет принимать соединения, когда Nginx пытается получить к ней доступ, но до того, как Nginx сможет отключиться - она ​​освобождается и начинает обработку, но идет слишком медленно, и Nginx прерывает работу из-за тайм-аута чтения. Я считаю, что у службы есть такие случаи, но после выполнения нескольких тестов, насчитывающих несколько миллионов запросов, я не смог увидеть ни одного запроса, который бы возвращал что-либо выше proxy_read_timeout(что является большим временем ожидания).

Я был бы признателен за любые комментарии по этому вопросу, хотя я думаю, что это может быть связано с ошибкой в ​​Nginx (я пока не смотрю на код, так что это всего лишь предположение), что счетчик тайм-аут не сбрасывается после подключения успешно, если Nginx ничего не читал с вышестоящего сервера.


1
Какая версия NGINX? Я думаю, что помню что-то подобное в более старой версии (возможно, около 0.6 / 7), но это было исправлено в более поздней версии (последняя стабильная версия 1.0.5), но это может быть неправильно. Все еще зная, что ваша версия поможет
Smudge

Обратите внимание, что в документах говорится proxy_read_timeoutне «глобальное время ожидания», а между двумя операциями чтения.
Пой

@Sam: я использую Nginx 1.0.0. @poige - да, я знаю об этом, поэтому я ожидаю, что общее время ожидания будет proxy_read_timeout + proxy_connect_timeout.
Гусс

1
В качестве примечания, вам, вероятно, следует изучить некоторые настройки одновременной сборки мусора для вашей JVM: en.wikipedia.org/wiki/…
полином

@polynomial: мы это сделали, но в соответствии с нашими тестами одновременная сборка мусора приводит к тому, что GC теряет больше процессорного времени по сравнению с GC «Stop the World», поэтому мы предпочитаем инвестировать в настройку Nginx :-)
Guss

Ответы:


18

Я не смог воспроизвести это на:

2011/08/20 20:08:43 [notice] 8925#0: nginx/0.8.53
2011/08/20 20:08:43 [notice] 8925#0: built by gcc 4.1.2 20080704 (Red Hat 4.1.2-48)
2011/08/20 20:08:43 [notice] 8925#0: OS: Linux 2.6.39.1-x86_64-linode19

Я установил это в моем nginx.conf:

proxy_connect_timeout   10;
proxy_send_timeout      15;
proxy_read_timeout      20;

Затем я настраиваю два тестовых сервера. Тот, который будет просто тайм-аут на SYN, и тот, который будет принимать соединения, но никогда не отвечать:

upstream dev_edge {
  server 127.0.0.1:2280 max_fails=0 fail_timeout=0s; # SYN timeout
  server 10.4.1.1:22 max_fails=0 fail_timeout=0s; # accept but never responds
}

Затем я отправил в одном тестовом соединении:

[m4@ben conf]$ telnet localhost 2480
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
Host: localhost

HTTP/1.1 504 Gateway Time-out
Server: nginx
Date: Sun, 21 Aug 2011 03:12:03 GMT
Content-Type: text/html
Content-Length: 176
Connection: keep-alive

Затем посмотрел error_log, который показал это:

2011/08/20 20:11:43 [error] 8927#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: 127.0.0.1, server: ben.dev.b0.lt, request: "GET / HTTP/1.1", upstream: "http://10.4.1.1:22/", host: "localhost"

тогда:

2011/08/20 20:12:03 [error] 8927#0: *1 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 127.0.0.1, server: ben.dev.b0.lt, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:2280/", host: "localhost"

И затем access.log, который имеет ожидаемое время ожидания 30 с (10 + 20):

504:32.931:10.003, 20.008:.:176 1 127.0.0.1 localrhost - [20/Aug/2011:20:12:03 -0700] "GET / HTTP/1.1" "-" "-" "-" dev_edge 10.4.1.1:22, 127.0.0.1:2280 -

Вот формат журнала, который я использую, который включает индивидуальные таймауты:

log_format  edge  '$status:$request_time:$upstream_response_time:$pipe:$body_bytes_sent $connection $remote_addr $host $remote_user [$time_local] "$request" "$http_referer" "$http_user_agent" "$http_x_forwarded_for" $edge $upstream_addr $upstream_cache_status';

1
Мой вопрос выше в вашем сценарии больше похож на этот: предположим, что тестовый сервер принимает соединение через произвольное время между 0 и 20 секундами, а затем ожидает произвольное время между 19 и 21 секундами, прежде чем ответить. Затем запустите простой тест на это. Я ожидаю увидеть около 50% результатов запросов с тайм-аутом 10 секунд, 25% с тайм-аутом 20 ~ 30 секунд и 25% получат успешный ответ. В таком случае, сколько успешных запросов займет более 20 секунд? В моем тесте ни один из них - и это меня беспокоит.
Guss

Я проверил, настроив случайную потерю в SYN и затем установив CGI, который действительно медленно выплевывает линии в течение 50 секунд. Мне удалось увидеть, что запросы занимают намного больше времени, чем оба тайм-аута вместе, но все еще успешно: box.access.log 200: 69.814: 67.100:.: 1579 33 127.0.0.1 test.host - [21 / Aug / 2011: 20: 30:52 -0700] "GET / huugs HTTP / 1.1" "-" "-" "-" dev_edge 127.0.0.1:2280 -
полином

Хорошо, это странно на другом уровне :-). Одно из возможных объяснений состоит в том, что Nginx требуется время для написания запроса ( proxy_send_timeout), и, если вы установите его выше proxy_connection_timeout, это фактически может объяснить любую задержку в течение 20 секунд proxy_read_timeout. Когда вы говорите «выплевываете линии очень медленно» - что вы имеете в виду?
Гусс

сон 1 между печатными строками HTML в теле ответа. Просто показывать, как происходит proxy_read_timeout между чтениями, а не все чтение.
полином

1
Ах я вижу. Ну, это определенно не мой случай, и я извиняюсь за то, что не разъяснил это в моем ОП. В моем случае сервер приложений завершает всю обработку перед возвратом какого-либо ответа, а затем возвращает все сразу - так что proxy_read_timeoutлибо запрос полностью завершается неудачей, либо он полностью разрешается. Это также объясняет разницу между поведением, которое вы видите, и поведением, которое я вижу.
Гусс

3

Проблема заключается в том, что я ожидал бы увидеть некоторые запросы с истечением тайм-аута после proxy_read_timeout + proxy_connect_timeout или почти через такой промежуток времени, если сервис застрял и не будет принимать подключения, когда Nginx пытается получить к нему доступ, но до того, как Nginx сможет тайм-аут - он освобождается и начинает обработку, но работает слишком медленно, и Nginx прерывает работу из-за тайм-аута чтения.

Тайм-аут соединения означает, что TCP останавливается при установлении связи (например, не было SYN_ACK). TCP повторил бы попытку отправки SYN, но вы дали только 2 секунды. в Nginx, чтобы перейти на другой сервер, поэтому у него просто нет времени для повторной отправки SYN.

UPD. : Не может найти в документах, но tcpdump показывает, что есть 3 секунды. задержка между первой отправленной SYN и второй попыткой отправить SYN.


Я не думаю, что это именно то, о чем я спрашиваю - вопрос в том, что если восходящий поток зависает и возвращает SYN_ACK через 1,999 секунды, почему nginx не продолжит процесс с текущим восходящим потоком?
Гусс

Ну, вы можете использовать сниффер, если вы хотите быть точно уверены. Может оказаться, что в течение <2 сек вообще нет ACK.
Пой

Я не могу использовать сниффер, потому что я ожидаю увидеть такое поведение в условиях высокой нагрузки на систему. Объяснение того, что ACK никогда не идут позже, чем некоторые X, но ранее, чем через 2 секунды, даже при рассмотрении миллионов запросов, кажется неправдоподобным.
Guss
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.