Какой сервер нужен API-шлюзу: ресурсы, параллельность и трафик
Отделите пересылку API от локального инференса. Оцените запросы в системе, память, соединения и трафик, затем проверьте нагрузку с имитатором upstream.
Шлюзу, который только пересылает запросы удалённому API, обычно не нужен GPU ради самого факта работы с ИИ. Если на машине выполняется инференс, ресурсы для модели, контекста и параллельных запросов нужно рассчитывать отдельно. Сначала установите эту границу, а затем выбирайте сервер — вместо обещания «столько-то пользователей на нескольких ядрах».
Это инструкция по оценке ёмкости и проверке нагрузки, а не рекомендация облачного тарифа. Все числа ниже условные: они не являются результатами испытания конкретного сервиса или сервера.
1. Определите, где выполняется модель
| Развёртывание | Что делает эта машина | Что проверять при выборе ресурсов |
|---|---|---|
| Шлюз обращается к удалённому API | HTTPS, авторизация, маршрутизация, пересылка, учёт и логи | CPU, память, соединения, базу данных и сеть |
| Шлюз и локальная модель на одной машине | Всё перечисленное плюс загрузка модели и инференс | Требования среды исполнения, RAM или VRAM, контекст и параллельность |
| Шлюз, база и модель разделены | Каждый компонент работает отдельно и общается по сети | Ёмкость и соединения каждого слоя, а не только шлюза |
Пересылка сама по себе не требует GPU. Но локальные эмбеддинги, переранжирование, обработка изображений или другой инференс уже выходят за рамки «только пересылки». Возможность инференса на CPU и объём видеопамяти зависят от модели и среды исполнения: GPU не является безусловным требованием для любой локальной модели.
Официальный FAQ Ollama указывает, что параллельные запросы и длина контекста влияют на потребность в памяти. Это расходы слоя инференса; память процесса шлюза не заменяет их оценку.[1]
2. Переведите число пользователей в нагрузку запросов
Запишите четыре величины: запросы в секунду на входе, среднее время от входа до завершения запроса, байты запроса и ответа, число одновременно незавершённых запросов. Число пользователей не равно нагрузке: одно фоновое задание может обращаться постоянно, а множество зарегистрированных пользователей — бездействовать.
В устойчивом интервале наблюдения, когда очередь не растёт непрерывно, среднее число незавершённых запросов можно оценить так:
Среднее число запросов в системе ≈ запросы в секунду × среднее время пребывания в секундах.
При условных 2 запросах в секунду и средней длительности 30 секунд это около 60 запросов. Если вышестоящий сервис замедлится до 60 секунд, а вход останется прежним, в новом устойчивом режиме получится около 120. Это не максимальная параллельность и не гарантия ёмкости: всплески, повторы и длинный хвост нужно изучать отдельно. Если очередь продолжает расти, интервал нельзя считать устойчивым.
Потоковый запрос считается завершённым после окончания потока или отмены, а не после первого токена. Быстрый первый ответ может сопровождаться долгим удержанием соединения. Не подставляйте p95 задержки в формулу для средних значений, называя результат точной «p95 параллельности».
3. Ищите ограничение отдельно по четырём ресурсам
CPU: учитывайте реальную работу шлюза. TLS, преобразование JSON, сжатие, авторизация и обработка логов расходуют CPU. Асинхронное ожидание upstream не означает непрерывной загрузки процессора. Но низкая загрузка CPU не доказывает запас ёмкости: раньше могут закончиться соединения, память или ресурсы базы.
Память: отделите базовое потребление от прироста на запрос. Сначала измерьте состояние без нагрузки, затем повышайте параллельность ступенями при одинаковом размере запроса и режиме ответа. Записывайте фактическое использование процесса или контейнера. Накопленный объём выделений не равен текущей резидентной памяти; не смешивайте разные метрики между опытами.
Допустим, базовое потребление шлюза — 100 MiB, а в некотором контролируемом диапазоне каждый незавершённый запрос добавляет около 0,35 MiB. При 60 запросах оценка равна 121 MiB, при 120 — 142 MiB. Это лишь линейное приближение для данного диапазона, без ОС, базы, других служб и запаса. Оно не означает, что нужно покупать сервер со 142 MiB памяти. Большие запросы, сбор полного ответа, копии для повторов или запись в базу могут нарушить линейность.
Соединения и файловые дескрипторы: одному запросу не всегда соответствует одно соединение. В простом HTTP/1.1-прокси без повторного использования активный запрос может занимать соединение клиент–прокси и соединение прокси–upstream. В NGINX worker_connections учитывает и соединения с вышестоящими серверами, а фактический предел ограничен числом открытых файлов.[2] Мультиплексирование HTTP/2, пулы и дополнительные слои меняют соотношение. Значение настройки нельзя напрямую считать числом обслуживаемых пользователей.
Сеть и диск: считайте байты и срок хранения. Пусть тело запроса занимает 100 KiB, ответ — 20 KiB, частота — 2 запроса в секунду. Если обе пересылки проходят через сетевой интерфейс этой машины, исходящие прикладные данные составят примерно 120 × 1024 × 2 = 245 760 байт/с, или 1,97 Мбит/с. Будет и соответствующий входящий трафик. Заголовки HTTP, TLS, повторы и другие службы не учтены. Направление тарификации и ограничения полосы уточняйте у облачного провайдера. Здесь KiB равен 1024 байтам, а Мбит/с используется в десятичном смысле.
Занятое логами и базой место зависит от состава записей и срока хранения. Не записывайте полные запросы, ответы и ключи только ради нагрузочного теста.
4. Начните со ступенчатой проверки с локальным имитатором upstream
Необязательно сразу отправлять множество платных запросов модели. В контролируемой тестовой среде имитатор upstream может возвращать фиктивные данные заданного размера с заданными длительностью, интервалом частей, ошибками и обрывами. Клиент нагрузки также должен быть под вашим контролем; не используйте сторонний сервис как произвольную цель для нагрузочного теста.
Для каждой ступени заранее задайте предел запросов, длительность и условия остановки:
- Снимите базовые показатели шлюза, базы и ОС без нагрузки; проверьте ограничения процессов и соединений.
- Начните с небольшой параллельности и повышайте её ступенями. Уточните, ограничивает инструмент число одновременных запросов или интенсивность поступления: это разные режимы нагрузки.
- Проверьте пересылку маленьких запросов, затем отдельно увеличивайте размер, длительность и меняйте потоковые части. Не изменяйте всё сразу.
- Записывайте фактические интенсивности входа и завершения, среднее время и длинный хвост, незавершённые запросы, очередь, память, CPU, соединения, задержку базы и ошибки.
- Проверьте освобождение ресурсов при отмене клиентом, медленном чтении и обрыве upstream. После прекращения поступления запросов наблюдайте уменьшение очереди и числа активных запросов.
- При постоянно растущей очереди, росте памяти, исчерпании соединений или неприемлемых ошибках прекратите увеличение нагрузки и сохраните данные ступени.
При включённой буферизации NGINX хранит ответ в буферах памяти, а часть, которая не помещается, при соответствующей конфигурации может попасть во временный файл. Отключение буферизации меняет пересылку, но не означает, что всё приложение перестаёт использовать память для буферов.[3] Конфигурация теста должна соответствовать планируемой рабочей конфигурации.
Имитатор проверяет только локальный тракт, а не доступность реального upstream, квоту аккаунта или скорость модели. Расчётные примеры этой статьи проверены локальной арифметикой и дискретной имитацией запросов. Облачные серверы не сравнивались, реальный платный API нагрузкой не проверялся.
5. Выберите слой для улучшения по наблюдениям
| Наблюдение | Что проверить сначала | Какой вывод преждевременен |
|---|---|---|
| CPU свободен, очередь растёт | Предел параллельности приложения, время upstream, пул базы и соединения | Что дополнительные ядра обязательно помогут |
| Память растёт с числом длинных запросов | Буферы, копии истории, медленных клиентов и очистку после отмены | Что достаточно теста только коротких запросов |
| Ошибки соединений при свободной памяти | Лимиты прокси, файловые дескрипторы и пулы | Что предел можно увеличивать без измерений |
| 429 возвращает только реальный upstream | Ограничения аккаунта, модели или канала | Что локальное обновление повысит внешнюю квоту |
| Поток обрывается после похожего интервала тишины | Тайм-ауты чтения, heartbeat и буферизацию всех слоёв | Что достаточно смотреть общую длительность |
Например, proxy_read_timeout в NGINX ограничивает промежуток между последовательными чтениями, а не общую длительность ответа.[3] Увеличение тайм-аута может дольше удерживать незавершённые запросы. После этого пересмотрите ёмкость, а не ограничивайтесь изменением одного числа.
Добавляйте CPU, память, полосу или отделяйте базу и инференс, когда измерения показывают локальное ограничение. Оставляйте запас для колебаний, но универсального процента запаса и правила «столько-то запросов на ядро» для всех шлюзов нет.
Дополнительно: 429 и управление параллельностью, обрывы потоковых ответов, проверка перед запуском в эксплуатацию. Эти инструкции рассматривают внешние лимиты, протокол и эксплуатационные границы; они не заменяют проверку ёмкости вашей машины.
Официальные источники и границы применимости
- [1] Ollama FAQ: параллельные запросы и память модели. Источник поясняет зависимость локального инференса от параллельности; его настройки нельзя автоматически переносить на другие среды.
- [2] NGINX Core: worker_connections и worker_rlimit_nofile.
- [3] NGINX Proxy: буферизация и тайм-аут чтения.
Источники проверены 10 октября 2026 года. Другая реализация шлюза, ОС, протокол или топология требуют повторных измерений.