Skip to content

Сетевые квоты и очереди шлюза ​

В каждом процессе API реализован локальный исполнитель бюджета. Для каждой передачи действуют общий допуск, предел активных передач клиента и два ограничения payload-скорости: на всё направление и на клиента. Ключи с одинаковым id делят состояние между всеми репозиториями и соединениями. В standalone бюджет относится к одному процессу. Дополнительный профиль READ_GATEWAYS распределяет фиксированные доли общего download-бюджета через конечные PostgreSQL leases; балансировщик запросов остаётся внешним. Решение: ADR 0008.

Настройка ​

ПеременнаяПо умолчаниюЗначение
ARKVORY_MAX_UPLOADS8Активные изменяющие upload-сценарии, 1..32
ARKVORY_MAX_DOWNLOADS16Активные downloads, 1..256
ARKVORY_MAX_UPLOADS_PER_PRINCIPALmin(4, uploads)Не больше ARKVORY_MAX_UPLOADS
ARKVORY_MAX_DOWNLOADS_PER_PRINCIPALmin(4, maxDownloads)Не больше ARKVORY_MAX_DOWNLOADS
ARKVORY_DOWNLOAD_*см. нижеОчередь скачиваний (ADR 0076)
ARKVORY_UPLOAD_BYTES_PER_SECOND0Общая скорость приёма payload
ARKVORY_DOWNLOAD_BYTES_PER_SECOND0Общая скорость выдачи payload
ARKVORY_UPLOAD_BYTES_PER_SECOND_PER_PRINCIPAL0Приём от одного клиента суммарно
ARKVORY_DOWNLOAD_BYTES_PER_SECOND_PER_PRINCIPAL0Выдача одному клиенту суммарно

Rate задаётся целым числом bytes/s: 0 отключает соответствующий ceiling, иначе допустимы 65 536..1 099 511 627 776. Ошибочная конфигурация отклоняется при старте. Пример ограничения шлюза 64 MiB/s и каждого клиента 16 MiB/s в каждом направлении:

dotenv
ARKVORY_UPLOAD_BYTES_PER_SECOND=67108864
ARKVORY_DOWNLOAD_BYTES_PER_SECOND=67108864
ARKVORY_UPLOAD_BYTES_PER_SECOND_PER_PRINCIPAL=16777216
ARKVORY_DOWNLOAD_BYTES_PER_SECOND_PER_PRINCIPAL=16777216

Это пример, а не рекомендуемая ёмкость вашей сети. Общая полоса загрузки и скачивания независима; если uplink/диск разделяются, выбирайте оба бюджета с учётом суммарной нагрузки и резерва replication/служебного трафика. Изменение конфигурации требует перезапуска. Старые установки без rate variables остаются без ограничения bytes/s; новый default активных передач одного принципала применяется после обновления.

Один ключ не обязан соответствовать одному физическому клиенту: если все CI используют один id, они делят квоту и предел активных операций. Для разных потребителей назначайте разные id; для ротации ключа сохраняйте id, чтобы не удвоить лимит.

Гарантии и границы ​

Лимит общий для всех потоков направления и для всех ключей одного id. Burst каждого включённого bucket — min(floor(rate / 10), 1 MiB), квант до 64 KiB. С момента полного bucket выдача ограничена rate × elapsed + burst. Ожидание не загружает весь файл в память. Подтверждение upload, SHA-256 и durable publication остаются в серверном storage-сценарии.

Full upload и multipart делят upload bucket. Скачивания по ID, пакету и пути файла, включая Range, делят download bucket. HEAD, 304 и отклонённый Range не расходуют byte budget. Metadata/health не ограничиваются байтовой очередью; глобальный предел 128 HTTP-запросов остаётся. Completion/register/cancel используют существующий upload admission, но без расхода сетевых bytes на локальную сборку. Повторно переданные после обрыва байты расходуют квоту повторно.

Admission ждёт до 20 секунд, держит до 64 ожидающих запросов направления и до 8 ожидающих от клиента; перегрузка возвращает 503/Retry-After. Retry-After не фиксирован: это очередь впереди (ждущие плюс сам запрос), делённая на измеренную скорость освобождения мест по последним 256 освобождениям за минуту, плюс до четверти случайно; от 2 секунд до 10 минут, без измерений — один срок ожидания (ADR 0076). Квота bytes может ожидать дольше допуска: действуют AbortSignal, HTTP timeout и предел активных потоков. Подбирайте SDK attemptTimeoutMs под 8 MiB и худшую долю клиента; при множестве конкурентов стандартных 120 секунд может не хватать. Для медленных каналов используйте multipart; full HTTP upload ограничен 30 минутами серверного request timeout.

Очередь скачиваний ​

Скачивание объекта больше ARKVORY_DOWNLOAD_SESSION_MIN_BYTES (16 МиБ) — сессия (ADR 0076): место выдаётся на всё скачивание, а не на диапазон. Ключ сессии — принципал, объект и Arkvory-Download-Id клиента; без него — адрес клиента. Ссылка на скачивание считается отдельным принципалом, а не выпустившим её. Полоса по-прежнему делится BandwidthGovernor.

ПеременнаяПо умолчаниюЗначение
ARKVORY_DOWNLOAD_STRATEGYordered (на шлюзах чтения — shared)ordered, smallest-first или shared (без очереди, допуск на запрос)
ARKVORY_MAX_DOWNLOAD_SESSIONSARKVORY_MAX_DOWNLOADSМеста: одновременные сессии, 1..1024
ARKVORY_MAX_DOWNLOADS_PER_PRINCIPALmin(4, maxDownloads)Доля принципала, пока первым в очереди стоит другой
ARKVORY_DOWNLOAD_RESERVE1 (0 при меньше чем 4 местах)Места только для interactive
ARKVORY_DOWNLOAD_WEIGHTSinteractive=8,release=4,bulk=2,background=1Веса классов; можно указать только меняемые
ARKVORY_DOWNLOAD_SESSION_MIN_BYTES16777216Объекты до этого размера — допуск на запрос, без очереди
ARKVORY_DOWNLOAD_IDLE_SECONDS30Пауза, после которой место освобождается; очередь сохраняется ещё 10 минут
ARKVORY_DOWNLOAD_AGING_MINUTES15Шаг старения на класс, не выше release; 0 — без старения
ARKVORY_DOWNLOAD_PREEMPTtrueВытеснение на границе диапазонов для клиентов протокола очереди
ARKVORY_DOWNLOAD_RANGES_PER_SESSION4Одновременные ответы одной сессии
ARKVORY_DOWNLOAD_QUEUE_LIMIT65536Сессий всего, активных и ждущих
ARKVORY_DOWNLOAD_QUEUE_PER_PRINCIPAL4096Сессий одного принципала
ARKVORY_DOWNLOAD_HOLD_SECONDSARKVORY_TRANSFER_QUEUE_TIMEOUT_MS / 1000Сколько держать запрос клиента вне протокола до его очереди; 0 — отвечать сразу

Значения очереди меняются и без перезапуска: PUT /api/v1/system/downloads/settings с expectedRevision или карточка «Настройки» на странице «Площадки» (в том числе для управляемой площадки, ADR 0077). Сохранённые значения важнее переменных на процессе записи и применяются со следующего решения; длина очереди (ARKVORY_DOWNLOAD_QUEUE_LIMIT, ARKVORY_DOWNLOAD_QUEUE_PER_PRINCIPAL) и ARKVORY_DOWNLOAD_HOLD_SECONDS — только переменными. Шлюзы чтения остаются на окружении.

Ошибочное значение останавливает запуск с именем переменной. Действующие настройки видны в readiness (transfers.downloads.sessions.settings).

Порядок. ordered — классы с весами (stride): свободные места делятся между классами по весам, внутри класса принципалы идут по кругу, у каждого — по очереди прихода. smallest-first — внутри класса сначала меньшие объекты. Каждые ARKVORY_DOWNLOAD_AGING_MINUTES ожидания поднимают сессию на класс, но не выше release: полоса людей остаётся их. Люди (сессия консоли, личный токен) — interactive, сервисные ключи и ссылки — release. Заголовок Arkvory-Download-Class понижает класс; неизвестное значение — 400; применённый класс возвращается в ответе.

Места не простаивают. За отсутствующим клиентом место не держится. Такт планировщика (500 мс) отмечает первых в очереди — вдвое больше, чем свободных мест, считая места сессий, которые закончат в ближайшие 5 секунд. Место берёт тот из них, кто придёт первым; людям доступен резерв, остальным — места вне его. Оценка начала моделирует освобождение мест по остаткам активных сессий при пиковой секундной скорости за минуту: средняя падала бы при простое и растягивала оценки. Retry-After — половина пути до начала, от 2 секунд до 5 минут, с разбросом по сессии; первым в очереди — от секунды. Неявка (не пришёл к сроку, плюс половина и 15 секунд) снимает сессию.

Клиенты протокола и прочие. SDK и arkvoryctl отправляют Arkvory-Download-Id: такой клиент сразу получает 503 busy с причиной download_queued, местом (Arkvory-Queue-Position), оценкой начала (Arkvory-Starts-At, RFC 3339) и Retry-After, ждёт и продолжает. Запрос без id (docker, npm, curl, браузер по ссылке) сервер держит до его очереди до ARKVORY_DOWNLOAD_HOLD_SECONDS, проверяя на каждом такте. Одновременно держится не больше ARKVORY_TRANSFER_QUEUE_LIMIT запросов, остальные получают 503 сразу. Такие инструменты за одним NAT с одним ключом делят одну сессию, не больше ARKVORY_DOWNLOAD_RANGES_PER_SESSION ответов сразу. Без ARKVORY_TRUSTED_PROXIES за обратным прокси все клиенты выглядят одним адресом.

Вытеснение. Если свободных мест нет, первый в очереди — более высокого класса или принципал ниже доли, а активная сессия клиента протокола держит место дольше минуты и выше доли или ниже классом, то на границе диапазонов она получает download_queued и уступает место. Клиент продолжает с того же байта, когда снова дойдёт очередь. Инструменты без id не вытесняются: многие не переживают 503 посреди файла.

Завершение и пауза. Сессия завершена, когда отдан последний байт и все байты объекта, а других ответов нет: чтение конца файла первым (ZIP) сессию не закрывает. Пауза дольше ARKVORY_DOWNLOAD_IDLE_SECONDS освобождает место, но скачивание ещё 10 минут хранит свою очередь и прогресс: вернувшись, оно встаёт на прежнее место.

Талон очереди. Каждый ответ сессии несёт Arkvory-Queue-Ticket — подписанное время прихода скачивания. Клиент возвращает его со следующими запросами; после перезапуска сервера скачивание встаёт на прежнее место. Талон принимается 15 минут после выдачи, а каждый ответ выдаёт свежий с тем же временем прихода. Ключ подписи — в БД (arkvory_download_ticket_key), общий для процессов установки, вне резервной копии. Окна клиента — в SDK (notBefore, notAfter) и arkvoryctl (--not-before, --not-after): клиент не спрашивает раньше и прекращает ожидание, если очередь начнёт позже срока.

Остановка и границы. При drain новые и ждущие сессии получают 503 busy (Retry-After: 2), места больше не раздаются, активные доводятся. Часы планировщика монотонные: сдвиг системного времени не трогает сроки. Порядок очереди — O(n log n) на такт, на 65 536 сессий — десятки миллисекунд (tickMilliseconds в readiness). Очередь принадлежит процессу: после перезапуска клиенты с талоном встают на прежнее место, остальные — заново; шлюзы чтения до общей очереди этапа 4 по умолчанию работают в shared. Состояние — readiness transfers.downloads.sessions и метрики arkvory_download_sessions_active, arkvory_download_sessions_waiting, arkvory_download_queue_oldest_wait_seconds, arkvory_download_session_events_total.

Объекты до ARKVORY_DOWNLOAD_SESSION_MIN_BYTES допускаются на запрос через admission выше (ARKVORY_MAX_DOWNLOADS): несколько диапазонов не должны ждать за многогигабайтными скачиваниями. Одновременно может идти до ARKVORY_MAX_DOWNLOAD_SESSIONS сессий и ARKVORY_MAX_DOWNLOADS коротких запросов; учитывайте это в ARKVORY_MAX_REQUESTS.

Pacing ​

Pacing ограничивает выдачу/чтение payload приложением. TCP/proxy буфер может принять данные заранее; заголовки, TLS overhead и retransmissions не считаются. Для ограничения реального интерфейса и защиты от входящего flood нужны настройки сети/ОС. Reverse proxy должен передавать request/response потоково: полная буферизация на proxy скрывает backpressure от клиента. Приложение не меняет чужие proxy-настройки.

Состояние процесса сбрасывается при рестарте. Отмена после выдачи разрешения не возвращает bytes в bucket. Когда клиент читает медленнее лимита, свободная полоса доступна другим. Чередование по принципалам относится к готовым квантам; это не гарантированная минимальная доля или приоритетный scheduler. Потеря standalone DB ownership прерывает выдачу новых квантов; сервис требуется перезапустить.

Диагностика ​

Авторизованный GET /health/ready содержит transfers.uploads и transfers.downloads:

  • admission.active, waiting, capacity, perPrincipalCapacity;
  • admission.rejected — отказы заполненной очереди, timedOut — истёкшее ожидание, cancelled — отменённые ожидающие запросы;
  • bandwidth.bytesPerSecond, perPrincipalBytesPerSecond, burstBytes, perPrincipalBurstBytes — параметры, 0 означает отключённый потолок;
  • bandwidth.waiting — ожидающие кванты, grantedBytes — десятичная строка счётчика разрешённых payload bytes.

Агрегаты доступны любому валидному сервисному ключу, как прежний readiness. Нет ID принципалов, путей, токенов и названий файлов. Счётчики относятся к одному процессу и обнуляются при его перезапуске. grantedBytes — разрешения, включая повторы/отменённые операции, а не доставленные или подтверждённые байты.

Проверки ​

Unit tests с виртуальным монотонным временем проверяют математический предел shared/per-principal buckets, burst, чередование, множество соединений, отсутствие обхода через маленькие кванты, отмену, закрытие, bounded queue и backpressure. HTTP/PostgreSQL тесты проверяют одновременные full/multipart uploads, разные ключи одного клиента, независимый клиент, Range и asset content, диагностику, отмену очереди и preClose с активной передачей.

Большой профиль: npm run gate -- large-multipart, отдельная тестовая БД и ≥11 GiB свободного места. Он включает реальные 5 GiB, рестарты API, обрыв download, контроль hash/RSS и квоты 64 MiB/s на шлюз, 48 MiB/s на принципала. Отчёт сохраняется в ignored test-results/large-traffic.json. Межсерверная координация и HA этим тестом не проверяются.

Размер ожидающей очереди и timeout теперь настраиваются через ARKVORY_TRANSFER_QUEUE_LIMIT, ARKVORY_TRANSFER_QUEUE_PER_PRINCIPAL, ARKVORY_TRANSFER_QUEUE_TIMEOUT_MS. Defaults прежние: 64/8/20000. Readiness дополнен waitingCapacity/perPrincipalWaitingCapacity/timeoutMs. Это пределы шлюза, отдельные от клиентской очереди скачиваний.

После допуска upload действует отдельное время ожидания данных отправителя: ARKVORY_UPLOAD_IDLE_TIMEOUT_MS=30000. Оно не учитывает паузы bandwidth governor и backend. ARKVORY_UPLOAD_DEADLINE_MS=1800000 ограничивает всю принятую операцию PUT/complete, включая обработку и публикацию; это не лимит всей multipart-сессии. Оба значения — целые 1..1800000, idle ≤ deadline. До допуска продолжают действовать обычные HTTP/queue ограничения. Решение.

Arkvory · ProAnimaStudio