한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

Анатомия игровых лагов › L9 Процесс игрового сервера

Исчерпание пула потоков Thread pool starvation

ID причины sp-threadpool · Основной ответственный Команда разработки · Разработка сервера

Открыть карточку в основной версии с иллюстрациями и экспериментами →

Если все рабочие потоки заняты медленными задачами, новые запросы ждут неопределённо долго.

Почему Рабочие потоки заняты ожиданием ответа внешних API или БД → Следствие Для новых запросов не остаётся свободных потоков → На экране Бесконечная загрузка в отдельных функциях, например при входе или в магазине

Симптомы
Ошибка входа / бесконечная загрузка, Задержка ввода, Фриз
Факторы
Остановка
У кого
Только одна функция, Весь сервер
Когда
При наплыве игроков, Сразу после входа или техработ
Ответственные
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Поставить таймауты на медленные вызовы, разделить пулы потоков по функциям, перейти на асинхронные вызовы.
На графике
Упор в лимит (плато) · число потоков и длина очереди пула потоков, время обработки запросов
Где смотреть
Для .NET смотреть в dotnet-counters monitor число потоков пула и длину очереди (начиная с .NET 9 dotnet.thread_pool.thread.count и dotnet.thread_pool.queue.length, в 8 и ниже ThreadPool Thread Count и ThreadPool Queue Length) и через dotnet-stack проверить, где ждут рабочие потоки. Для JVM и нативных серверов то же самое проверяют по дампу потоков
Подтверждает
Загрузка CPU намного ниже 100%, а число потоков медленно, но постоянно растёт или держится на пределе, очередь копится, и большинство рабочих потоков ждут ответа на один и тот же внешний вызов (БД, HTTP)
Опровергает
Если очередь пуста, а запросы всё равно обрабатываются медленно, тормозит сам вызываемый сервис: дело в каскадном отказе или зависимости от внешних сервисов
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если приём пакетов и игровая логика делят один пул рабочих потоков, то, как только несколько медленных задач займут все потоки, обработка пакетов на всём сервере остановится.
Реальные инциденты
Riot Games 2021: Сбой League of Legends EUW на 5 часов: одна второстепенная БД остановила весь сервер

Источники

  1. Debug ThreadPool Starvation Microsoft
    Если в пуле не осталось свободных потоков и новые задачи ждут, ответы замедляются. Причина в блокирующем коде, который занимает потоки. Признак исчерпания в dotnet-counters: CPU намного ниже 100%, а dotnet.thread_pool.thread.count медленно, но постоянно растёт (часто велик и dotnet.thread_pool.queue.length). Где ждут потоки, проверяют через dotnet-stack
  2. Avoiding insurmountable queue backlogs AWS
    Число одновременно обрабатываемых запросов = интенсивность поступления × задержка (закон Литтла). При 100 запросах в секунду рост задержки со 100 ms до 10 с увеличивает нужное число потоков с 10 до 1 000, и пул исчерпывается
  3. Bulkhead Pattern Microsoft Azure
    Если для каждого вызываемого сервиса держать отдельный пул соединений и потоков, сбой одного сервиса блокирует только его пул
  4. .NET runtime metrics .NET
    dotnet.thread_pool.thread.count (число потоков пула) и dotnet.thread_pool.queue.length (число ожидающих задач) доступны начиная с .NET 9
  5. Well-known EventCounters in .NET Microsoft
    ThreadPool Thread Count (threadpool-thread-count) и ThreadPool Queue Length (threadpool-queue-length) в .NET 8 и ниже

Смотрите также

Тот же слой: L9 Процесс игрового сервера

Причины с тем же симптомом (Ошибка входа / бесконечная загрузка) на других слоях

Карточка в основной версии с иллюстрациями и экспериментами