1 of 67

Автогенерация архитектуры �«as Code»

Руслан Сафин, Бындюсофт

2 of 67

Руслан Сафин

Технический директор и архитектор в Бындюсофт

Автор и преподаватель курса по микросервисной архитектуре в ИТМО

Член программных комитетов CodeFest, TechLeadConf и UWDC

2

3 of 67

Byndyusoft — 12 лет на рынке

Создаём IT-продукты для на заказ. Нам доверяют ключевые сервисы, от которых зависит бизнес.

3

4 of 67

Архитектура As Code

  1. Что это?
  2. Форматы
  3. Примеры
  4. Преимущества

4

5 of 67

ИТ-архитектура

«Фундаментальная организация системы, реализованная в её компонентах, их взаимоотношениях друг с другом и средой и принципах, определяющих её конструкцию и развитие»

​

© стандарт ANSI/IEEE Std 1471-2000

​

​

5

5

5

6 of 67

Архитектура — картинка

6

7 of 67

Картинка

—

  • Версионирование
  • Работа с ветками
  • Синхронизация с исполняемым кодом
  • Возможности интеграции

​

+

  • Наглядность

​

7

8 of 67

Код

+

  • Версионирование
  • Работа с ветками
  • Синхронизация с исполняемым кодом
  • Возможности интеграции

​

—

  • Наглядность

​

8

9 of 67

Код → Картинка

+

  • Наглядность
  • Версионирование
  • Работа с ветками
  • Синхронизация с исполняемым кодом
  • Возможности интеграции

​

9

10 of 67

Инструменты

  • Plantuml
  • Structurizr
  • …

10

11 of 67

12 of 67

Архитектура микросервисов в PlantUML

System_Ext(goods, “Goods Repo")

System_Ext(stock, “Stock")

​

Container(bff, “BFF", "NestJS")

Container(task_repository, “Task Repo", "NestJS”)

​

Rel(bff, goods, "Get products", “API Gateway")

Rel(task_repository, stock, “Send task", $tags="async")

Rel(bff, task_repository, "Get task", “REST")

​

12

12

12

13 of 67

13

14 of 67

Преимущества архитектуры «as code»

  • Унификация
  • Полностью аналогичный работе с кодом процесс:
    • Версионирование
    • Ветки
    • PullRequest’ы
    • Merge
    • …
  • Возможность автоматизации

14

15 of 67

Проблемы �архитектурных схем

0. Их отсутствие😅

  1. Неактуальность
  2. …

​

15

16 of 67

Неактуальность архитектуры

16

17 of 67

Неактуальность архитектуры

17

18 of 67

Архитектуру теперь можно описывать кодом�↓�значит её можно сгенерировать!

18

19 of 67

19

20 of 67

Автогенерация архитектуры

  1. На примере микросервисов
  2. Откуда брать данные?
  3. Результат

20

21 of 67

На примере архитектуры микросервисов

21

21

21

22 of 67

Архитектура микросервисов в PlantUML

System_Ext(goods, “Goods Repo")

System_Ext(stock, “Stock")

​

Container(bff, “BFF", "NestJS")

Container(task_repository, “Task Repo", "NestJS”)

​

Rel(bff, goods, "Get products", “API Gateway")

Rel(task_repository, stock, “Send task", $tags="async")

Rel(bff, task_repository, "Get task", “REST")

​

22

22

22

23 of 67

Откуда брать актуальные зависимости сервисов?

​

— Сложность извлечения данных

— Отсутствие инфраструктурных данных

​

​

Код сервисов

​

+ Первоисточник поведения сервисов

​

23

24 of 67

Откуда брать актуальные зависимости сервисов?

�— Нет «редких» связей

— Сложность симуляции на препроде

— Данные только после появления трафика

​

Service Mesh

�+ Реальный трафик

​

24

25 of 67

Ещё варианты? 🙂

25

26 of 67

26

27 of 67

Откуда брать актуальные зависимости сервисов?

k8s configs

�+ Все связи, включая «редкие»

+ Бóльшая информативность

+ Данные не требуют трафика

​

​

27

28 of 67

Конфиг сервиса

environment:

  GOODS_REPO_BASE_URL:

    default: https://gateway.int.com:443/goods/v1

  TASK_REPO_BASE_URL:

    default: http://tasks-repository:8080

KAFKA_TASKS_BROKERS:

    default: msg-q8s.int.cloud:9092

KAFKA_TASKS_TOPIC:

default: stock-tasks-q8s-v1

28

28

28

29 of 67

Берём данные из конфигов

[

Сервис1 {

[ связь1, связь2 ]

},

Сервис2 {

[ связь1, связь3 ]

},

...

]

29

29

30 of 67

Реализация

30

30

31 of 67

Результат генерации

31

32 of 67

Ручной�plantuml

Сгенери-рованный

33 of 67

Что ещё можно добавить?

Всё, что есть в конфиге и важно отразить на архитектуре ☺

Например:

  • Тип и параметры связей
  • Параметры контейнеров
  • Репликация и автоскейлинг
  • Разделение по хостам и дата-центрам
  • Метрики мониторинга
  • …

​

33

33

33

34 of 67

Что если результат плачевный?

34

34

34

35 of 67

Сигнал о нарушении принципов:

  • Stable Dependencies Principle:�Depend in the direction of stability
  • Stable Abstractions Principle:�A component should be as abstract as it is stable

​

35

35

35

36 of 67

Подробнее о принципах проектирования и исправлении их нарушений:

37 of 67

Ещё сложности

  • Именование внешних систем
  • Направление асинхронных связей
  • Добавление отсутствующей в конфиге информации

37

37

37

38 of 67

Генерировать постоянно

38

s

v

Внести изменения в единожды сгенерированное

Что если второе?

39 of 67

Проблемы архитектурных схем

0. Их отсутствие ✅

  1. Неактуальность
  2. …

​

39

40 of 67

40

41 of 67

Сравниваем данные из архитектуры и конфигов

41

[

Сервис1 {

[ связь1, связь2 ]

},

Сервис2 {

[ связь1, связь2 ]

},

]

[

Сервис1 {

[ связь1, связь3 ]

},

Сервис2 {

[ связь1 ]

},

Сервис3

]

41

41

42 of 67

42

42

42

43 of 67

Пример — сопоставление списка сервисов

it("finds diff in configs and uml containers", () => {

  const namesFromDeploy = deployConfigs.map((x) => x.name);

  const containerNamesFromPuml = containersFromPuml

    .filter((x) => x.type == "Container")

    .map((x) => x.name);

�  expect(namesFromDeploy).toEqual(containerNamesFromPuml);

});

​

43

43

44 of 67

Output

Container name bff ✅

Container name task_repository❌

Container name invoice_acl ✅ �--------------------------------------------------------

First failed container name task_repository

--------------------------------------------------------

FAIL test/architecture.spec.ts

● Architecture › finds diff in configs and uml dependencies

expect(received).toEqual(expected) // deep equality

- Expected - 1

+ Received + 1

Array [

“bff",

- “stock",

+ “goods",

“invoice",

44

44

44

45 of 67

Проблемы �архитектурных схем

0. Их отсутствие ✅

  1. Неактуальность ✅
  2. Декларативность
  3. Отсутствие контроля

​

45

46 of 67

Декларативность

46

47 of 67

Декларативность

47

48 of 67

Отсутствие контроля

48

49 of 67

Тесты на соблюдение архитектурных принципов

49

50 of 67

1. ACL (Anti-corruption Layer) Pattern

За интеграцию с внешними системами ответственны отдельные микросервисы-адаптеры, инкапсулирующие в себе знания о внешних системах (например, об их доменных сущностях)

50

50

50

51 of 67

1. ACL (Anti-corruption Layer) Pattern

51

52 of 67

1. ACL (Anti-corruption Layer) Pattern

Как протестить: 

  1. помечаем на архитектуре соответствующие микросервисы признаком «Adapter»
  2. проверяем, что связи с внешними системами имеют только сервисы с таким признаком

52

Container(goods_adapter, “Goods ACL", "NestJS", $tags="adapter")

52

52

53 of 67

Больше примеров принципов и тестов на них:

53

54 of 67

Проблемы архитектурных схем

0. Их отсутствие ✅

  1. Неактуальность ✅
  2. Декларативность✅
  3. Отсутствие контроля

​

54

55 of 67

Предписания архитекторов могут нарушаться по незнанию или умышленно

  • Упавшие тесты отсеют нарушения по незнанию
  • Обязательный апрув архитектора для PR в тестах и архитектуре отсеют недобросовестные нарушения

55

Архитектурные изменения не пройдут мимо архитектора

55

55

56 of 67

Личный опыт

  • 2 чел/нед разработчика
  • 2 чел/нед архитектора
  • 0,5 чел/нед девопса

В «продакшне» несколько месяцев

​

​

​

56

57 of 67

Личный опыт, решённые проблемы

  • Актуализировали архитектуру
  • Привели к единым конвенциям
  • Нашли топики кафки с продьюсерами, но без подписчиков
  • Нашли неиспользуемые REST-зависимости в конфигах и коде
  • Актуализировали понимание внешних систем
  • Измерили и зафиксировали архитектурный техдолг
  • Переключили на API Gateway все необходимые зависимости
  • Убрали дублирование в конфигах

57

57

57

58 of 67

Как начать применять?

  1. github.com/Byndyusoft/aact
  2. Библиотека по работе с PlantUML (или аналогом) на вашем стэке
  3. Маппинг вашего варианта InfractructureAsCode в термины архитектуры
  4. Генерация и тесты
  5. 💰💰💰

​

58

58

58

59 of 67

Как присоединиться к развитию OpenSource-репозитория?

59

60 of 67

Roadmap репозитория

  • Покрытие архитектуры тестами
  • Автогенерация
  • Инструменты рефакторинга микросервисной архитектуры

​

https://github.com/Byndyusoft/aact/blob/main/roadmap.md

​

60

60

60

61 of 67

Roadmap репозитория. Покрытие архитектуры тестами�

✅ Покрытие тестами микросервисной архитектуры

✅ Покрытие тестами архитектуры модульного монолита

🟩 Добавление реализаций и примеров под разные стэки (сейчас TypeScript и C#)

⌛ Справочник принципов и паттернов проектирования (например, в формате ADR)

⌛ Примеры тестов на пункты справочника

61

61

61

62 of 67

Покрытие архитектуры тестами. Справочник паттернов�

62

62

62

63 of 67

Покрытие архитектуры тестами. ADR�

Шаблон ADR

​

Пример ADR: ACL-паттерн

63

63

63

64 of 67

Roadmap репозитория. Автогенерация�

✅ Автогенерация архитектурной схемы по конфигам инфраструктуры

​

🟩 Автогенерация конфигов инфраструктуры по архитектурной схеме

​

🟩 Добавление провайдеров для различных реализаций IaC

​

🟩 Автогенерация и архитектурной схемы, и конфигов инфраструктуры по архитектурному решению (ADR)

64

64

64

65 of 67

Roadmap репозитория. Инструменты рефакторинга микросервисной архитектуры�

🟩 Изменение сигнатуры метода API (endpoint’а)

​

🟩 Вынос метода API (endpoint'а) микросервиса в отдельный микросервис

​

🟩 Inline микросервиса — поглощение микросервиса своим потребителем

65

65

65

66 of 67

Welcome!

66

66

67 of 67

Спасибо!

Руслан Сафин, технический директор Бындюсофт