Проєктуємо вебсайт із гібридною розподіленою архітектурою
Традиційна монолітна архітектура найвідоміша через свою найбільшу поширеність серед вебсайтів. Відносно недавно почала набувати великої популярності мікросервісна. А от про інші рішення, які займають проміжне місце між монолітною та мікросервісною, інформації дуже мало, через що я і вирішив написати цю статтю.
Розподілена архітектура
Спочатку був моноліт, і це було добре. Всі частини вебсайту (код, зображення, БД тощо), структуровані певним чином, розміщувались на одному сервері. Але з часом на популярних вебсайтах кількість даних та запитів збільшувалась, і навіть найпотужніші сервери не встигали їх вчасно опрацьовувати. Тоді виникла думка фізично розділити вебсайт на окремі більш незалежні частини та розподілити їх по окремих серверах. Таким чином виникла розподілена архітектура, яка задовольняє потреби більшості високонавантажених вебсайтів.
Нішеве позиціювання архітектур
Централізоване розташування компонентів в проєктах з монолітною архітектурою дає можливість легше вносити в них зміни. Їх розвиток обмежений використанням лише вертикального масштабування в межах одного фізичного сервера. Відповідно для їх діяльності необхідна менша кількість серверів та працівників. Через ці фактори монолітна архітектура найкраще підходить для низьконавантажених проєктів (зелений). А оскільки їх кількість найбільша з-поміж усіх архітектур — ця архітектура є найпоширенішою.
Поділ вебсайту на малі частини з власними БД, розвитком кожного з яких займається окрема команда, типове рішення для проєктів з мікросервісною архітектурою. А розподіл мікросервісів по окремих серверах надає надзвичайно великі можливості для горизонтального масштабування. Водночас створює велику складність з підтримки, через що її доцільно використовувати лише на максимально навантажених проєктах (червоний). Оскільки подібних проєктів відносно небагато на практиці, дане рішення використовується не часто.
Збалансована гібридна розподілена архітектура займає проміжне місце між проєктами з монолітною та мікросервісною архітектурами. Вона використовується на вебсайтах середньої завантаженості (помаранчевий), частіше за мікросервісну, але водночас рідше за монолітну. Для її підтримки необхідна середня кількість серверів та персоналу.
Розподілений моноліт
Сама назва «розподілений моноліт» є загальною й означає архітектуру, при якій виконання програми з монолітною архітектурою розподіляють на різні вузли. Реалізувати такий підхід можливо багатьма різними способами. Але з набуттям популярності мікросервісної архітектури авторитетні програмісти необачно використали цю назву для позначення одного з її антипатернів — спроби неефективної реалізації цієї архітектури. В ній проєкт з однієї сторони поділений на окремі мікросервіси, а з іншої — залишає внутрішні зв’язаності між ними як в моноліті. На превеликий жаль відтоді ця назва абсолютно несправедливо отримала негативне забарвлення в контексті мікросервісів й активно з ним популяризується в спеціалізованих технічних статтях.
Microservices Antipattern: The Distributed Monolith
Також мікросервіси дуже часто протиставляють моноліту як ледь не єдиний шлях горизонтального масштабування проєкту і лише через архітектуру модульного моноліту. Тим самим вони суттєво звужують можливі проміжні варіанти інших архітектур між двома крайностями. Зверніть увагу, що це далеко не єдині архітектури для вебсайтів, але вони найвідоміші та найпоширеніші.
З маркетингових міркувань, через несправедливу дискримінацію та дискредитацію зрозумілого терміну «розподілений моноліт», я вимушений використовувати альтернативну для неї назву — гібридна розподілена архітектура. А через суттєву розподіленість моноліту на багатьох різних рівнях вебсайту я б назвав її навіть архітектурою мультирозподіленого моноліту.
Еволюція розподілення
В тих поодиноких випадках, коли заздалегідь достеменно відомо, що проєкт буде дуже високонавантаженим і один сервер з ним не впорається, відразу підбирають бажану для нього розподілену архітектуру, наприклад мікросервісну. Але в більшості реальних випадках розвиток як самого проєкту, так і його архітектури відбувається еволюційним шляхом за принципом «від простого до складного». На практиці це означає, що для вебсайту спочатку використовують просту монолітну архітектуру, а в міру його розвитку — частини моноліту поступово розподіляють на різні вузли. При цьому комбінують різні підходи з метою пошуку збалансованого рішення для оптимального використання наявних ресурсів.
Розподіл БД монолітного вебсайту на окремий сервер з можливою реплікацією
Найперше, що зробить програміст коли для роботи типового монолітного вебсайту почне бракувати обчислювальних ресурсів одного сервера — перенесе на окремий сервер БД. Якщо прийняти, що БД вебсайту є його обов’язковою невіддільною частиною, необхідною для його повноцінної роботи, то таку архітектуру вже можна сміливо назвати розподіленим монолітом. А на професійних вебсайтах, за необхідності, можливо відразу легко розподілити саму БД на декілька серверів, реалізувавши її горизонтальне масштабування з балансуванням (реплікація, шардінг тощо). Через те, що більшість вебсайтів за своєю суттю є зручними інтерфейсами між користувачем та БД (WUI — Web User Interface), зазвичай такого підходу вистачає для розв’язання проблеми.
Розподіл файлів монолітного вебсайту на окремий сервер з можливою реплікацією
Друге, що зробить програміст — відокремить програмно та фізично на окремий сервер сховище файлів, зазвичай зображень. Якщо додатково реалізувати на ньому API, за допомогою якого можна додавати, зчитувати та видаляти файли та зберігати їх метадані у своїй незалежній БД, він перетвориться на справжній мікросервіс. А якщо є необхідність, можливо додатково також реалізувати його горизонтальне масштабування на декілька серверів з балансуванням (реплікація, шардінг тощо).
Розподіл коду монолітного вебсайту на frontend та backend
При використанні на проєкті відповідних технологій на зразок Node.js та React, цілком природньо спробувати розподілити frontend та backend. Зверніть увагу, що розподіляти моноліт можна не тільки на сервери, а на вузли — будь-які обчислювальні пристрої. І з погляду масштабування перенесення виконання частини функцій вебсайту на сторону клієнта, наприклад процес генерації вебсторінки, нічим не відрізняється від його перенесення на окремий сервер в дата-центрі.
Розподіл коду монолітного вебсайту на великі частини
Наступний приклад розподілення складніший та ефективніше працює в парі з розподіленням БД і сховища файлів. Вебсайти зазвичай складаються з декількох основних частин, різних за призначенням. Наприклад, з головної частини, за допомогою якої користувачі взаємодіють з вебсайтом, отримуючи необхідну інформацію. Або з адміністративної частини — панель керування, в якій редактори вебсайту додають, змінюють чи видаляють дані. Хоча вони програмно дещо відрізняються, в більшості випадків фізично розташовуються на одному сервері в одній спільній директорії та мають між собою певний рівень зв’язаності.
Але на професійних вебсайтах їх можливо розподілити по окремих серверах. Наприклад, панель керування (Panel) через низьке навантаження можливо розташувати на одному сервері з головною версією реплікованої БД (primary). А от головну частину вебсайту (Main) через високе навантаження можливо розмістити на окремому сервері, всі вільні ресурси якого задіяні для проміжного кешуванням даних та генерації вебсторінок. Вторинні версії масштабованої БД (secondary) треба розташувати фізично кожен на окремому сервері з балансуванням залежно від завантаженості. Аналогічно можна окремо розташувати частину вебсайту, яка відповідає за роботу зі зображеннями (Image).
Розподіл даних монолітного вебсайту вебсервісах
Також варто згадати про концепцію Mashup з Web 2.0, при якій вебсайт для своєї діяльності використовує інші незалежні вебсервіси (Google Analytics, Google AdSense, Google Map, Youtube, Facebook, Twitter тощо). А оскільки ці сервіси розміщені на зовнішніх ресурсах (вузлах) та одночасно є важливою частиною нашого вебсайту, подібний підхід на загальному рівні також можна віднести до розподілення моноліту.
Розподіл статичних даних монолітного вебсайту через CDN
Наостанок маю згадати про практику кешування статичних копій сторінок монолітного вебсайту за допомогою мереж CDN на зразок CloudFlare, яку теж можна віднести до архітектури розподіленого моноліту. Так само як і розміщення на зовнішніх серверах цих мереж службових файлів вебсайтів, тобто знову ж таки — розподілу власних даних по інших вузлах.
Гібридна розподілена архітектура
Як ви могли переконатись, між монолітною та максимально масштабованою архітектурою на зразок мікросервісної існують багато проміжних підходів для часткового розподілення монолітного вебсайту. Всі ці підходи давно відомі, перевірені часом та добре себе зарекомендували. А тепер зведімо всі попередньо наведені мною інгредієнти в одну страву, приправимо її деяким спеціями та поглянемо на результат.
Попри можливість горизонтального масштабування вебсайту з гібридною розподіленою архітектурою більшість його частин, окрім клієнтського фронтенду та незалежних вебсервісів, можливо використовувати на одному сервері. Така мінімалістична конфігурація буде корисна для середньонавантажених проєктів, що планують швидко розвиватись. При цьому не будуть задіяні переваги розподіленості для масштабування системи, які можуть бути не затребувані на даному етапі її розвитку. Додатково подібний спосіб організації можна використати для головної репліки усього вебсайту, зображений нижче в максималістичній конфігурації гібридного розподілу.
Програмістам, які локально працюють з вебсайтом на своїх робочих комп’ютерах, також буде корисний такий підхід. Якщо існує потреба, наприклад, для тестування змін коду перед публікацією, різні частини вебсайту також можна використовувати на окремих віртуальних машинах, розміщених на одному фізичному сервері. Зрештою централізоване використання достатнє для демонстрації своїх можливостей проєкту, щоб кожен бажаючий міг запустити його локально для ознайомлення.
Натомість для оптимальної конфігурації гібридної розподіленої архітектури вебсайту необхідно задіяти хоча б декілька окремих серверів. В першу чергу подібне горизонтальне масштабування дає можливість витримувати значно більші навантаження. Додатково така організація компонентів системи дає можливість краще оптимізувати апаратні конфігурації самих серверів для конкретних потреб. Зверніть увагу, що подібну схему можливо також реалізувати на віртуальних серверах, розміщених на окремих фізичних серверах з різними технічними характеристиками.
Наприклад, сервер A, призначений для обслуговування потреб редакторів вебсайту, не створює великих навантажень, тому для його роботи достатньо малопотужного дешевшого сервера з використанням HDD-накопичувача. Натомість на сервер B навпаки припадає найбільше навантаження, через що для нього доцільно задіяти потужний та дорогий сервер з шиною NVMe для SSD накопичувача. Сервер C може потребувати середнього за потужністю та ціною сервера зі звичайним SATA SSD.
На цій схемі зображено приклад теоретичної максималістичної конфігурації гібридної розподіленої архітектури вебсайту. В ній реалізована ще краща масштабованість через розподіл вебсайту на ще більшу кількість серверів, розташованих в географічно віддалених дата-центрах. Також значно підвищена відмовостійкість всієї системи шляхом дублювання критичних вузлів. Разом з цим значно збільшилась складність та вартість її підтримки, через що в більшості випадків немає потреби відразу реалізовувати проєкт саме в такому вигляді. Краще поступово, попередньо визначаючи слабкі місця системи, розподіляти частини моноліту відповідно до зростання його навантаження, створюючи тим самим власну індивідуальну конфігурацію проєкту.
Переваги та недоліки
Переваги гібридної розподіленої архітектури відносно монолітної я вже згадував раніше в статті, але варто ще раз зібрати їх в одному місці. По-перше, розподілення моноліту по вузлах дає можливість горизонтально її масштабувати та, як наслідок, витримувати значно більші навантаження. По-друге, дублювання важливих розподілених вузлів збільшує її надійність. По-третє, цей підхід дає можливість краще оптимізувати апаратну частину вузлів для виконання спеціалізованих завдань. Додатковим бонусом є спрощення рефакторингу окремих частин коду моноліту, за винятком поодиноких ситуацій, коли вони взаємодіють між собою. Недоліками відносно монолітної організації вузлів є додаткові витрати ресурсів на підтримку більшої кількості вузлів та взаємодію між ними.
Відносно мікросервісної архітектури все навпаки. Перевагою гібридної розподіленої архітектури є менші витрати ресурсів на підтримку значно меншої кількості вузлів та взаємодію між ними. Основним недоліком є суттєво менші можливості масштабування і, відповідно, витримування менших навантажень. Додатковий недолік — відносно складніший рефакторинг великих окремих частин коду на вузлах.
Властивості | Моноліт | Гібридна | Мікросервіси |
Розмір проєкту | Малий | Середній | Великий |
Навантаження проєкту | Мале | Середнє | Велике |
Складність розробки | Низький | Середній | Високий |
Складність тестування | Низька | Середня | Висока |
Кількість працівників | Мала | Середня | Велика |
Керування працівниками | Просте | Середня | Складне |
Цілісність даних | Висока | Середня | Низька |
Швидкість реакції | Висока | Середня | Низька |
Внутрішні залежності | Великі | Середні | Низькі |
Можливість масштабування | Низька | Середня | Висока |
Максимальна продуктивність | Низька | Середня | Висока |
Зазвичай порівнюючи різні архітектури на зразок моноліту чи мікросервісів за приклад беруть однаковий тип проєкту з одним і тим самим розміром та навантаженням. Але я вважаю подібний підхід абсолютно неінформативним через фундаментально різні призначення архітектур. Через це в таблиці вище я порівняв три різні архітектури для трьох сайтів однакового типу водночас з різними розмірами та навантаженнями.
Приклад реалізації
MediaCMS — безплатна система керування вмістом для професійних високонавантажених інтернет-видань з відкритим початковим кодом, розміщеним на сервісі GitHub. Її монолітний за стилем програмний код розподілений на три великі частини, кожна з яких може розміщуватись на окремому сервері. При розподіленому використанні ці частини, сервера БД, сховища зображень, фронтенд та вебсервіси утворюють гібридну розподілену архітектуру вебсайту. Всі частини написані на JavaScript, серверна частина коду працює на Node.js з каркасом Express.js, авторизація здійснюється через jsonwebtoken.
MediaCMS Main — головна частина, призначена для виводу читачам наповнення вебсайту в зручному вигляді. Дані кешуються з допомогою пакунка lru-cache. Генерація сторінок реалізована на стороні сервера за допомогою шаблонізатора EJS з метою уникнення проблем з індексацією в пошукових системах. Для зберігання даних використовується MongoDB, яка може бути розміщена на окремому сервері (або її secondary
версії при реплікації).
MediaCMS Panel — панель керування, призначена для додавання, редагування чи видалення наповнення вебсайту, зокрема публікацій, які читачі переглядають на головній частині вебсайту. Код фронтенду реалізовано з використанням бібліотек React та Bootstrap, запакованого за допомогою Webpack, запити HTTP
виконуються через axios. Для зберігання даних використовується та сама MongoDB, що й для головної частини (або її primary
версія при реплікації). Також в неї інтегровано гібридний WYSIWYG-редактор, про який можна довідатись більше з попередньої моєї статті «Проєктуємо гібридний онлайн WYSIWYG-редактор для React».
MediaCMS Image — сховище зображень з власним REST API, мінімальні метадані зберігаються в БД Redis, файли кешуються з допомогою пакунка lru-cache. Приклад реалізації даного сервісу я описав в одній зі своїх попередніх статей «Автоматизуємо використання адаптивних зображень для вебсайтів за допомогою Node.js».
В даному проєкті реалізовані базові функції з метою перевірки працездатності (Minimum viable product — MVP). Його зручно використовувати як шаблон для створення власної версії інтернет-видання (fork
), при цьому максимально адаптовуючи під свої потреби. Він впроваджений та перевірений на реальних вебсайтах, довів на практиці свою надійність та здатність витримувати великі навантаження. Для реалізації повного функціоналу розглядається можливість створення платної професійної версії MediaCMS Pro.
Висновок
Дуже часто в статтях про мікросервісну архітектуру, яка використовується на відомих проєктах, авторитетні інженери ідеалізують її переваги та водночас нівелюють або взагалі замовчуються її недоліки. При цьому вони активно самостверджуються над монолітною архітектурою, забуваючи, що вона краще підходить для переважної більшості проєктів через свою простоту та дешевизну. Як наслідок у більшості читачів створюється хибна ілюзія про нову фантастичну технологію, здатну розв’язати всі їх проблеми на проєкті.
При написанні даної статті, попри концентрації переважно на одній архітектурі, я намагався бути об’єктивним та уникати ідеалізації чи дискримінації будь-яких інших архітектур. Кожна з них унікальна, має право на існування та займає певну нішу на ринку. А через перекриття недоліків однієї архітектури перевагами іншої вони всі разом задовольняють вимоги переважної більшості вебсайтів. Найголовніше правильно визначити, для якого проєкту яка архітектура краще підходить.
Гібридна розподілена архітектура вебсайту займає проміжне місце між монолітною та мікросервісною, охоплює різноманітні техніки, підходи та концепції з метою оптимального розподілу навантаження монолітної архітектури між різними вузлами найбільш ефективним способом. Вона буде корисною для більшості вебсайтів, які досягли фізичного обмеження вертикального масштабування для свого монолітного проєкту, розміщеного на одному сервері та водночас їм не доцільно переходити на значно складнішу мікросервісну архітектуру.
P.S. В момент публікації статті я знаходжуся в одному з навчальних центрів ЗСУ, відповідно не можу оперативно давати відповіді на питання в коментарях та перепрошую, що не встиг покращити контент на демо-сайті.
24 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів