Балансировка нагрузки и медленные клиенты¶
Страница для инженера эксплуатации, который ставит перед кластером балансировщик или обратный прокси: на какие узлы направлять запросы, каким эндпоинтом проверять узел и какие таймауты задать, чтобы медленные клиенты не мешали остальным.
Балансировка нагрузки¶
Балансировщик может направлять запросы на любой узел, и привязка клиента к узлу не нужна. Каждый
инстанс с сервисом 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 не отдаёт чужие данные.