Post

Изоляция данных и Feign: архитектура без сквозных связей

Изоляция данных и Feign: архитектура без сквозных связей

В микросервисной архитектуре важнейшим принципом является изоляция данных. Каждый сервис должен быть независимым и автономным: он владеет своей базой данных, управляет своим доменом и не зависит от внутренних деталей других сервисов — ни на уровне кода, ни на уровне БД.

Но как тогда один сервис может узнать что-то о другом? Ответ — через внешний API. И в мире Spring Boot для этого удобно использовать FeignClient.

Почему нельзя связывать микросервисы через JPA

Рассмотрим пример. У нас есть два сервиса:

  • courses-service — управляет курсами и уроками.
  • content-service — отвечает за хранение медиафайлов, например видео-лекций.

В Lesson из courses-service может быть ссылка на контент. Но мы не должны делать это так:

1
2
3
@OneToOne
@JoinColumn(name = "content_item_id")
private ContentItem contentItem;

Это создает сквозную зависимость по JPA:

  • courses-service становится зависим от content-service;
  • нельзя запустить сервис без наличия структуры чужой БД;
  • нарушается граница между доменами;

Как правильно

Вместо этого мы просто храним внешний идентификатор:

1
private UUID contentItemId;

И при необходимости получаем информацию о контенте через Feign:

1
2
3
4
5
6
@FeignClient(name = "content-service")
public interface ContentClient {

    @GetMapping("/api/content/{id}")
    ContentItemDTO getById(@PathVariable UUID id);
}

Таким образом:

  • база courses-service остается чистой и независимой;
  • никаких внешних JOIN;
  • взаимодействие идет через стабильный API.

Каждый сервис — отдельный мир

Это касается не только контента. Например, profiles-service управляет пользователями, courses-service может ссылаться на profileId, но не должен знать, как устроена таблица профилей.

Если нужно получить данные профиля — используем ProfileClient с Feign:

1
2
3
4
5
6
@FeignClient(name = "profiles-service")
public interface ProfileClient {

    @GetMapping("/api/profiles/{id}")
    ProfileDTO getProfile(@PathVariable UUID id);
}

Принципы слабой связанности

ПринципПочему это важно
У каждого сервиса — своя БДНезависимость, масштабируемость
Только DTO между сервисамиЧеткие границы, простота изменений
JPA-связи только внутри сервисаКонтроль и модульность
REST/Feign между сервисамиГибкость, устойчивость

Статьи серии

This post is licensed under CC BY 4.0 by the author.