
goroutineleak в Go 1.27 выявляет зависшие горутины в продакшене
Что добавил Go 1.27
9 сентября команда Go анонсировала профиль goroutineleak. Он интегрирован в стандартный пакет runtime/pprof и доступен через HTTP‑обработчик net/http/pprof по пути /debug/pprof/goroutineleak. Профиль работает на живом сервисе – не требуется остановка процесса и написание тестов.
Как он определяет утечку
Механизм использует уже существующий в GC анализ достижимости. Сначала отмечаются все горутины, которые сейчас могут выполнять код. Затем обходятся каналы, мьютексы, WaitGroup и условные переменные, доступные этим горутинам. Всё, что остаётся недостижимым, считается навечно заблокированным и попадает в отчёт. Профиль ловит блокировки на отправке/приёме в канал, в select, а также на Mutex, RWMutex, WaitGroup и Cond. Ожидание ввода‑вывода, системные вызовы и пользовательские спин‑локи не считаются утечкой.
Производительность и рекомендации
Памяти под учёт горутин требуется микроскопически мало, а влияние на сборщик мусора почти незаметно. В худшем случае один проход GC может потребовать квадратичную работу — O(n²) — поэтому профиль рекомендуется снимать периодически, например раз в четыре часа, а не включать постоянно.
Пример из блога команды Go
Сервис запускал десять воркеров, а при первой ошибке сразу возвращался, оставляя остальных зависать на отправке в неблокируемый канал. Через несколько минут pprof показал 116 зависших горутин, все они стояли на одной операции ch <- result. Решение оказалось простым: сделать канал буферизованным (make(chan result, len(ws))). После изменения воркеры завершались корректно.
Как начать пользоваться
Обнови тулчейн до Go 1.27 (релиз 19 августа 2026) и пересобери сервис. Если у тебя уже подключён net/http/pprof, новый эндпоинт появится автоматически. Запускай профиль время от времени и проверяй отчёты – они помогут найти скрытые блокировки в коде, где воркеры могут «застрять» из‑за преждевременного завершения читателя.



Комментарии 0