Сдача проектной работы 6

На этот раз вы выступите в роли архитектора ПО для InsureTech. Компания предоставляет агрегационные услуги в сфере страхования. Она работает с частными и корпоративными клиентами:
  • частным клиентам компания предлагает удобный сайт для подбора и оформления страховок,
  • корпоративным клиентам и партнёрам предоставляет API для интеграции страховых услуг в их продукты.
Сейчас основной продукт InsureTech — это страхование жизни.

Проблемы компании

Компания успешно запустила MVP своего приложения и планирует активно развиваться дальше. Всё бы хорошо, но приложение столкнулось со всеми классическими проблемами быстрого роста:
  1. Сайт медленно загружает страницы. Когда нагрузка на приложение повышается, пользователи массово жалуются на то, что страницы грузятся по несколько минут или не загружаются вообще. При этом максимально зафиксированная нагрузка на запросы поиска составила 50 RPS, а на запросы оформления — 10 RPS. Такое положение дел плохо влияет на показатели NPS и retention.
  2. Нарушается SLA для B2B-клиентов. Менеджеры уже неоднократно получали сообщения от партнёров, что SLA API не соответствует заявленному. В ходе изучения таких инцидентов выяснилось, что в эти периоды количество запросов от одного из партнёров кратно возрастало. Оно достигало суммарно 250 RPS на все вызываемые операции. По сути, один из партнёров «сжирал» все ресурсы приложения. С этим партнёром изначально договорились, что нагрузка не будет превышать 20 RPS.
  3. Приложение падает. InsureTech несколько раз столкнулась с проблемой недоступности приложения. Команда реагировала на проблему очень медленно, поскольку узнавала о ней от пользователей. Каждый час простоя сервис несёт финансовые убытки — примерно 500 тысяч рублей. Также бизнес несёт репутационные потери: в СМИ выходят негативные публикации, у сервиса низкие показатели удовлетворённости пользователей, а некоторые партнёры уже заявили о нежелании продлевать сотрудничество.
InureTech планирует в ближайшее время провести большую рекламную кампанию. Ожидается существенный прирост пользователей.
Вам как архитектору нужно проработать описанные проблемы и предложить для них решения. В текущем состоянии приложение является «узким горлышком» для развития бизнеса.

Архитектура приложения

Основные компоненты приложения:
  • core-app — монолитное бэкенд-приложение. Оно отвечает за отображение доступных клиенту продуктов, оформление заявок на новые страховки и отображение уже оформленных.
  • client-info — сервис управления клиентскими данными. Он передаёт данные core-app для оформления страховок. Если пользователя нет в базе данных или его данные изменились, в процессе оформления страховки сервис client-info вносит данные в базу. Он же отвечает за отображение и редактирование клиентских данных в личном кабинете.
  • ins-product-aggregator — сервис интеграции со страховыми компаниями для получения информации о продуктах. Ещё он запрашивает у разных партнёров предложения по ОСАГО для конкретного автомобиля. Сервис предоставляет единый API, агрегируя данные от всех страховых компаний.
  • ins-comp-settlement — сервис взаиморасчётов со страховыми компаниями. Раз в месяц он отправляет перечень оформленных страховок в страховые компании для расчёта выплаты агентских премий.
  • Веб-приложение для клиентов сервиса.
Для деплоя всех приложений используется кластер Kubernetes, расположенный в одной зоне доступности.
В качестве базы данных используется PostgreSQL. Каждый сервис, использующий БД, имеет отдельную схему данных. БД развёрнута на отдельной ВМ в единственном экземпляре.
Взаимодействие между фронтендом и бэкендом происходит посредством REST.
API предоставляет партнёрам доступ напрямую через LoadBalancer Kubernetes, который доступен в сети Интернет.
Бэкенд-приложение интегрировано с пятью страховыми компаниями.
Вот диаграмма контейнеров приложения в модели C4:

Как подготовиться к работе

Первым делом — приготовьтесь к работе над проектом.
Настройте draw.io:
  1. Установите draw.io или откройте онлайн-редактор. Используйте тот способ, который вам удобнее.
  2. В draw.io установите библиотеки иконок Yandex Cloud для сервисов и контейнеров.
Установите инструменты, которые нужны для выполнения заданий:
  1. Minikube.
  2. Kubectl.
  3. Python.
  4. Pip
  5. Locast. Чтобы его установить, потребуется pip.
Подготовьте репозиторий, куда вы будете загружать решения заданий:
  1. Проект этого спринта вы будете сдавать в Git-репозитории. Создайте публичный репозиторий в GitHub или GitLab. Назовите его «architecture-sprint-6».
  2. Проект состоит из шести заданий. Решение каждого задания нужно будет залить в отдельную директорию. Создайте в репозитории шесть директорий и назовите их «Exc1», «Exc2», «Exc3», «Exc4», «Exc5» и «Exc6».
  3. Чтобы ревьюеру было проще проверять вашу работу, а вам отслеживать изменения на разных итерациях, загрузите файлы в свой репозиторий и сделайте пулл-реквест. На ревью нужно отправить ссылку на пулл-реквест.
Повторите теорию, которая точно пригодится:
  1. Как документировать решения с помощью модели C4. Мы рассказывали про это в спринте «Создание микросервисов, построение пайплайна CI/CD», тема называется «Построение микросервисного лендскейпа».
  2. Синтаксис манифестов Kubernetes.
  3. Синтаксис конфигураций Nginx.
  4. Синтаксис OpenAPI (Swagger).
  5. Синтаксис схем GraphQL.
Когда всё будет готово, можете смело приступать к заданиям!

Задание 1. Проектирование технологической архитектуры

Компания хочет сделать упор на развитие в регионах РФ. Планируется значительный рост количества пользователей и запросов. Нужно обеспечить бесперебойную работу сервиса 24/7, при этом сервис должен обслуживать клиентов из всех часовых поясов.
Требования к отказоустойчивости системы крайне высокие: RTO — 45 мин., RPO — 15 мин. Согласно требованиям бизнеса, доступность приложения должна быть равна 99,9%.
Дополнительно к этому нужно обеспечить одинаковое время загрузки страниц для пользователей из разных регионов. Оно не должно зависеть от географического местоположения пользователя.
На текущий момент сервис хранит ограниченный набор данных, который включает в себя:
  • базовую информацию о клиентах — ФИО, контакты, документы,
  • информацию о продуктах и тарифах,
  • историю заявок клиентов.
Общий объём данных, которые хранятся в системе, равен 50 GB.

Что нужно сделать

Необходимо спроектировать технологическую архитектуру приложения так, чтобы оно отвечало требованиям бизнеса. Создайте схему итогового решения на основании текущей технологической архитектуры сервиса.
Вот схема текущей архитектуры в draw.io:
Создайте новый документ в draw.io и назовите его «InureTech_технологическая архитектура_to-be». Работайте над первым заданием там.
Постарайтесь выдержать единый стиль оформления. Желательно, чтобы схема вашего решения была оформлена в той же нотации, что и схема текущей архитектуры. Для этого используйте библиотеки объектов Yandex Cloud. Ссылки на них мы дали в блоке «Как подготовиться к работе».
При проектировании уделите внимание следующим аспектам:
  1. Определите стратегию масштабирования и отказоустойчивости. Рассмотрите вертикальное и горизонтальное масштабирование для вашей системы. Оцените, какая стратегия будет эффективнее. Требуется ли использование дополнительных зон безопасности?
  2. Если приняли решение деплоить приложение в нескольких зонах безопасности, то продумайте и отразите на схеме следующие вопросы:
    a. Проработайте конфигурацию развёртывания приложения в Kubernetes. Вы будете использовать независимые кластеры в каждой площадке или один растянутый? Оставьте на схеме комментарий с объяснением, почему вы выбрали тот или другой подход. b. Спланируйте балансировку нагрузки. Опишите подход к балансировке нагрузки, который обеспечит распределение трафика между вашими сервисами и географически распредёленными серверами. Явно отразите на схеме все health check. c. Определите наиболее подходящую фейловер-стратегию. Она должна отвечать заданным требованиям отказоустойчивости. Отразите её на схеме на уровне взаимодействия клиента с приложением. d. Определите конфигурацию базы данных. Учитывая требования RTO и RPO, спроектируйте конфигурацию базы данных: определите, как вы будете обеспечивать репликацию данных и их резервное копирование. Если будете использовать конкретный фреймворк конфигурации кластера БД, отразите его на схеме.
  3. Определите, будете ли вы применять шардирование БД. Отразите своё решение на схеме.
Когда будете сдавать задание, загрузите готовую схему в директорию Exc1 в рамках пул-реквеста.

Задание 2. Динамическое масштабирование контейнеров

Сейчас сервисы InsureTech развёрнуты в Kubernetes. Каждый из них развёрнут в определённом количестве экземпляров.
Обычно этих экземпляров достаточно для успешной обработки всех запросов. Но в периоды пиковой нагрузки система не справляется: она демонстрирует нестабильное поведение и постоянно перезагружает поды из-за нехватки памяти. Как следствие, пользователи получают негативный опыт работы с приложением. Бизнес видит, что NPS снижается.
Можно, конечно, держать больше реплик постоянно активными, чтобы система могла справиться с пиковыми нагрузками. Но это экономически невыгодно и приведёт к низким показателям утилизации ресурсов. Таким образом, вам необходимо решить проблему с помощью конфигурации динамического масштабирования для сервисов компании.
Вы будете тестировать динамическое масштабирование на примере простого приложения. Оно предоставляет два ресурса:
  • GET / — получение идентификатора пода;
  • GET /metrics — получение метрик в формате Prometheus.
Метрика http_requests_total возвращает количество запросов для метода получения идентификатора пода.
Образ тестового приложения. Оба метода приложения доступны по порту 8080.
🔍 Обратите внимание: в этом задании две части — одна обязательная, другая дополнительная.
Мы рекомендуем выполнить вторую часть, если вы хотите глубже разобраться в теме и получить опыт конфигурации кастомных метрик и горизонтального масштабирования на их основе. Главный плюс этой части в том, что эта задача ближе к реальной жизни и намного чаще встречается на практике, чем масштабирование на базе памяти и CPU.
Если у вас нет цели разобраться с кастомной конфигурацией метрик, можете пропустить дополнительное задание. Первой части достаточно, чтобы получить общее понимание механизма динамической маршрутизации.

Обязательная часть задания: динамическая маршрутизация на основании показателей утилизации памяти

Что нужно сделать

  1. Поднимите локальный кластер Kubernetes в Minikube.
  2. Активируйте metrics-server.
  3. Напишите манифест развёртывания (Deployment) Kubernetes для запуска тестового приложения. Для начального количества реплик установите значение, равное единице. Лимит памяти установите равный “30Mi”. Примените написанную конфигурацию в вашем кластере. В рамках пул-реквеста добавьте файл в директорию Exc2.
  4. Напишите и примените манифест сервиса (Service) для доступа к приложению, которое вы установили на прошлом шаге. В рамках пул-реквеста файл с этим манифестом тоже загрузите в директорию Exc2.
  5. Настройте динамическую маршрутизацию на основании показателей утилизации оперативной памяти с помощью Horizontal Pod Autoscaler (HPA). Для нашего тестового приложения оптимальный уровень утилизации памяти равен 80%. В качестве максимального количества реплик рекомендуем установить 10. Примените манифест в вашем кластере. В рамках пул-реквеста загрузите готовый манифест в директорию Exc2.

    BASH

    minikube service <имя сервиса> --url 
  6. Настройте динамическую маршрутизацию на основании показателей утилизации оперативной памяти с помощью Horizontal Pod Autoscaler (HPA). Для этого нужно активировать поддержку метрик в вашем кластере. Самый простой способ это сделать — воспользоваться командой:

    BASH

    minikube addons enable metrics-server 
  7. Теперь создайте манифест для Horizontal Pod Autoscaler. Этот манифест будет автоматически масштабировать количество реплик вашего приложения в зависимости от роста потребления оперативной памяти (memory). Для нашего тестового приложения оптимальный уровень утилизации памяти равен 80%. В качестве максимального количества реплик рекомендуем установить 10. Примените манифест в вашем кластере. Загрузите готовый манифест в директорию Exc2 в рамках пул-реквеста.
  8. Теперь надо убедиться, что всё работает как задумано. Для этого необходимо сгенерировать нагрузку на приложение. Воспользуйтесь инструментом нагрузочного тестирования locust:
    a. Создайте Locustfile. Это сценарий на Python, где вы определяете поведение пользователей. Создайте файл с именем locustfile.py в удобной для вас директории. Скопируйте туда код:

    BASH

         from locust import HttpUser, between, task
     
         class WebsiteUser(HttpUser):
             wait_time = between(1, 5)
       
             @task
             def index(self):
                 self.client.get("/") 
    Этот пример создаёт класс пользователя, который переходит на главную страницу ("/") с интервалом между запросами от 1 до 5 секунд.
    b. Откройте терминал и перейдите в директорию, где находится ваш locustfile.py. Выполните команду:

    BASH

    locust 
    c. После запуска Locust откройте веб-браузер и введите адрес http://localhost:8089. Вы увидите веб-интерфейс Locust, где можно настроить параметры теста: количество пользователей и hatch rate — скорость, с которой генерируются новые пользователи.
    d. Запустите тест и проанализируйте результаты. Проще всего посмотреть результаты в дашборде Kubernetes. В локальном кластере Minikube его можно открыть с помощью команды:

    BASH

    minikube dashboard 
    Сделайте скриншоты дашборда или выгрузите логи, которые покажут, что количество реплик базы данных поменялось в ответ на сгенерированную нагрузку. Загрузите их в директорию Exc2 в рамках пул-реквеста.

Дополнительная часть задания: динамическая маршрутизация на основании показателей количества запросов в секунду

🔍 Это задание выполнять необязательно. Если сдадите работу без него, это не отразится на ревью.
Kubernetes предоставляет возможность управлять масштабированием на основании CPU и memory. Однако на реальных проектах зачастую требуется бóльшая гибкость для управления масштабированием. Для этого нужно использовать внешние метрики из системы мониторинга, которая может предоставить их в Kubernetes. Например, Prometheus.
В нашем проекте нужно настроить динамическое масштабирование на основании количества запросов в секунду (RPS) на один под приложения.

Что нужно сделать

  1. Установите Prometheus в вашем кластере. Рекомендуем установить Prometheus в Kubernetes с помощью Prometheus Operator через Helm. Лучше всего воспользоваться Prometheus Community Helm charts. Для этого используйте команды:

    YAML

    helm repo add prometheus-community <https://prometheus-community.github.io/helm-charts>
    helm repo update
    helm install prometheus-operator prometheus-community/kube-prometheus-stack 
  2. Теперь необходимо обеспечить экспорт метрик из приложения в Prometheus. Для этого стоит воспользоваться Service Monitor. Он использует Prometheus Operator для автоматического обнаружения сервисов в Kubernetes посредством Service Discovery. Вот пример манифеста ServiceMonitor:

    YAML

    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: scaletestapp-app-sm
      namespace: default
      labels:
        serviceMonitorSelector: prometheus
    spec:
      endpoints:
        - interval: 10s
          targetPort: 8080
          path: /metrics
      namespaceSelector:
        matchNames:
          - default
      selector:
        matchLabels:
          prometheus-monitored: "true" 
    Требуемый сервис можно обнаружить посредством лейбла app или кастомного лейбла (например, prometheus-monitored), который вы можете отразить в манифесте Service.
  3. ServiceMonitor можно применить как отдельный манифест или воспользоваться специальной секцией additionalServiceMonitors при настройке Prometheus Operator через Helm. \n Вот пример конфигурации Prometheus Operator:

    YAML

    defaultRules:
      create: false
    alertmanager:
      enabled: false
    grafana:
      enabled: false
    kubeApiServer:
      enabled: false
    kubelet:
      enabled: false
    kubeControllerManager:
      enabled: false
    coreDns:
      enabled: false
    kubeEtcd:
      enabled: false
    kubeScheduler:
      enabled: false
    kubeStateMetrics:
      enabled: false
    nodeExporter:
      enabled: false
    prometheus:
      enabled: true
      additionalServiceMonitors:
        - name: app-sm
          namespace: default
          labels:
            serviceMonitorSelector: prometheus
          endpoints:
            - interval: 10s
              targetPort: 8080
              path: /metrics
          namespaceSelector:
            matchNames:
              - default
          selector:
            matchLabels:
              prometheus-monitored: "true" 
  4. Когда примените конфигурацию, проверьте, что метрики из вашего приложения поступают в Prometheus. Зайдите в Prometheus Web UI, откройте раздел Graph или Targets, чтобы убедиться, что ваше приложение отображается и метрики доступны. Чтобы получить доступ к интерфейсу, нужно открыть доступ к серверу Prometheus с локальной машины. Например, с помощью команды:

    BASH

    minikube service <имя сервиса> --url 
    Сделайте скриншоты интерфейса с метриками и загрузите их в директорию Exc2.
  5. Теперь необходимо настроить Prometheus Adapter для использования метрик Prometheus в Horizontal Pod Autoscaler (HPA). Prometheus Adapter служит мостом между Kubernetes и Prometheus. Он позволяет Kubernetes использовать метрики Prometheus для масштабирования подов. Чтобы настроить Prometheus Adapter:
    a. Когда используете Helm для установки или обновления Prometheus Adapter, предоставьте значения, которые переопределяют базовую конфигурацию. Создайте файл values.yaml и включите туда определение для prometheus-adapter:

    YAML

       prometheus:
         url: "http://<адрес_prometheus>"
       rules:
         default: false
         custom:
           - seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
             resources:
               overrides:
                 namespace: {resource: "namespace"}
                 pod: {resource: "pod"}
             name:
               matches: "^http_requests_total"
               as: "http_requests_per_second"
             metricsQuery: 'sum(rate(http_requests_total{<<.LabelMatchers>>}[30s])) by (<<.GroupBy>>)'
        
    b. Установите Prometheus Adapter при помощи команды:

    BASH

       helm intall prometheus-adapter prometheus-community/prometheus-adapter -f values.yaml
        
    c. Чтобы убедиться, что кастомная метрика http_requests_per_second стала доступной, воспользуйтесь командой:

    BASH

       kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1
        
  6. Обновите манифест Horizontal Pod Autoscaler. Укажите там, что масштабирование нужно производить на базе новой метрики — http_requests_per_second. Вот пример манифеста:

    YAML

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: scaletestapp-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: scaletestapp
      minReplicas: 1
      maxReplicas: 10
      metrics:
        - type: Pods
          pods:
            metric:
              name: http_requests_per_second
            target:
              type: AverageValue
              averageValue: 50 
    Когда будете сдавать задание, загрузите новую версию манифеста в директорию Exc2.
  7. Теперь надо убедиться, что всё работает как задумано. Для этого сгенерируйте нагрузку на приложение. Действуйте по аналогии с восьмым шагом в обязательной части задания.
    Сделайте скриншоты дашборда или выгрузите логи, которые покажут, что количество реплик базы данных поменялось в ответ на сгенерированную нагрузку. Загрузите их в директорию Exc2 в рамках пул-реквеста.

Задание 3. Переход на Event-Driven архитектуру

Сервисы core-app и ins-comp-settlement получают данные о доступных продуктах через REST API сервиса ins-product-aggregator. В момент вызова он:
  • запрашивает информацию из всех страховых компаний (сейчас их пять),
  • агрегирует её в единый список,
  • возвращает этот список в рамках того же синхронного запроса.
Чтобы ускорить работу сервисов, при изначальном проектировании команда решила хранить локальные реплики данных о продуктах и тарифах в сервисах core-app и ins-comp-settlement.
Сервис core-app осуществляет запрос к ins-product-aggregator раз в 15 минут, а ins-comp-settlement — раз в сутки (ночью), при формировании реестра оформленных страховок. Иногда команда сталкивается с ошибками взаимодействия между этими сервисами. Они связаны с задержками ответов или ошибками при взаимодействии с API страховых компаний.
Дополнительно сервис ins-comp-settlement раз в сутки осуществляет запрос в core-app по REST API для получения всех оформленных за день страховок. Эти данные он использует.
В ближайшее время InsureTech планирует подписать агентское соглашение ещё с пятью страховыми компаниями. Вам предстоит спроектировать решение, которое устранит текущие проблемы.

Что нужно сделать

  1. Проанализируйте текущую архитектуру. Создайте текстовый документ и напишите там список проблем и рисков, которые связаны с планируемым ростом нагрузки. Когда всё будет готово, загрузите документ в директорию Exc3 в рамках пул-реквеста.
  2. Обновите диаграмму контейнеров InsureTech, предложив решения для выявленных вами рисков и проблем. При этом:
    • Не меняя декомпозицию функциональности между сервисами, подумайте, какие взаимодействия стоит переделать на Event-Streaming.
    • Решите, будете ли вы использовать паттерн Transactional Outbox.
    Когда схема будет готова, загрузите её в директорию Exc3 в рамках пул-реквеста.

Задание 4. Проектирование продажи ОСАГО

Компания планирует вскоре запустить новый продукт: оформление ОСАГО онлайн. Пользовательский путь выглядит так: клиенту предлагается заполнить заявку с информацией о своём автомобиле, после этого сервис запрашивает у всех доступных страховых компаний предложения с условиями страхования под заявку клиента. Бизнесу важно, чтобы на экране пользователя предложения от каждой страховой компании отображались сразу, как только от неё пришёл ответ. Максимальное время ожидания решения от страховой компании — 60 секунд.
Все страховые компании предоставляют однотипные REST API с двумя эндпоинтами:
  • создать заявку на ОСАГО,
  • получить предложение по заявке.
Бизнес предполагает, что в пик нагрузки количество одновременных пользователей, создающих заявку на ОСАГО, может достигать 2,5 тысячи человек.
Вы обсудили задачу с командой разработки и приняли такие решения:
  1. Сохранить подход, который использовался для получения данных о продуктах и тарифах из страховых компаний.
  2. Выделить отдельный сервис для взаимодействия со страховыми компаниями — osago-aggregator.
Функциональная обязанность этого сервиса — отправка заявок в страховые компании и дальнейший опрос решений по ним для передачи результатов в core-app. Остальная функциональность, связанная с оформлением ОСАГО, остаётся на стороне бэкенда в core-app.
Теперь вам нужно проработать ещё несколько моментов, исходя из требований бизнеса. Доработайте схему, которая у вас получилась в третьем задании. Отразите на ней ваши решения по этим вопросам:
  1. Проработайте реализацию osago-aggregator. Решите:
  2. Требуется ли ему своё хранилище данных?
  3. Какой API он предоставляет core-app?
  4. Определите средство интеграции между сервисами core-app и osago-aggregator.
  5. Подумайте над API для веб-приложения в core-app.
  6. Определите средство интеграции между веб-приложением и core-app. Если будете использовать средство, отличное от REST, отразите интеграцию новой стрелкой.
  7. В зависимости от выбранных средств интеграции подумайте, требуется ли где-то применение паттернов отказоустойчивости:
    • Rate Limiting,
    • Circuit Breaker,
    • Retry,
    • Timeout.
    Отобразите применение паттернов на схеме с помощью обозначений из этой библиотеки.
  8. Примите во внимание, что сервисы задеплоены в нескольких экземплярах. Подумайте, зависит ли ваше решение от этого.
Загрузите новый вариант схемы в директорию Exc4 в рамках пул-реквеста.

Задание 5. Проектирование GraphQL API

При развитии сервиса управления клиентскими данными (client-info) команда столкнулась с проблемой. Потребители данных (веб-приложения и сервиса core-app) в разных сценариях продажи и обслуживания страховок могут требовать абсолютно разные данные. При этом карточка клиента у сервиса достаточно объёмная: общий атрибутивный состав достигает 500 штук. Из-за высокой вариативности набора запрашиваемых данных команда приняла решение в своём REST API предоставить множество отдельных ресурсов, с помощью которых можно запрашивать отдельные объекты данных клиента: контакты, документы, родственники и так далее.
Однако такая реализация кратно увеличивает нагрузку и RPS сервиса client-info, поскольку в рамках одного сценария могут потребоваться сразу несколько объектов данных — их придётся запрашивать по отдельности. Предоставить один ресурс для получения абсолютно всех данных клиента не представляется возможным: объём передаваемых данных будет настолько большим, что замедлит скорость взаимодействия с сервисами (особенно с веб-приложением).
Вы обсудили проблему с командой и приняли решение перевести REST API сервиса client-info на GraphQL.

Что нужно сделать

Спроектируйте GraphQL на основании существующего контракта сервиса:
  1. Проанализируйте Swagger контракт client-inf. Оцените существующую структуру API, выделите ключевые ресурсы и операции.

    Контракт Swagger

    YAML

    swagger: '2.0'
    info:
     description: API сервиса управления клиентскими данными
     version: 1.0.0
     title: Клиентский Сервис
    host: api.client-service.com
    basePath: /v1
    schemes:
     - https
    paths:
     /clients/{id}:
       get:
         tags:
           - Клиент
         summary: Получить информацию о клиенте по ID
         description: Возвращает информацию о клиенте.
         produces:
           - application/json
         parameters:
           - name: id
             in: path
             description: ID клиента
             required: true
             type: string
         responses:
           '200':
             description: Успешный ответ
             schema:
               $ref: '#/definitions/Client'
     /clients/{id}/documents:
       get:
         tags:
           - Документы
         summary: Список документов клиента
         description: Возвращает список документов клиента по ID.
         produces:
           - application/json
         parameters:
           - name: id
             in: path
             description: ID клиента для поиска его документов
             required: true
             type: string
         responses:
           '200':
             description: Успешный ответ
             schema:
               type: array
               items:
                 $ref: '#/definitions/Document'
     /clients/{id}/relatives:
       get:
         tags:
           - Родственники
         summary: Информация о родственниках клиента
         description: Возвращает информацию о родственниках клиента по ID.
         produces:
           - application/json
         parameters:
           - name: id
             in: path
             description: ID клиента
             required: true
             type: string
         responses:
           '200':
             description: Успешный ответ
             schema:
               type: array
               items:
                 $ref: '#/definitions/Relative'
    definitions:
     Client:
       type: object
       properties:
         id:
           type: string
         name:
           type: string
         age:
           type: integer
     Document:
       type: object
       properties:
         id:
           type: string
         type:
           type: string
         number:
           type: string
         issueDate:
           type: string
         expiryDate:
           type: string
     Relative:
       type: object
       properties:
         id:
           type: string
         relationType:
           type: string
         name:
           type: string
         age:
           type: integer
      
  2. На основе анализа REST API разработайте эквивалентную схему GraphQL, которая позволит избежать дублирования за счёт гибкости в выборе запрашиваемых данных.
  3. Определите сущности, их поля, а также необходимые запросы (queries), которые покроют все операции REST API.
Когда будете сдавать решение, загрузите схему в директорию Exc5 в рамках пул-реквеста.
Проанализируйте получившееся решение и подумайте, как GraphQL помогает оптимизировать взаимодействие между потребителями и client-info. Описывать свои выводы в решении не нужно, это упражнение полезно выполнить для себя.

Задание 6. Настройка Rate Limiting

Количество запросов от одного из партнёров всё ещё снижает производительность приложения. Это влияет на опыт использования API других партнёров. Этой проблемой тоже нужно заняться.
Одно из возможных решений — динамическое масштабирование приложения, которое вы уже внедрили. Однако ресурсы системы не бесконечные. Поэтому необходимо предусмотреть дополнительную защиту на случай, если количество запросов от партнёра снова превысит оговорённое количество.
С этим поможет паттерн Rate Limiting.

Что нужно сделать

  1. Перед вами конфигурационный файл Nginx. Доработайте его таким образом, чтобы обеспечить ограничение количества отправляемых запросов. Должно быть не более 10 запросов в минуту.

    JSX

    http {
       # Настройка upstream для балансировки нагрузки
       upstream backend_servers {
           server backend1.example.com;
           server backend2.example.com;
           server backend3.example.com;
       }
    
       server {
           listen 80;
    
           location / {
               proxy_pass http://backend_servers;
           }
    
       }
    }
      
  2. Сделайте так, чтобы при превышении лимита запросов клиент получал HTTP-ошибку с кодом 429.
Сохраните обновлённый конфигурационный файл в директорию Exc6 в рамках пул-реквеста.

Как сдать работу

В начале работы у вас должен быть Git-репозиторий, в котором есть шесть пустых директорий. Чтобы сдать своё решение на проверку, вам нужно сделать пул-реквест, который будет содержать все изменения.
В директории Exc1 должна лежать схема в draw.io с новым вариантом технологической архитектуры («InureTech_технологическая архитектура_to be»).
Содержание директории Exc2 зависит от того, выполнили вы все задания или только обязательное.
Для сдачи обязательной части в директории должны быть:
  1. Манифест развёртывания (Deployment).
  2. Манифест для Horizontal Pod Autoscaler.
  3. Манифест для Service.
  4. Скриншоты дашборда или логи, которые показывают, что количество реплик базы данных поменялось в ответ на сгенерированную нагрузку.
Если вы выполнили дополнительную часть задания, то в Exc2 также будут:
  1. Доработанный манифест для Horizontal Pod Autoscaler.
  2. Скриншоты Prometheus, отображающие сбор нужных метрик приложения.
  3. Скриншоты дашборда или логи, которые показывают, что количество реплик базы данных поменялось в ответ на сгенерированную нагрузку.
В директории Exc3 должны быть документ с описанием проблем и рисков, а также обновлённая диаграмма контейнеров InsureTech в draw.io.
В Exc4 — схема draw.io в нотации С4 с результатами задания.
В Exc5 — схема GraphQL.
В Exc6 — конфигурационный файл Nginx.