Перейти к основному содержимому

Чтобы получить чистое содержимое этой страницы в формате Markdown, добавьте .md к этому URL. Полный индекс документации см. на https://docs.nvidia.com/dynamo/llms.txt. Полное содержимое, включая справочник API и примеры SDK, см. на https://docs.nvidia.com/dynamo/llms-full.txt.

Корректное завершение работы

В этом документе описано, как компоненты Dynamo обрабатывают сигналы завершения работы, чтобы текущие запросы успешно завершались, а ресурсы корректно освобождались.

Обзор​

Корректное завершение работы в Dynamo обеспечивает следующее:

  1. Маршрутизация быстро останавливается - конечные точки сначала снимаются с регистрации в discovery
  2. Текущие запросы могут завершиться - рабочие процессы продолжают обслуживать запросы в течение короткого льготного периода
  3. Конечные точки осушаются - после льготного периода конечные точки становятся недействительными и, при необходимости, ожидают завершения текущей работы
  4. Ресурсы освобождаются - движки, соединения и временные файлы освобождаются
  5. Pods перезапускаются корректно - коды выхода сигнализируют Kubernetes о правильном поведении при перезапуске

Обработка сигналов​

Все компоненты Dynamo обрабатывают сигналы Unix для корректного завершения работы:

СигналТриггерПоведение
SIGTERMЗавершение pod в KubernetesЗапускается корректное завершение работы
SIGINTCtrl+C / ручное прерываниеЗапускается корректное завершение работы

Реализация​

Каждый компонент регистрирует обработчики сигналов при запуске:

def signal_handler():
asyncio.create_task(graceful_shutdown(runtime, endpoints))

for sig in (signal.SIGTERM, signal.SIGINT):
loop.add_signal_handler(sig, signal_handler)

Функция graceful_shutdown():

  1. Записывает сигнал завершения работы в журнал
  2. Снимает все конечные точки с регистрации в discovery
  3. Ожидает настраиваемый льготный период (DYN_GRACEFUL_SHUTDOWN_GRACE_PERIOD_SECS, по умолчанию 5 с)
  4. Вызывает runtime.shutdown(), чтобы сделать конечные точки недействительными и прекратить прием новых запросов
  5. Ожидает текущие запросы (на основе graceful_shutdown для каждой конечной точки)
  6. Возвращает управление, чтобы можно было продолжить очистку

Осушение конечных точек​

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

Конфигурация​

При регистрации конечной точки параметр graceful_shutdown управляет поведением при осушении:

generate_endpoint.serve_endpoint(
handler.generate,
graceful_shutdown=True, # Wait for all requests to finish
metrics_labels=[("model", model_name)],
health_check_payload=health_check_payload,
)
graceful_shutdownПоведение
TrueОжидать завершения всех текущих запросов перед возвратом
FalseВернуться немедленно, не ожидая запросы

Поведение отдельных компонентов​

КомпонентПоведение по умолчаниюОбоснование
FrontendН/Д (HTTP server)HTTP server самостоятельно обрабатывает свое завершение работы
Prefill Workersgraceful_shutdown=TrueОперации prefill должны завершиться, чтобы избежать напрасных вычислений
Decode Workersgraceful_shutdown=TrueОперации decode должны завершиться, чтобы избежать напрасных вычислений
Routergraceful_shutdown=TrueГарантирует завершение решений по маршрутизации

Интеграция с миграцией​

Backend workers всегда используют graceful_shutdown=True, то есть ожидают завершения текущих запросов до остановки движка. Миграция запросов настраивается на уровне frontend через --migration-limit:

  • Когда миграция включена на frontend, отключенные потоки от отказавших workers автоматически повторяются на исправных workers
  • Workers не должны знать о конфигурации миграции - они просто завершают свою работу или сигнализируют о незавершенных потоках
  • Подробнее о работе миграции см. в разделе Архитектура миграции запросов

Очистка ресурсов​

После осушения конечных точек компоненты очищают свои ресурсы в блоках finally:

Очистка vLLM Worker​

finally:
logger.debug("Cleaning up worker")
handler.cleanup()

Метод cleanup() обработчика:

  • Удаляет временные каталоги (адаптеры LoRA и т. д.)
  • Освобождает ресурсы движка

Очистка SGLang Worker​

def cleanup(self) -> None:
# Cancel pending consume tasks
for task in self._consume_tasks:
if not task.done():
task.cancel()
self._consume_tasks.clear()

# Shutdown engine
self.engine.shutdown()

Очистка TensorRT-LLM Worker​

async def cleanup(self):
if self._llm:
try:
self._llm.shutdown()
except Exception as e:
logging.error(f"Error during cleanup: {e}")
finally:
self._llm = None

Завершение работы, инициированное ошибкой​

Workers могут инициировать корректное завершение работы при возникновении фатальных ошибок:

Мониторинг работоспособности движка (vLLM)​

VllmEngineMonitor непрерывно проверяет работоспособность движка:

async def _check_engine_health(self):
while True:
try:
await self.engine_client.check_health()
await asyncio.sleep(HEALTH_CHECK_INTERVAL) # 2 seconds
except EngineDeadError as e:
logger.error(f"Health check failed: {e}")
self._shutdown_engine()
self.runtime.shutdown()
os._exit(1)

Конфигурация:

  • HEALTH_CHECK_INTERVAL: 2 секунды между проверками
  • ENGINE_SHUTDOWN_TIMEOUT: не более 30 секунд на завершение работы движка

Обработка фатальных ошибок (TensorRT-LLM)​

async def _initiate_shutdown(self, error: Exception):
logging.warning(f"Initiating graceful shutdown due to: {error}")

try:
if self.runtime:
self.runtime.shutdown()
if self.engine:
await self.engine.cleanup()
except Exception as cleanup_error:
logging.error(f"Error during graceful shutdown: {cleanup_error}")
finally:
logging.critical("Forcing process exit for restart")
os._exit(1)

Интеграция с Kubernetes​

Процесс завершения pod​

  1. Kubernetes отправляет SIGTERM в pod
  2. Dynamo инициирует корректное завершение работы
  3. У pod есть terminationGracePeriodSeconds на завершение (по умолчанию 30 с)
  4. Если pod не завершился, Kubernetes отправляет SIGKILL

Рекомендуемая конфигурация​

Для production-развертываний настройте достаточный льготный период завершения:

apiVersion: nvidia.com/v1alpha1
kind: DynamoGraphDeployment
spec:
services:
VllmWorker:
extraPodSpec:
terminationGracePeriodSeconds: 60 # Allow time for request draining

Интеграция с проверками работоспособности​

Kubernetes использует health endpoints, чтобы определить готовность pod:

  • Во время завершения работы: конечные точки становятся недоступными
  • Readiness probe fails: трафик перестает направляться в pod
  • Graceful draining: существующие запросы завершаются

Рекомендации​

1. Задавайте подходящие льготные периоды​

Согласуйте terminationGracePeriodSeconds с ожидаемым временем завершения запросов:

  • Короткие запросы (< 10 с): льготный период 30 с
  • Долгая генерация (> 30 с): льготный период 120 с и больше

2. Включите миграцию запросов​

Включите миграцию на frontend, чтобы запросы могли восстанавливаться при завершении работы workers:

python3 -m dynamo.frontend ... --migration-limit 3 # Allow up to 3 migration attempts

Это позволяет frontend автоматически повторять отключенные потоки на исправных workers.

3. Отслеживайте метрики завершения работы​

Отслеживайте поведение при завершении работы по журналам:

INFO Received shutdown signal, shutting down DistributedRuntime
INFO DistributedRuntime shutdown complete
DEBUG Cleaning up worker

4. Обрабатывайте ошибки очистки​

Убедитесь, что методы очистки корректно обрабатывают ошибки:

def cleanup(self):
for resource in self.resources:
try:
resource.cleanup()
except Exception as e:
logger.warning(f"Cleanup failed: {e}")
# Continue with other resources

Связанная документация​