Вопрос проверяет понимание распределённой трассировки и важности correlation ID для связывания логов в микросервисной архитектуре.
Correlation ID (или Trace ID) — это уникальный идентификатор, который генерируется при первом входящем запросе в систему и передаётся через все последующие вызовы между микросервисами. Он позволяет объединить логи разных сервисов в единую историю обработки одного запроса.
В монолите все логи пишутся в один файл, и порядок запросов легко восстановить по времени. В микросервисах каждый сервис пишет свои логи независимо. Если запрос проходит через 5 сервисов, а потом возникает ошибка, без correlation ID невозможно понять, какой именно запрос вызвал проблему и как он прошёл через систему.
Correlation ID обычно генерируется на API-шлюзе или первом сервисе, который принимает запрос. Затем он передаётся в HTTP-заголовке (например, X-Correlation-ID) или в метаданных сообщения (например, в RabbitMQ/Kafka). Каждый сервис обязан логировать этот ID вместе с остальными данными.
// Пример на go
package main
import (
"context"
"encoding/json"
"log"
"net/http"
"time"
)
type ProductResponse struct {
ID int `json:"id"`
Name string `json:"name"`
Recommendations []string `json:"recommendations"`
Degraded bool `json:"degraded"`
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/product", productHandler)
log.Println("server started on :8080")
log.Fatal(http.ListenAndServe(":8080", mux))
}
func productHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
product := ProductResponse{
ID: 1,
Name: "Laptop",
}
recs, err := getRecommendations(ctx, product.ID)
if err != nil {
log.Printf("recommendations unavailable: %v", err)
// graceful degradation:
// основной ответ отдаём, но без рекомендаций
product.Recommendations = []string{}
product.Degraded = true
} else {
product.Recommendations = recs
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(product)
}
func getRecommendations(ctx context.Context, productID int) ([]string, error) {
ctx, cancel := context.WithTimeout(ctx, 300*time.Millisecond)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://recommendations-service/recs", nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode >= 500 {
return nil, http.ErrServerClosed
}
var result []string
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
return result, nil
}Быстрая отладка: по correlation ID можно найти все логи, связанные с конкретным запросом.
Мониторинг производительности: можно измерить время прохождения запроса через каждый сервис.
Аудит: легко отследить, какие действия выполнил пользователь.
Вывод: Correlation ID — это обязательный элемент observability в микросервисной архитектуре. Его стоит применять везде, где есть распределённая обработка запросов, чтобы не тратить часы на поиск причины ошибки в логах.