flowchart LR A[User] --> B((Internet)) B --> C[Service] C --> D((Network)) D --> E[(Storage)] style A fill:#5cb85c style B fill:#5bc0de style C fill:#d9534f style D fill:#5bc0de style E fill:#428bca
Конструювання програмного забезпечення
КНУ імені Тараса Шевченка, ФІТ
ihor.miroshnychenko@kneu.ua



Як долучитися?
Примітка
Клас буде активний з 11 жовтня 2023 року до 11 квітня 2024 року, після чого буде відкрито наступний потік. Слідкуйте за оновленнями.
Оскільки задача проєктування систем майже завжди формується у відкритій формі, нам потрібно окреслити функціонал та визначити вимоги до системи.
Функціональні вимоги - це можливості, які система надає користувачеві.
Наприклад, для соціальних мереж це:
Для цього варто виписати основні можливості системи в порядку важливості та вказати, над якими ми плануємо сконцентруватися надалі.
Потім, залежно від спрямованості соціальної мережі, можемо представити такі функції, як:
Якісь соцмережі можуть підтримувати всі напрямки і додаткові можливості, на кшталт додавання геотегів, пошуку контенту, рекомендацій тощо.
Нефункціональні вимоги - це те, як має поводитися система в роботі.
Типові запитання, на які хочемо відповісти:

На перший погляд всі ці питання можуть виглядати дивними — чому б не зробити систему якомога швидшою та надійнішою? Але відповіді на них допоможуть нам зрозуміти, які компроміси ми готові робити.
Наприклад, CAP-теорема говорить, що розподілена система не може одночасно бути:
Збої мережі неминучі, тому на час розділення обираємо між C та A.

Для соціальної мережі важливо, щоб вона завжди була доступною.
Соціальна мережа також розподілена, маючи користувачів по всьому світу (і сервери, відповідно).
Однак, якщо користувач публікує пост, можливо, ми не одразу його побачимо.
Нічого страшного, якщо станеться затримка, рано чи пізно він все одно стане доступним для всіх користувачів. Тобто, консистентність не така критична.
У випадку з банківським додатком успішно проведена грошова транзакція повинна означати надходження і видимість коштів на рахунку адресата, ніяк інакше.
Ціною цьому може бути недоступність застосунку якийсь час.
Щоб перетворювати довгі посилання на короткі, зручні для обміну.
Функціональні вимоги:
Нефункціональні вимоги:
Бонус: збір аналітики, API для розробників.
Щоб ділитися кодом і шукати в ньому помилки разом.
Функціональні вимоги:
Нефункціональні вимоги:
Щоб при введенні перших букв запиту пропонувалися варіанти доповнення.
Функціональні вимоги:
Нефункціональні вимоги:
Бонус: враховувати минулу історію запитів, профіль користувача, контекст тощо.
Щоб зберігати файли в хмарі та мати до них доступ з різних пристроїв.


Функціональні вимоги:
Нефункціональні вимоги:
Щоб ділитися фотографіями їжі та себе у дзеркалі.
Функціональні вимоги:
Нефункціональні вимоги:
Щоб від спілкування Вас відволікали роботою.
Функціональні вимоги:
Нефункціональні вимоги:
Бонус: стікери, групові чати, сторіз 🙈, тощо
Щоб почитати чергову маячню Маска і що з цього приводу думає цивілізований світ.



Функціональні вимоги:
Нефункціональні вимоги:
Бонус: пошук, реплаї, гарячі теми, повідомлення, рекомендації, аватарки з NFT мавпами.
Щоб подивитися Гаррі Поттера перед Різдвом.
Функціональні вимоги:
Нефункціональні вимоги:
Бонус: жанри, популярне, вибране, списки на подивитися потім.
Щоб не їсти їжу з жовтих сумок.
Функціональні вимоги:
Нефункціональні вимоги:
Бонус: фільтри за категоріями, рекомендації нових закладів.
Щоб не їздити на маршрутках.
Функціональні вимоги:
Нефункціональні вимоги:
Бонус: оцінки водіям, оцінки пасажирам, пояснення ціноутворення.
Після збору первинних вимог до системи дуже важливо оцінити необхідну інфраструктуру для розгортання і підтримки системи, а також вартість усього обладнання і процесів.
Від того, наскільки точним буде розрахунок, залежатиме успіх проєкту і його життєздатність, а найголовніше - чи вистачить у замовника матеріальних ресурсів, щоб втілити всі сформульовані побажання і вимоги до системи.
Оцінка дасть змогу скоригувати очікування від продукту.
На цій стадії проєктування ми оцінюємо з різних сторін яке навантаження може бути на систему.
Чи є якісь перекоси у бік читання або запису і яке залізо або інтернет-канал може знадобитися для передачі необхідної кількості даних.
flowchart LR A[User] --> B((Internet)) B --> C[Service] C --> D((Network)) D --> E[(Storage)] style A fill:#5cb85c style B fill:#5bc0de style C fill:#d9534f style D fill:#5bc0de style E fill:#428bca
Щоб розрахувати необхідний обсяг трафіку, потрібно оцінити потенційну аудиторію системи та підрахувати загальну кількість користувачів.
Якщо це якась закрита система для внутрішнього користування організації - кількість користувачів оцінюємо, виходячи з поточного штатного розкладу та обов’язків співробітників. Також можна закласти відсоток розширення персоналу, щоб врахувати приріст користувачів у майбутньому.
Якщо майбутня система це загальнодоступний ресурс - соціальна мережа або інший сервіс, тоді для приблизної оцінки можна проаналізувати метрики найближчих конкурентів.
Виходячи з кількості потенційних користувачів, далі можна оцінити час роботи користувачів у системі на день/місяць, оцінити обсяг контенту, що генерується і споживається під час роботи, а також обсяг місця на жорстких дисках під зберігання цього контенту.
Мережеве навантаження складається з кількості одночасно утримуваних з’єднань і загального обсягу трафіку, який проходить через мережу за одиницю часу.
З мережевого навантаження на сервіс можна вивести загальну вартість трафіку.
Хмарні провайдери беруть плату переважно за вихідний трафік: від $0.01 (між зонами доступності) до $0.1 (в інтернет) за 1 ГБ. Вхідний трафік зазвичай безкоштовний.
Під обчислювальним навантаженням зазвичай мається на увазі кількість запитів користувачів до сервісу за секунду. Цей показник вимірюється в RPS (requests per second).
Залежно від операції, з якою користувач звертається до сервісу, обчислювальне навантаження помітно різниться, тому показники рахують для групи операцій, наприклад, окремо для операції на отримання текстових даних, окремо для читання з БД і окремо для запису в БД.
Обчислювальне навантаження на старті, звісно, оцінити найскладніше.
Природним чином воно залежатиме від складності створюваної нами системи. Але на якийсь порядок цифр для простих сценаріїв можна орієнтуватися за бенчмарками TechEmpower Web Framework Benchmarks
За грубою оцінкою можна виходити з того, що в простих сценаріях у хмарі ми зможемо витримувати навантаження в 100k RPS для текстових даних, 10k RPS на читання і 1k RPS на запис у БД.
За наявності потужних фізичних серверів у тих самих сценаріях можна прикидати ймовірне навантаження в 500k RPS для текстових даних, 50k RPS на читання і 5k RPS на запис у БД.
Реальні характеристики системи, звісно ж, виявлятимуться вже під час тестувань
Оцінивши кількість створюваного контенту з боку користувачів, ми можемо прикинути скільки місця він займатиме, який постійний приріст при цьому очікується і, відповідно, скільки того чи іншого заліза нам знадобиться для нашої системи.
Найпоширеніші види сховищ і значення показників їхньої швидкості обробки даних, а також вартість зберігання даних:
Найпоширеніші види сховищ і значення показників їхньої швидкості обробки даних, а також вартість зберігання даних:
У середньому зберігання 1 ТБ обійдеться приблизно в $10000 в RAM, $300 на SSD і $30 на HDD.
Для оцінок можна вважати, що в одному сервері буде близько 1 ТБ RAM, 50 ТБ SSD або 200 ТБ HDD.
Якщо дисків багато, у гру вступає і річний рівень відмов (Annualized Failure Rate, AFR) — близько 1–2% дисків на рік.
Один з важливих факторів для системи — це час/затримка відповіді або latency.
В деяких сценаріях вона буде визначатися швидкістю мережі/диску, але можуть бути й інші причини.
У 2007 році відомий інженер Jeff Dean з Google у лекції для студентів Стенфорда навів час виконання різних операцій на різних пристроях:
0.5 ns5 ns7 ns100 ns100 ns10 000 ns20 000 ns250 000 ns500 000 ns10 000 000 ns10 000 000 ns30 000 000 ns150 000 000 nsПримітка
Ті самі операції графічно, але з пізніше уточненими значеннями (наприклад, mutex — 25 ns, читання 1 МБ з диска — 20 ms) і доданими SSD:
На які показники варто орієнтуватися під час розрахунків навантаження на систему:
Для оцінок на одну машину беремо 1 TB RAM, 50 TB SSD або 200 TB HDD.
Звернень до сервісу в місяць: 100 * 100М = 10Млрд.
Навантаження на створення записів: 100М / (30 * 86400) ≈ 40 RPS. На читання: x100 = 4K RPS.
Якщо кожен запис займає 1 КБ, ми будемо генерувати трафік у 32 Мбіт/с1.
На горизонті 5 років ми будемо зберігати 100М * 5 * 12 = 6Млрд записів або 6 ТБ даних.
У підсумку, для такого навантаження достатньо і однієї робочої станції за декілька тисяч доларів.
Звернень до сервісу в місяць: 30 * 10 * 1М = 300 млн.
Навантаження на створення записів: 1М / (86400) ≈ 12 RPS. На читання: x10 = 120 RPS.
Якщо кожен запис займає 10 КБ, ми будемо генерувати трафік у 10 Мбіт/с.
На горизонті 5 років ми будемо зберігати 30М * 5 * 12 = 1.8 Млрд записів або 18 ТБ даних.
У підсумку, для такого навантаження достатньо і однієї робочої станції за декілька тисяч доларів.
Маємо: 50 символів на запит в середньому, тобто в 200 байт точно поміститься.
Всього на збереження 10 млн. унікальних запитів піде: 10 млн. * 200 байт = 2 ГБ.
Якщо припустити, що кожен день з’являється 5% нових унікальних запитів, то на горизонті 5 років ми будемо зберігати індекс розміром 2 ГБ + 2 ГБ * 0.05 * 365 * 5 ≈ 185 ГБ.
У підсумку, для такого навантаження достатньо і однієї робочої станції за декілька тисяч доларів.
Мережа: на оновлення 100 млн. * 100 кБ = 10 ТБ трафіку в день, 10 ТБ / 86 400 сек ≈ 1 Gbps, 10 ТБ * ≈ 2 тис. днів ≈ 20 PB за 5 років, відкрито 10 тис. з’єднань.
Обчислення: необхідно писати 100 млн. записів в день = 1 тис. RPS з записами до БД.
Сховище: всього зберігаємо 1 млрд. * 100 * 100 кБ = 10 PB, тобто 50 серверів з 200 TB HDD кожен.
Вартість: синхронізація змін на інші пристрої дасть щонайменше 20 PB вихідного трафіку, тобто від $2 млн., на зберігання 10 PB HDD потрібно $300 тис.
На датаноди нам знадобиться до 100 серверів, з’єднання і трафік витримає і один сервер, але краще більше.
Підтримка всієї системи обійдеться в декілька млн. доларів на горизонті 5 років.
Мережа:
Обчислення: 1 тис. RPS на запис фото, 100 тис. RPS на читання.
Сховище: всього зберігаємо 20 PB фото, тобто 100 серверів з 200 TB HDD кожен.
Вартість: на зберігання 20 PB HDD потрібно $600 тис., а віддача фото (100 Gbps ≈ 2 EB за 5 років) за прайсом $0.1/GB коштувала б ≈ $200 млн.
На датаноди нам знадобиться від 100 серверів, на з’єднання, трафік та читання БД — ще десятки.
Сервери та сховище обійдуться в декілька млн. доларів на горизонті 5 років, а фото вигідніше роздавати через CDN.
Мережа:
Обчислення: 100 тис. RPS на запис повідомлень, 1 млн. RPS на читання.
Сховище: всього зберігаємо 20 PB повідомлень, тобто 100 серверів з 200 TB HDD кожен.
Вартість: на зберігання 20 PB HDD потрібно $600 тис., вихідний трафік на читання (10 Gbps ≈ 200 PB за 5 років) обійдеться у $20 млн.
Знадобляться сотні серверів: і для датанод, і для підтримки з’єднань, і для записів у БД.
Підтримка всієї системи обійдеться в десятки млн. доларів на горизонті 5 років.
Мережа:
Обчислення: 1 тис. RPS на запис повідомлень, 10 тис. RPS на читання + JOIN та алгоритмічна стрічка.
Сховище: всього зберігаємо 2 PB повідомлень, тобто 10 серверів з 200 TB HDD кожен.
Вартість: вихідний трафік на читання (1 Gbps ≈ 20 PB за 5 років) обійдеться у $2 млн., на зберігання 2 PB HDD потрібно $60 тис.
На датаноди нам знадобиться десятки серверів + сервери для обчислень і допоміжні сервери.
Підтримка всієї системи обійдеться в декілька млн. доларів на горизонті 5 років.
Мережа: відео 1080p потребує ≈ 5 Mbps; за день 10 млн. * 4000 сек * 5 Mbps = 200 Pb ≈ 25 PB, тобто в середньому ≈ 2 Tbps (2 000 Gbps 😧).
Обчислення: 10 млн. * 10 переглядів / 100 000 сек. = 1 тис. RPS на отримання метаданих між серіями.
Сховище: 20 000 найменувань по 10 годин (фільми, але і серіали): 20 тис. * 10 * 4000 сек * 10 Mbps = 8 Pb ≈ 1 PB = 1 тис. TB на одну якість відео.
Вартість: сховище навіть з десятками копій у різних якостях — до кількох мільйонів доларів, а мережа — мільярди: 25 PB * ≈ 2 тис. днів ≈ 50 EB, тобто ≈ $5 млрд. 😮.
За трафік по стандартному прайсу розплатитися неможливо, тому Netflix має власні CDN (мережі дистрибуції контенту).
ihor.miroshnychenko@kneu.ua