Перейти к содержанию

Балансировка нагрузки и медленные клиенты

Страница для инженера эксплуатации, который ставит перед кластером балансировщик или обратный прокси: на какие узлы направлять запросы, каким эндпоинтом проверять узел и какие таймауты задать, чтобы медленные клиенты не мешали остальным.

Балансировка нагрузки

Балансировщик может направлять запросы на любой узел, и привязка клиента к узлу не нужна. Каждый инстанс с сервисом s3r_api открывает собственный порт и обслуживает обращения к любым данным кластера: строка объекта и его фрагменты находятся по кластерной карте размещения, а не по узлу, на который пришёл запрос.

Исключение — запись при ярусах на разных инстансах. Запись выполняет инстанс, принявший запрос, в свою группу размещения яруса. Если ярусы находятся на разных инстансах, запись в ярус направляют на инстансы с его дисками (см. «Классы хранения S3 и ярусы»).

Проверка узла

Для проверки балансировщик использует эндпоинт /-/ready, который не требует подписи:

curl -sf --cacert /etc/s3r/ca.pem https://node1.example.net:8443/-/ready && echo ready
Эндпоинт Что подтверждает
/-/ready ответ 200 означает, что кластер прошёл начальное формирование, а инстанс загрузил свои группы размещения
/-/health только работу слушателя S3

Узел, который не отвечает на проверку, балансировщик выводит из обслуживания, а данные остаются доступны через остальные узлы.

Состояние отдельных дисков на ответ /-/ready не влияет: вышедший из строя диск не выводит из балансировки инстанс, который ещё обслуживает запросы. За дисками следят метрики и оповещения (см. Наблюдение за кластером).

Медленные клиенты

Перед S3R нужен обратный прокси, если клиентам нельзя доверять

S3R не ограничивает клиента, который медленно передаёт или принимает данные. S3R сам завершает TLS и может принимать запросы напрямую, но защиты от медленных клиентов не имеет: несколько медленных читателей занимают память api_memory, и остальные запросы получают ответ 503 SlowDown.

Настройка обратного прокси

Медленных клиентов ограничивает обратный прокси перед S3R. В прокси задают:

Что задать Параметр nginx
таймаут получения заголовков запроса client_header_timeout
таймаут между двумя частями тела запроса client_body_timeout
таймаут между двумя частями ответа, отправляемыми клиенту send_timeout
буферизацию ответа, в том числе на диске прокси proxy_buffering on, proxy_max_temp_file_size
таймаут простоя соединения между запросами keepalive_timeout

При буферизации S3R передаёт тело ответа прокси со своей скоростью и освобождает память, не дожидаясь медленного клиента.

Почему S3R не ограничивает клиента сам

Предельное время запроса (read_timeout_s, write_timeout_s, catalog_timeout_s) не учитывает время, пока S3R ждёт клиента: приём тела объекта и отправку тела ответа. Клиент, который передаёт или читает хотя бы один байт за каждый интервал простоя, не простаивает и удерживает соединение сколь угодно долго.

Запрос GetObject отдаёт тело по мере чтения полос и резервирует память api_memory:

  • под четыре полосы: две читаются заранее, одна уходит клиенту, а ещё одна ждёт отправки;
  • для сжатого объекта с полосой меньше 1 МиБ — под четыре участка по 1 МиБ;
  • для следующей части с более крупными полосами резерв увеличивается.

Резерв освобождается, когда клиент принял тело ответа. Несколько медленных читателей занимают эту память, и остальные запросы получают ответ 503 SlowDown по истечении своего предельного времени.

Обрыв тела ответа

Если полосу не удалось прочитать после того, как заголовки ответа отправлены, S3R закрывает соединение и клиент получает меньше байт, чем указано в Content-Length.

  • Клиент должен сверять длину полученного тела с Content-Length, как это делают AWS SDK.
  • Обрыв учитывается в метрике s3r_get_bodies_cut_total.
  • Журнал инстанса получает запись GetObject cut short с идентификатором запроса.

Медленное чтение обрывается так же, если во время чтения объект удалили, перезаписали или перенесли на другой ярус: блоки, освобождённые объектом, по истечении refill_after_s занимают новые записи, и S3R не отдаёт чужие данные.