Как диагностировать зависание или узкое место в Go-сервисе?

Ответ

Для диагностики производительности и поиска причин зависания в Go-приложении используются встроенные и сторонние инструменты.

  1. Профилирование с помощью pprof Это стандартный и самый мощный инструмент для анализа производительности. Для его подключения достаточно добавить импорт и запустить HTTP-сервер:

    import (
        _ "net/http/pprof"
        "net/http"
        "log"
    )
    
    go func() {
        // pprof эндпоинты будут доступны на :6060/debug/pprof/
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()

    Основные эндпоинты для анализа:

    • go tool pprof http://.../debug/pprof/profile?seconds=30 — анализирует использование CPU.
    • go tool pprof http://.../debug/pprof/heap — анализирует распределение памяти.
    • http://.../debug/pprof/goroutine?debug=2 — показывает стектрейсы всех активных горутин, что критически важно для поиска зависаний.
  2. Контексты с таймаутами и дедлайнами Использование context.WithTimeout или context.WithDeadline позволяет прервать операцию (например, запрос к базе данных или другому сервису), если она выполняется слишком долго. Это предотвращает каскадные сбои.

    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    
    // Передаем контекст в функцию, которая выполняет долгую операцию
    err := longOperation(ctx)
    if errors.Is(err, context.DeadlineExceeded) {
        log.Println("Операция прервана по таймауту")
    }
  3. Распределенная трассировка В микросервисной архитектуре, когда запрос проходит через несколько сервисов, pprof не всегда помогает. Здесь нужны системы распределенной трассировки, такие как OpenTelemetry (стандарт де-факто) и Jaeger или Zipkin для визуализации. Они позволяют отследить весь путь запроса и найти, какой именно сервис или операция является узким местом.

  4. Метрики Сбор метрик с помощью библиотеки Prometheus и их визуализация в Grafana. Ключевые метрики для отслеживания:

    • Время ответа на запрос (latency), включая перцентили (p95, p99).
    • Количество активных горутин.
    • Использование памяти и CPU.

Краткий итог: для локальной диагностики одного сервиса начните с pprof (особенно с профиля горутин). Для контроля времени выполнения операций используйте context. В распределенных системах внедряйте трассировку и метрики.