Настав час зануритися в практичну магію Spring Boot, Sleuth і Zipkin, щоб трасування стало нашим найкращим другом в мікросервісній археології.
Огляд Spring Cloud Sleuth
Spring Cloud Sleuth — це бібліотека, інтегрована в Spring Boot, яка додає розподілене трасування в мікросервіси, ніби ви дали своїм сервісам можливість лишати сліди в кожному запиті.
Вона автоматично додає ідентифікатори трасувань (traceId) і спанів (spanId) в ваші логи. Таким чином ви зможете зрозуміти, як ваш запит подорожує по мікросервісній системі, які сервіси він відвідує, і де саме він затримується.
Як детектив, який аналізує відбитки пальців на місці злочину, Sleuth дозволяє витягувати логи й зв'язувати їх між різними сервісами.
Чому це важливо?
- Логи без контексту – як шматки випадкового пазла. Sleuth додає єдиний
traceId, який зв'язує логи докупи. - Ви можете відстежити «затримки» запитів до конкретного сервісу.
- Зручно використовувати з системами трасування, такими як Zipkin або Jaeger.
Основні можливості Sleuth
- Вбудовані ідентифікатори
traceIdіspanId. - Інтеграція з логуванням.
- Автоматичне відстеження часу виконання запитів.
- Підтримка HTTP, Kafka, RabbitMQ та інших транспортів.
Налаштування Sleuth у Spring Boot
Переходимо до практики! Створимо простий Spring Boot мікросервіс і інтегруємо Sleuth.
Додавання залежності
Для інтеграції Sleuth потрібно додати залежність у ваш pom.xml (або build.gradle, якщо використовуєте Gradle). Крім того ми додамо Zipkin, щоб візуалізувати трасування запитів.
<dependencies>
<!-- Spring Cloud Sleuth -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<!-- Zipkin -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
</dependencies>
Конфігурація
У application.yml додаємо базову конфігурацію для увімкнення трасування і Zipkin.
spring:
application:
name: microservice-a
sleuth:
sampler:
probability: 1.0 # 100% запитів будуть трасуватися
zipkin:
base-url: http://localhost:9411 # URL вашого Zipkin-сервера
Ця конфігурація робить наступне:
- Налаштовує ім'я вашого сервісу як
microservice-a. - Задає
sampler.probability: 1.0, що означає, що всі запити будуть трасуватися (в проді краще зменшити значення). - Вказує URL Zipkin-сервера.
Інтеграція з Zipkin
Zipkin — це система розподіленого трасування, яка збирає і візуалізує дані про запити. Уявіть, що ви споглядаєте за запитом через магічне вікно: бачите, де він був, як довго там затримувався, і куди пішов далі.
Zipkin працює з traceId і spanId, які Sleuth автоматично передає.
- Найпростіший спосіб запустити Zipkin — використати Docker:
docker run -d -p 9411:9411 openzipkin/zipkin - Після запуску Zipkin буде доступний за адресою:
http://localhost:9411.
Демонстрація: Трасування в мікросервісах
Крок 1. Створимо два мікросервіси
Створимо два мікросервіси: Service A та Service B. Service A викликає Service B через REST. Наша ціль — побачити, як запит подорожує між ними.
Головний контролер Service A:
@RestController
@RequestMapping("/service-a")
public class ServiceAController {
private final RestTemplate restTemplate;
public ServiceAController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/call-service-b")
public String callServiceB() {
String response = restTemplate.getForObject("http://localhost:8081/service-b/endpoint", String.class);
return "Response from Service B: " + response;
}
}
Конфігурація для RestTemplate:
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Контролер Service B виглядає так:
@RestController
@RequestMapping("/service-b")
public class ServiceBController {
@GetMapping("/endpoint")
public String endpoint() {
return "Hello from Service B!";
}
}
Крок 2. Підключення Sleuth і Zipkin
Обидва сервіси використовують ті ж залежності Sleuth і Zipkin, що ми налаштували раніше. Також потрібно переконатися, що у них задані різні імена:
Для Service A:
spring:
application:
name: service-a
Для Service B:
spring:
application:
name: service-b
Крок 3. Перевірка трасування
- Запустіть обидва сервіси (на портах 8080 і 8081).
- Спробуйте викликати Service A, щоб ініціювати запит:
curl http://localhost:8080/service-a/call-service-b - Перейдіть в UI Zipkin за адресою
http://localhost:9411.
Ви побачите трасування запиту з двома спанами:
- Перший спан: виклик контролера в Service A.
- Другий спан: виклик Service B з Service A.
Приклад логування зі Sleuth
Коли ви вмикаєте Sleuth, у логи автоматично додаються traceId і spanId.
Приклад лога:
2023-10-25 12:00:00.123 INFO [service-a,traceId=1ab23cd4,spanId=2ef56gh7] Request initiated
2023-10-25 12:00:00.456 INFO [service-b,traceId=1ab23cd4,spanId=3ij89kl0] Processing request
На що звернути увагу
- Самплінг (Sampling): За допомогою
spring.sleuth.sampler.probabilityви можете налаштувати, який відсоток запитів буде трасуватися. Наприклад, для продакшену краще використовувати0.1(10%). - Контекст запитів: Sleuth автоматично передає заголовки трасування, такі як
X-B3-TraceId, між сервісами. Переконайтеся, що ваш код не перезаписує ці заголовки. - Проблеми з трасуванням: Якщо Zipkin не показує дані:
- Перевірте URL Zipkin-сервера в конфігурації.
- Переконайтеся, що Sleuth увімкнений (
spring.sleuth.enabled=true).
Реальне застосування
- У продакшені Sleuth + Zipkin допомагають швидко знаходити «вузькі місця». Наприклад, якщо запит довго обробляється, ви одразу бачите, який сервіс винен.
- Також популярним інструментом є OpenTelemetry, який більш гнучкий, але складніший у налаштуванні.
- Ви можете інтегрувати трасування з логуванням на рівні ELK для повного спостереження.
На цьому етапі ви вже не просто додали Sleuth і Zipkin у свої проекти, а й знаєте, як відслідкувати запити, ніби хижак на полюванні за багами. У наступній лекції ми зануримось у централізоване логування з ELK. Сподіваюся, ваші мікросервіси знову там зустрінуться!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ