Як створити онлайн-банкінг для бізнесу: нефункціональні вимоги, Highload та розрахунок ресурсів. Chapter 2

💡 Усі статті, обговорення, новини про Java — в одному місці. Приєднуйтесь до Java спільноти!

Усім привіт! З вами знову Костянтин Каширін. Як і обіцяв у попередньому дописі (де ми розбирали етап G0 і формували бізнес-бачення), сьогодні ми занурюємося в сувору реальність інженерії. Переходимо до етапу G1 — системний аналіз.

Тут ми вже починаємо справжнє мʼясо. Онлайн банкінг для юридичних осіб це не те саме що і для звичайного користувача у якого просто картка з 15ти гривнями на ній. Банкінг для Юр осіб це місце де +1 секунда не так сильно грає роль при платежі, тут головне контрольованість, керованість та аудит

У цій статті ми розберемо вимоги до розробки системи дистанційного банківського обслуговування (ДБО), що розрахована на роботу 1 000 000 активних користувачів, побудована на мікросервісній архітектурі та повністю відповідає актуальним нормам НБУ.
Так, так, вам не почулось, 1 мільйон, і це наша мета. Який сенс нам боротись за 10тис юр осіб як в монобанку, ми Ощадбанк, у нас купа Юр осіб і ми хочемо більше і стати монополією, бажаємо крові, влади ще більше грошей, дівок і пива і тому ми будемо орієнтуватись на таку цифру, так.

Якщо коротко, ми буквально зараз опишемо не функціональні вимоги. Але якщо вам не цікаво, то наступна стаття буде вже технічною і можете одразу чекати її.

Нефункціональні вимоги

Тут трішки буде написано багато тексту, але важливого для майбутнього
Ми візьмемо з якоїсь книги основні стовпи нефункціональних вимог: це Throughput, Latency, Concurrency, Autoscaling, Observability, Security, Compliance,

1. Продуктивність та Масштабованість (Performance & Scalability)

  • Пропускна здатність (Throughput): Система повинна витримувати базове навантаження у 300 RPS та пікове навантаження до 1000 RPS. так, цифра дещо смішна, але 1000 користувачів одночасних на секунду не так і легко витримати якщо операції не просто отримати користувача по ІД
  • Час відгуку (Latency): не враховуючи майбутній Service Mesh
    • Для операцій читання (Read): ≤ 200мс (максимальне число 200мс)
    • Для транзакційних операцій (Write): ≤ 500мс, без урахування часу на інтеграцію з зовнішніми системами, бо ми за них не відповідальні
  • Конкурентність (Concurrency): Підтримка мінімум 50 000 одночасних активних сесій без деградації часу відгуку.
  • Масштабування (Autoscaling):
    • Синхронні мікросервіси масштабуються через Horizontal Pod Autoscaler (HPA) при досягненні ≥ 60% утилізації CPU або RAM.
    • Асинхронні воркери масштабуються на основі глибини черги (lag) у топіках Kafka (використовуючи KEDA).
    • Час підняття та готовності нової ноди (Cold Start) не повинен перевищувати 30 секунд.

2. Доступність та Відмовостійкість (Availability & Reliability)

  • SLA (Service Level Agreement): Доступність системи на рівні 99.99% (максимальний час простою — 52 хвилини на рік), це урахуванням деплоїв і всього іншого
  • RTO (Recovery Time Objective): Цільовий час відновлення системи після критичного збою — не більше 15 хвилин.
  • RPO (Recovery Point Objective): Цільова точка відновлення — 0. Будь-яка втрата фінансових транзакцій є неприпустимою. І тут ми вдаримось в тему баз даних, бо саме там нам треба буде гарантувати RPO
  • Також у разі відмови некритичних сервісів (наприклад, модуля аналітики чи генерації PDF), базовий функціонал (проведення платежів) повинен продовжувати працювати, тому у нас буде мікросервісна архітектура

3. Цілісність даних та Архітектурні патерни (Data Integrity)

  • Ідемпотентність API: Усі POST, PUT, DELETE запити повинні бути ідемпотентними.
  • Розподілені транзакції:
    • Заборона використання двофазних комітів (2PC) в платежах, бо ми по суті будемо робити платіж через систему корпоративного банку тобто абс і синхронізуватися з нею.
    • Для забезпечення узгодженості між мікросервісами використовується патерн Saga (Оркестрація або Хореографія) із механізмом компенсуючих транзакцій.
  • Надійність доставки подій: Використання патерну Transactional Outbox. Запис фінансової транзакції у PostgreSQL та відправка події у Kafka виконуються в єдиній локальній транзакції БД, щоб уникнути втрати повідомлень (гарантія At-Least-Once delivery).

4. Безпека (Security & Compliance)

  • Шифрування:
    • Data in Transit: Увесь трафік між клієнтом і сервером, а також між мікросервісами (mTLS), це по суті строга вимога де ми використаємо сервіс меш.
    • Data at Rest: Шифрування БД та бекапів алгоритмом AES-256. Зберігання секретів та API-ключів у HashiCorp Vault. Але при цьому не всі дані будуть в бд шифрованими, ми все-таки не будемо використовувати дорогий Оракл, але сенсетів дата повинна шифруватись.
  • Автентифікація та Авторизація:
    • Використання OAuth 2.0 / OpenID Connect.
    • Короткострокові JWT-токени (TTL 15 хвилин) з механізмом Refresh Token Rotation.
    • Перевірка прав доступу (RBAC) відбувається на рівні API Gateway та дублюється на рівні кожного мікросервісу.
  • Криптографія НБУ: Накладання та перевірка КЕП. Тут ми будемо використовувати Сайфер або ІІТ або і те і інше).
  • Audit Trail: Аудит важливих дій користувачів та адміністраторів на рівні БД, ізольоване від звичайних логів аплікації. По суті це аудит що користувач щось підписав чи створив перехід між сторінками чи перегляд чогось ми не будемо писати сюди.

5. Спостережуваність (Observability

  • Розподілене трасування (Distributed Tracing): Імплементація OpenTelemetry. Кожен HTTP-запит від клієнта отримує Trace-ID, який прокидається через усі мікросервіси та Kafka до кінцевої точки для відстеження «вузьких місць» (+візуалізація).
  • Метрики: Експорт системних (JVM heap, GC pauses, HikariCP pool) та бізнес-метрик (кількість успішних/відхилених платежів) у Prometheus для побудови дашбордів у Grafana.
  • Централізоване логування: Збір логів з усіх подів через Fluent-bit/Logstash у єдиний кластер Elasticsearch (ELK стек) із обов’язковим маскуванням персональних та фінансових даних клієнтів.

Тож ідею що до чого розписав, а тепер будемо рахувати, але тут буде умовність така, будуємо систему де 200 тис користувачів на годину як дефолтний стан. Тобто майбутні оптимізації урізання або масштабованість є причиною цього, і якщо вам треба буде просто 200 тис користувачів на день то просто вріжете декілька подів й на цьому можна зекономити.

Формули розрахунку стандартні які просто в Гуглі можна знайти і які працюють.

Розрахунок цільового навантаження (200 000 користувачів пер годину)

  • Крок 1. Обсяг запитів на годину: Беремо середню сесію — 20 API-запитів на одного користувача (авторизація, баланс, завантаження довідників, створення 1-2 платежів). «враховувати масові імпорти платежів ми не будемо, бо вони не грають роль у підрахунку»
    • Трафік = 200 000 × 20 = 4 000 000 запитів за годину
  • Крок 2. Базовий RPS (Requests Per Second):
    • Базове навантаження = 4 000 000 / 3600 секунд ≈ 1 111 запитів за секунду
  • Крок 3. Пікові мікро-сплески (Burst factor): Навіть у межах однієї години трафік ніколи не буває ідеально рівним. Бувають сплески в перші хвилини години або реакції на масові push-сповіщення. Для фінансових систем береться коефіцієнт запасу x2.5 або x3.
    • Цільовий піковий RPS = 1 111 RPS × 3 ≈ 3 300 RPS
  • Крок 4. Пропорція Read/Write (TPS):
    • 90% Read (≈ 3 000 RPS): Перегляд балансів та виписок. Витримується за рахунок In-Memory кешу (Redis Cluster) та 3-4 Read-реплік бази даних PostgreSQL.
    • 10% Write (≈ 330 TPS): Фізичний запис нових платежів, накладання КЕП. Це вже дуже серйозне навантаження на блокування рядків у Master-ноді бази даних. Тут звичайно ми спробуємо трішки поборотися з тим, щоб це було не боляче і швидко, але ми все ж таки дамо собі можливість взяти зайву секунду на запис.

Конвертація навантаження в інфраструктурні ресурси (Pod Sizing)

Щоб витримати 3 300 RPS без деградації часу відгуку, вимоги до заліза зростають пропорційно і звучить як дорого багато:

  • Бекенд: Сучасний Spring Boot (Java 25) з використанням Virtual Threads або реактивного стеку на 1 vCPU для вузьких задач здатен тримати від 800 до 2000+ RPS в залежності від ролі сервісу та його роботи в фоні. Тому буквально в спокійний день або в ночі можна тримати 1-3 пода активних в залежності від сервісу. далі ми побудуємо десь 25 мікросервісів, тому для сучасних навантажень це нормальна ціна.
  • База даних (PostgreSQL): на сьогодні PostgreSQL на SSD/NVMe дисках легко виконує від 5 000 до 10 000 простих TPS. Master-нода (Write): Для нашого навантаження повністю достатньо інстансу на 8-16 vCPU та 32-64 GB RAM. Цього з запасом вистачить для фіксації транзакцій, генерації WAL-логів та утримання індексів у пам’яті, але наші RTO та RPO нам кажуть що треба по іншому спробувати, а саме 2 майстер ноди
  • Read-репліки: Для обробки 3000 RPS на читання вистачить 1-2 реплік аналогічного розміру.
  • Брокер повідомлень (Kafka): Ну навіть якщо ми захочемо запити всі опрацьовувати через казку, то нам буде її достатньо хоч як би ми її не поставили чи налаштували, АЛЕ:
      • Три брокери
      • 2-4 під одного консюмера
      • інстанси 2-4 vCPU та 8-16 GB RAM

В принципі якщо залізо сучасне і сучвасні технології, то нам буде легше пережити навантаження, і дешевше в майбутньому.

Тому на завершення скажу що буде далі

Далі у нас будуть технічні статті, і наступна буде про Бази Даних, як ми з ними будемо жити і як нам жити Java 25 в ними.

Стаття все ж таки маленька, але посперечатися є про що)

👍ПодобаєтьсяСподобалось8
До обраногоВ обраному6
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter