Ответ
Для анализа производительности HTTP-запросов используется комбинация логирования, метрик и профилирования.
1. Идентификация с помощью Middleware
Самый простой способ — написать middleware
(промежуточное ПО), которое измеряет время выполнения каждого запроса и логирует информацию о медленных.
func LoggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// Создаем обертку для ResponseWriter, чтобы перехватить статус код
rw := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
next.ServeHTTP(rw, r)
duration := time.Since(start)
// Логируем, если запрос выполнялся дольше заданного порога
if duration > 500*time.Millisecond {
log.Printf(
"SLOW REQUEST: method=%s path=%s duration=%v status=%d",
r.Method,
r.URL.Path,
duration,
rw.statusCode,
)
}
})
}
// responseWriter - обертка для http.ResponseWriter для захвата статус кода
type responseWriter struct {
http.ResponseWriter
statusCode int
}
func (rw *responseWriter) WriteHeader(code int) {
rw.statusCode = code
rw.ResponseWriter.WriteHeader(code)
}
2. Глубокий анализ причин
Когда медленный запрос найден, нужно понять, почему он медленный. Для этого используются:
Профилирование (
pprof
): Позволяет понять, на что тратятся ресурсы CPU и памяти во время выполнения запроса. Можно обернуть обработчик вpprof.Do
для сбора профиля только для конкретного запроса.Распределенная трассировка (OpenTelemetry, Jaeger): Это лучший инструмент для анализа в микросервисах. Трассировка разбивает запрос на логические части (спаны), например:
HTTP-запрос
->SQL-запрос к users
->SQL-запрос к orders
->gRPC-вызов
. Вы сразу увидите, какой из спанов занял больше всего времени.Метрики (Prometheus): Собирайте агрегированные данные о времени ответа (например, гистограммы или перцентили p95, p99) для каждого эндпоинта. Это помогает отслеживать общую производительность системы и выявлять деградацию после очередного релиза.
Что обычно вызывает медленные запросы?
- Неэффективные запросы к базе данных: Отсутствие индексов, N+1 проблема.
- Долгие вызовы внешних API: Сетевые задержки или медленная работа стороннего сервиса.
- Сложные вычисления: Операции, интенсивно использующие CPU.
- Большой объем данных: Обработка или передача больших JSON/XML/файлов.