Назад | Перейти на главную страницу

NGINX продолжает отправлять запросы в офлайн-апстрим

У меня следующая конфигурация балансировки нагрузки:

upstream upstream {
  ip_hash;
  keepalive 1000;
  server 10.10.10.1;
  server 10.10.10.2;
  server 10.10.10.3;
}

server {
  listen                  443;
  server_name             example.com;
  ssl_certificate         /etc/nginx/certs/cert.crt;
  ssl_certificate_key     /etc/nginx/certs/cert.key;

  ssl on;
  ssl_session_cache  builtin:1000  shared:SSL:10m;
  ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
  ssl_prefer_server_ciphers on;

  location / {
      client_max_body_size        80m;
      proxy_http_version          1.1;
      proxy_set_header Connection "";
      proxy_set_header            Host $host;
      proxy_set_header            X-Real-IP $remote_addr;
      proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header            X-Forwarded-Proto $scheme;
      proxy_read_timeout          90;
      proxy_pass                  http://upstream;
  }
}

Хотя мои внутренние узлы стабильны, все работает нормально. Однако, когда я выключаю один из узлов (например, 10.10.10.2), NGINX будет продолжать отправлять на него трафик, даже если запросы продолжают время ожидания (поскольку сервер выключен). Я уже пробовал настроить max_fails и fail_timeout параметры, но поведение остается прежним.

Может ли NGINX автоматически определять, что сервер не работает, и не отправлять туда трафик? Какая конфигурация мне не хватает?

Что такое keepalive?

Идея поддержки активности состоит в том, чтобы решить проблему задержки установления TCP-соединений в сетях с высокой задержкой. Для установления TCP-соединения требуется трехэтапное рукопожатие, поэтому при заметной задержке между клиентом и сервером поддержка активности значительно ускорит процесс за счет повторного использования существующих соединений.

Почему люди ставят nginx перед своими серверными модулями?

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

Обратите внимание, что nginx даже не поддерживал upstream keepalive до 1.1.4, согласно http://nginx.org/r/keepalive, поскольку, как указано выше, с большей вероятностью будет использоваться больше ресурсов вашего восходящего потока, чем для ускорения любой обработки, при условии, что у вас есть задержка менее миллисекунды между всеми вашими хостами (например, между nginx и вышестоящими серверами).

Вы видите, куда он идет?

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

Что происходит, когда служба / порт не работает?

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

Если мы остановим службу на бэкэнде, nginx справится с этим правильно. Проблема воспроизводится только при остановке всей виртуальной машины. - Рамиро Беррелеза, 27 октября в 22:48

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

Что делать?

  • Во-первых, как уже упоминалось, даже если вы не испытывали описанных вами проблем, вы, вероятно, только замедляете работу, используя upstream keepalive функциональность в локальной сети, особенно с таким большим числом.

  • В противном случае вы можете настроить свою настройку (брандмауэр, маршрутизатор, среда виртуализации и т. Д.), Чтобы возвращать соответствующие пакеты для недоступных хостов, что, безусловно, должно заставить nginx работать должным образом, поскольку вы уже сами проверили, что происходит, когда TCP RST пакеты фактически возвращаются хостом.

  • Другой вариант - настроить различные таймауты в nginx, чтобы учесть возможность бесследного исчезновения ваших восходящих потоков и компенсировать невозможность вашей сети генерировать соответствующие контрольные пакеты.

    Это может включать connect(2) таймаут для установления новых TCP-соединений через http://nginx.org/r/proxy_connect_timeout в миллисекундном диапазоне (например, если все ваши серверы находятся в локальной сети, и вы НЕ используете программное обеспечение корпоративного уровня с мультисекундными задержками корпоративного уровня), а также таймауты для текущих read(2) и send(2) операции через http://nginx.org/r/proxy_read_timeout и http://nginx.org/r/proxy_send_timeoutсоответственно, что будет зависеть от того, как быстро ваше внутреннее приложение должно отвечать на запросы. Вы также можете увеличить fail_timeout параметр server директива в upstream контекст, согласно http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server.

Попробуйте установить keepalive 16 и снова протестируем. 1k кешированных соединений на одного рабочего может быть слишком много для вашего случая.