← Назад к вопросам

Как понять, что запрос тормозит?

2.7 Senior🔥 81 комментариев
#Операционные системы и Linux

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Анализ производительности HTTP-запросов в Go

Понимание того, что запрос "тормозит", требует системного подхода к мониторингу и диагностике. Вот ключевые методы и инструменты:

1. Мониторинг метрик времени ответа

Установите пороговые значения для latency (задержки) и отслеживайте их через метрики:

import (
    "net/http"
    "time"
    "github.com/prometheus/client_golang/prometheus"
)

var requestDuration = prometheus.NewHistogramVec(
    prometheus.HistogramOpts{
        Name:    "http_request_duration_seconds",
        Help:    "Duration of HTTP requests",
        Buckets: []float64{0.1, 0.5, di.1, 2.0, 5.0},
    },
    []string{"path", "method"},
)

func middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        duration := time.Since(start).Seconds()
        
        // Если запрос длится > 1 секунды - потенциальная проблема
        if duration > 1.0 {
            log.Printf("SLOW REQUEST: %s %s took %.2fs", 
                r.Method, r.URL.Path, duration)
        }
        
        requestDuration.WithLabelValues(r.URL.Path, r.Method).Observe(duration)
    })
}

2. Инструменты профилирования

Используйте встроенные инструменты Go для pprof:

# 1. Добавьте импорт pprof
import _ "net/http/pprof"

# 2. Запустите сервер отладки
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=10

# 3. Анализируйте flamegraph для CPU
go tool pprof -http=:8080 profile.out

3. Трассировка (Tracing)

Для распределенных систем используйте OpenTelemetry:

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/trace"
)

func handleRequest(ctx context.Context) {
    tracer := otel.Tracer("myservice")
    ctx, span := tracer.Start(ctx, "slow-operation")
    defer span.End()
    
    // Если span длится слишком долго, это видно в Jaeger/ tempo
    time.Sleep(2 * time.Second) // Симуляция медленной операции
}

4. Анализ логов с временными метками

Структурированное логирование с context deadline:

func handlerWithTimeout(w http.ResponseWriter, r *http.Request) {
    ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
    defer cancel()
    
    done := make(chan bool)
    go func() {
        // Долгая операция
        time.Sleep(4 * time.Second)
        done <- true
    }()
    
    select {
    case <-ctx.Done():
        log.Printf("REQUEST TIMEOUT: %s - превышен лимит 3 секунды", r.URL.Path)
        http.Error(w, "Timeout", http.StatusGatewayTimeout)
    case <-done:
        w.Write([]byte("OK"))
    }
}

5. Практические индикаторы "тормозов"

Ключевые признаки медленных запросов:

  • Перцентили P95/P99 значительно выше среднего
  • Рост ошибок типа context.DeadlineExceeded
  • Увеличение queue time в балансировщиках нагрузки
  • Ступенчатый рост response time при увеличении нагрузки
  • Разница между server-side и client-side timing

6. Проактивные проверки

Реализуйте health checks и canary deployments:

// Health check с проверкой зависимостей
func healthHandler(w http.ResponseWriter, r *http.Request) {
    checks := map[string]func() error{
        "database": checkDatabaseLatency,
        "cache":    checkRedisPing,
        "external_api": checkExternalService,
    }
    
    for name, check := range checks {
        if err := check(); err != nil {
            log.Printf("HEALTH CHECK FAILED: %s - %v", name, err)
            http.Error(w, "Service degraded", http.StatusServiceUnavailable)
            return
        }
    }
}

7. Инструменты мониторинга

Настройте алертинг в системах:

  • Prometheus + AlertManager для перцентилей
  • Grafana dashboards с историческими данными
  • APM системы (DataDog, NewRelic) для автоинструментации

Рекомендации по пороговым значениям

  • Критично: > 3 секунд для API
  • Предупреждение: > 1 секунды для внутренних сервисов
  • Цели SLA: P95 < 500ms для пользовательских endpoints

Важно: "Тормозит" - понятие относительное. Определите бизнес.требования (SLA/SLO) и настройте мониторинг соответственно. Медленный запрос в 2 секунды может быть нормой для отчетного сервиса, но катастрофой для платежного шлюза.

Используйте комбинацию метрик + трассировка + логирование для триангуляции проблем. Часто "тормоза" вызваны не кодом приложения, а сетевыми задержками, блокирующими I/O операциями или конкурентным доступом к ресурсам.