Програмна архітектура та проектування систем: загальна картина та путівник по ресурсах

Вітаю колеги.

Сьогодні на ваш суд пропонується переклад статті Тугберка Угурлу (Tugberk Ugurlu), який взявся порівняно невеликий обсяг викласти принципи проектування сучасних софтверних систем. Ось що автор повідомляє про себе у сухому залишку:

Програмна архітектура та проектування систем: загальна картина та путівник по ресурсах
Оскільки рішуче неможливо охопити в хабростаті таку колосальну тему, як архітектурні патерни + патерни проектування станом на 2019 рік, рекомендуємо не лише сам текст пана Уруглу, а й численні посилання, які він люб'язно розставив. Якщо вам сподобається - опублікуємо і більш вузькоспеціальний текст про проектування розподілених систем.

Програмна архітектура та проектування систем: загальна картина та путівник по ресурсах

Знімок Айзека Сміта із сайту Unsplash

Якщо вам ніколи не доводилося стикатися з такими викликами, як проектування системи з нуля, то, приступаючи до такої роботи, іноді навіть не зрозуміло, з чого почати. Я вважаю, що спочатку потрібно окреслити кордони, щоб більш-менш упевнено уявляти, що саме ви збираєтеся спроектувати, а потім закатати рукави і працювати, не виходячи за ці кордони. Як відправна точка можна взяти якийсь продукт або сервіс (в ідеалі – такий, що вам дуже подобається) і розібратися в його реалізації. Можливо, ви вразитеся, наскільки просто виглядає даний продукт, і яка величезна складність у ньому насправді прихована. Не забувайте: просте - зазвичай складне, і це нормально.

Думаю, найкраща порада, яку я можу дати тим, хто приступає до проектування системи, така: не допускайте жодних припущень! Із самого початку потрібно конкретизувати факти, відомі про цю систему, та пов'язані з нею очікування. Ось кілька добрих питань, відповіді на які допоможуть вам приступити до проектування:

  • Яка проблема, яку ми намагаємось вирішити?
  • Яка пікова кількість користувачів, які взаємодіятимуть із нашою системою?
  • Які патерни запису та зчитування даних у нас будуть використовуватися?
  • Якими є очікувані випадки відмов, як ми збираємося з ними справлятися?
  • Які очікування висуваються до узгодженості та доступності системи?
  • Чи доводиться враховувати під час роботи якісь вимоги, пов'язані із зовнішньою перевіркою та регламентацією?
  • Які різновиди конфіденційних даних ми збираємось зберігати?

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

Задаємо вихідний рівень

Що розумію тут під «вихідним рівнем» (baseline)? Власне, в наш час більшість проблем у софтверній індустрії «можна» вирішити за допомогою вже наявних методів і технологій. Відповідно, орієнтуючись у цьому ландшафті, ви отримуєте певну фору, зіштовхуючись із завданнями, які комусь доводилося вирішувати до вас. Не забуваємо, що програми пишуться для вирішення проблем бізнесу та користувачів, тому ми прагнемо вирішити завдання найпрямішим і найпростішим (з погляду користувача) способом. Чому про це потрібно пам'ятати? Можливо, вам у вашій системі координат подобається підшукувати для всіх завдань унікальні рішення, тому що ви вважаєте, «який же я програміст, якщо всюди прямую патернам»? Насправді, мистецтво тут полягає у прийнятті рішень про те, де і що робити. Зрозуміло, кожному з нас іноді доводиться стикатися з унікальними проблемами, кожна з яких – справжній виклик. Однак, якщо наш вихідний рівень чітко окреслено, то ми знаємо, на що витрачати сили: на пошук готових варіантів вирішення поставленої перед нами завдання, або на її подальше вивчення та глибше розуміння.

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

Добре, то з чого ж почати? У Донна Мартіна є репозиторій на GitHub під назвою system-design-primer, за матеріалами якого ви зможете навчитися проектування великомасштабних систем, а також підготуватися до співбесід на цю тему. У репозиторії є розділ із прикладами реальних архітектурде, зокрема, розглянуто, як підходять до дизайну своїх систем деякі добре відомі компаніїнаприклад, Twitter, Uber, т.д.

Однак, перш ніж переходити до цього матеріалу, давайте докладніше розберемося з найважливішими архітектурними викликами, з якими доводиться стикатися практично. Це важливо, оскільки доводиться конкретизувати безліч аспектів неподатливої ​​та багатогранної проблеми, а потім вирішувати її в рамках регламентації, що діє в даній системі. Джексон Габбард, колишній співробітник Facebook, записав 50-хвилинне відео про співбесіди, присвячені проектуванню систем, де поділився власним досвідом із огляду сотень претендентів. При тому, що відео виразно стосується проектування великих систем і критеріїв успішності, важливих при підшукуванні кандидата на таку позицію, воно все ж таки стане вичерпним ресурсом про те, які речі найбільш важливі при проектуванні систем. Також пропоную короткий зміст цього відео.

Напрацьовуйте знання про зберігання та вилучення даних

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

Бази даних вважатимуться структурами даних, яким властива виняткова масштабованість і довговічність. Тому знання структур даних має вельми знадобитися і при виборі тієї чи іншої бази даних. Наприклад, Redis - Це сервер структур даних, що підтримує різні види значень. Він дозволяє працювати з такими структурами даних як списки та множини, зчитувати дані за допомогою загальновідомих алгоритмів, наприклад, LRU, організуючи таку роботу у довговічному та високодоступному стилі.

Програмна архітектура та проектування систем: загальна картина та путівник по ресурсах

Знімок Семюела Зеллера із сайту Unsplash

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

Зрештою, завершуючи розмову про питання зберігання даних, слід згадати і про кешування. Чи повинно воно виконуватись одночасно на клієнті та на сервері? Які дані будуть у вашому кеші? І чому? Як ви організуєте інвалідність кешу? Чи проводитиметься вона регулярно, через певні проміжки часу? Якщо так – то як часто? Опрацювання цих тем рекомендую почати зі наступного розділу вищезгаданого букваря з проектування систем.

Комунікаційні патерни

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

Необхідно забезпечити комунікацію цих ресурсів один з одним, а також обмін інформацією між усією системою та зовнішнім світом. У контексті проектування систем тут ми знову ж таки стикаємося з набором нових унікальних викликів. Розбираємось, чим можуть бути корисні асинхронні потоки завдань, і які рРізноманітні патерни комунікації є в наявності.

Програмна архітектура та проектування систем: загальна картина та путівник по ресурсах

Знімок Тоні Стоддарда із сайту Unsplash

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

Розподіл з'єднань

Не впевнений, що винесення цієї теми до самостійного розділу всім видасться виправданим. Проте, розгорнуто викладу тут цю концепцію, причому, вважаю, що матеріал цього розділу найточніше описується терміном «розподіл з'єднань» (connection distribution).

Системи формуються шляхом правильного з'єднання безлічі компонентів, та його комунікація друг з одним найчастіше організується з урахуванням усталених протоколів, наприклад, TCP і UDP. Однак цих протоколів як таких часто недостатньо для задоволення всіх потреб сучасних систем, які часто експлуатуються під високим навантаженням, а також залежать від потреб користувачів. Часто буває необхідно шукати способи розподілу з'єднань, щоб справлятися з такими високими навантаженнями у системі.

В основі такого розподілу лежить добре відома система доменних імен (DNS). Така система дозволяє перетворити доменне ім'я, наприклад зважений циклічний алгоритм (weighted round robin) і методи на основі затримок, що допомагають розподіляти навантаження.

Балансування навантаження принципово важлива, і практично будь-яка велика система в Інтернеті, з якою нам сьогодні доводиться мати справу, розташована за одним чи декількома балансувальниками навантаження. Балансувальники навантаження допомагають розподіляти запити клієнтів по безлічі доступних інстансів. Балансувальники навантаження бувають як апаратними, так і програмними, проте, на практиці частіше доводиться мати справу з програмними, наприклад, HAProxy и ELB. Зворотні проксі концептуально також дуже схожі на балансувальники навантаження, хоча між першими і другим є ряд виразних відмінностей. Ці відмінності обов'язково слід враховувати, проектуючи систему з урахуванням ваших потреб.

Також слід знати про мережах доставки контенту (CDN). CDN – це глобальна розподілена мережа проксі-серверів, що доставляє інформацію з тих вузлів, які розташовані географічно ближче до конкретного користувача. Мережі CDN краще використовувати, якщо ви працюєте зі статичними файлами, написаними на JavaScript, CSS та HTML. Крім того, сьогодні поширені такі хмарні сервіси, в яких надаються диспетчери трафіку, наприклад, Менеджер трафіку Azure, які забезпечують глобальний розподіл і знижені затримки при роботі з динамічним контентом. Однак, такі послуги зазвичай корисні в тих випадках, коли доводиться працювати з веб-сервісами без збереження стану.

Поговоримо про бізнес-логіку. Структурування бізнес-логіки, потоків завдань та компонентів

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

Як відомо з назви цієї статті, я збирався розповісти в ній про софтверну архітектуру та проектування систем. Відповідно, я не планував висвітлювати патерни проектування програмного забезпечення, які описують, як створюються програмні компоненти. Проте, чим більше я про це розмірковую, тим більше мені здається, що межа між патернами проектування ПЗ та архітектурними патернами дуже розмита, і ці дві концепції тісно пов'язані. Візьмемо, наприклад, реєстрацію подій (event sourcing). Варто взяти на озброєння цей архітектурний патерн - і він вплине практично на всі аспекти вашої системи: довготривале зберігання даних, рівень узгодженості, прийнятий у вашій системі, обриси компонентів в ній, і т.д., і т.п. Тому я вирішив згадати деякі архітектурні патерни, які безпосередньо стосуються бізнес-логіки. Нехай навіть у цій статті доведеться обмежитися простим списком, рекомендую вам познайомитися з ним та обміркувати ідеї, пов'язані з цими патернами. Ось будь ласка:

Колаборативні підходи

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

Програмна архітектура та проектування систем: загальна картина та путівник по ресурсах

Знімок Калейдіко із сайту Unsplash

У першу чергу потрібно виробити точне і загальновизнане уявлення про те, якою є та бізнес-мета, яку ви намагаєтеся досягти, і з якими рухомими елементами при цьому доведеться мати справу. Прийоми групового моделювання, зокрема, штурм подій (event storming) допомагають значно прискорити цей процес та підвищують ваші шанси на успіх. Цією роботою можна зайнятися до того чи після того, як ви окреслите межі ваших сервісів, а потім поглиблювати його у міру дозрівання продукту. Спираючись на той рівень узгодженості, що буде досягнуто тут, ви також можете сформулювати єдина мова для того обмеженого контексту, у якому працюєте. Коли потрібно буде розповідати про архітектуру вашої системи, для цього вам може стати в нагоді модель C4, запропонована Саймоном Брауном, особливо коли потрібно зрозуміти, наскільки вам доведеться заглиблюватися в деталі проблеми, візуалізуючи речі, які ви хочете повідомити.

Ймовірно, у цій темі знайдеться й інша зріла технологія, не менш корисна, ніж предметно-орієнтоване проектування. Однак, ми так чи інакше повертаємося до розуміння предметної галузі, тому знання та досвід у сфері предметно-орієнтованого проектування повинні вам стати в нагоді.

Джерело: habr.com

Додати коментар або відгук