Розробники часто віддають перевагу RPC через їх подібність до локальних викликів процедур, сприйняту ефективність та знайомі інструменти. Однак ця перевага може бути результатом непорозуміння принципів REST та його переваг у розподілених середовищах.
Хоча RPC може бути ефективним у тісно зв'язаних, критичних до продуктивності застосунках, REST зазвичай є кращим вибором для масштабованих, слабо зв'язаних та взаємодіючих додатків — особливо у великих або гетерогенних розподілених системах.
Давайте подивимося, чому REST і RPC такі різні.
Основою REST є обмеження розподілених обчислень, тоді як основа RPC — це імітація локальних викликів процедур. Це має глибокі наслідки для їх різниць у масштабованості, надійності, простоті та придатності для побудови розподілених систем.
Основи REST у контексті обмежень розподілених обчислень
REST було визначено спеціально для вирішення проблем та реалій розподілених систем. Його архітектурні обмеження тісно пов'язані з труднощами мережевих середовищ, такими як:
Затримка
- REST визнає, що мережеве спілкування inherently повільніше за локальне.
- Він оптимізує кількість взаємодій, роблячи їх самодостатніми, використовуючи стейтлесс (stateless) принципи та кешування.
- Приклад: Кешування відповідей на GET запити зменшує необхідність у повторних запитах до сервісу.
Часткові відмови
- REST розроблено для забезпечення стійкості до відмов у розподілених середовищах, де мережеві розділення та часткові відмови — це нормальна ситуація.
- Стейтлессність гарантує, що сервіси не потребують узгодження стану між вузлами, а клієнти можуть повторювати запити незалежно.
Масштабованість
- Стейтлессність REST і орієнтація на ресурси спрощують горизонтальне масштабування, що є критичним для розподілених систем з непередбачуваними навантаженнями.
- Приклад: Балансувальник навантаження може рівномірно розподіляти стейтлесс запити REST серед кількох серверів без урахування зв'язку із сесією.
Гетерогенність
- REST приймає гетерогенність розподілених систем, використовуючи універсальні стандарти (HTTP, URI, JSON тощо) для комунікації.
- Клієнти та сервіси можуть безперешкодно взаємодіяти, навіть якщо вони побудовані з різних технологій.
Незалежна еволюція
- Слабо зв'язана архітектура REST дозволяє клієнтам і сервісам розвиватися незалежно, якщо вони дотримуються визначених API контрактів.
- Гіпермедіа (HATEOAS) дозволяє створювати динамічні робочі процеси без необхідності, щоб клієнт мав попередні знання про всі можливі стани сервісу.
Імітація локальних викликів процедур у RPC
RPC, на відміну від REST, ґрунтується на парадигмі локальних викликів процедур, намагаючись абстрагувати складнощі розподілених систем. Хоча цей підхід може спростити програмування для розробників, він приносить значні труднощі в розподілених середовищах.
The assumptions behind RPC:
Прозорість
- RPC намагається зробити віддалені виклики ідентичними локальним викликам процедур, абстрагуючи мережеву комунікацію.
- Ця абстракція, хоча й зручна, приховує реальність мережевих затримок, часткових відмов і обмежень пропускної здатності.
Синхронна комунікація
- RPC часто передбачає синхронну, блокуючу комунікацію, що добре підходить для локальних викликів, але є проблемною в розподілених системах, де затримки або відмови є звичайним явищем.
Тісне зв'язування
- Системи RPC зазвичай тісно пов'язують клієнтів і сервіси через визначення методів та протоколи, ускладнюючи зміни і знижуючи гнучкість.
- Приклад: Зміна RPC методу часто вимагає оновлення та повторного розгортання як клієнта, так і сервісу.
Стан
- Багато реалізацій RPC покладаються на збереження стану сесії на стороні сервера — це ускладнює масштабування та відновлення після відмов.
Основні наслідки
Масштабованість
REST:
- Стейтлессність REST дозволяє будь-якому сервісу одного типу обробляти будь-який запит, що спрощує балансування навантаження та забезпечує безшовне горизонтальне масштабування.
- Кешування зменшує навантаження на сервери, дозволяючи проміжним елементам або клієнтам зберігати та повторно використовувати відповіді.
- REST спочатку проектувався для великих розподілених систем (як сама Мережа).
RPC:
- Станова взаємодія ускладнює масштабування, оскільки стан сесії потрібно управляти, синхронізувати або направляти на конкретні сервери.
- RPC не має вбудованих механізмів кешування, тому кожен виклик зазвичай потребує прямої взаємодії з сервісом.
- Масштабування систем на базі RPC часто вимагає складної реплікації стану або маршрутизації на основі афінності.
Стійкість до відмов
REST:
- Стейтлесс взаємодії та ідемпотентні операції (PUT, DELETE) гарантують, що клієнти можуть повторювати невдалі запити без порушення консистентності.
- REST приймає часткові відмови: клієнти можуть відновлюватися або повторювати запити незалежно, а кешування допомагає усунути проблеми під час тимчасових збоїв.
- Приклад: Якщо GET запит не вдався, клієнт може повторити той самий URI без ризику побічних ефектів.
RPC:
- Системи RPC часто виходять з ладу при часткових відмовах, оскільки клієнт припускає, що виклик є атомарним, як локальний виклик процедури.
- Повторні спроби ускладнюються можливими побічними ефектами (наприклад, частково виконаною транзакцією в базі даних).
- Мережеві помилки можуть порушити ілюзію локальності, що вимагає від розробників явного оброблення відмов.
Простота
REST:
- Використання REST універсальних стандартів (HTTP, JSON, URI) спрощує розробку та інтеграцію через різноманітні системи.
- Уніфікований інтерфейс знижує когнітивне навантаження на розробників: взаємодія з одним REST ресурсом концептуально така ж, як і взаємодія з іншим.
- Приклад: Розробник, що працює з GET /user, інтуїтивно розуміє, як взаємодіяти з GET /order.
RPC:
- Абстракція віддалених викликів як локальних спрощує початкову розробку, але створює складнощі при налагодженні, обробці помилок та масштабуванні.
- Тісне зв'язування між клієнтами і сервісами вимагає скоординованих оновлень, збільшуючи навантаження на обслуговування.
- Приклад: Додавання нового параметра до RPC методу часто вимагає перегенерації та повторного розгортання клієнтських заглушок.
Гнучкість
REST:
- Ресурсоорієнтоване проектування REST і контроль гіпермедіа (HATEOAS) дозволяють створювати динамічні робочі процеси та слабке зв'язування між компонентами.
- Клієнти можуть динамічно переміщатися між робочими процесами або знаходити нові ресурси через посилання, надані в відповідях.
- Приклад: Відповідь REST API на POST /ticket запит може містити посилання на GET /ticket/{id} для подальших дій.
RPC:
- Системи RPC жорстко зв'язані з попередньо визначеними методами, що робить робочі процеси жорсткими та важкими для адаптації до змінюваних вимог.
- Клієнти повинні знати всі доступні методи та їх параметри заздалегідь, що обмежує гнучкість.
- Приклад: Додавання нового етапу робочого процесу може вимагати визначення нового RPC методу та оновлення всіх клієнтів.
Налагодження та обслуговування
REST:
- Налагодження взаємодій у REST простіше, оскільки HTTP запити та відповіді читаються людиною і використовують стандартні інструменти (як-от curl, Postman).
- REST API самодокументовані, з чіткими представленнями ресурсів та HTTP статус-кодами, які вказують на успіх або невдачу.
RPC:
- Взаємодії RPC складніше налагоджувати через непрозорі формати серіалізації (Protocol Buffers!) та складні транспортні протоколи.
- Помилки часто вимагають аналізу низькорівневих мережевих трас чи специфічних логів протоколу.
Висновок
REST природно є кращим вибором для розподілених систем, оскільки він чітко враховує обмеження розподілених обчислень: затримки, часткові відмови, масштабованість і гетерогенність.
Натомість, спроба RPC імітувати локальні виклики абстрагує ці обмеження, що часто призводить до систем, які важче масштабувати, менш стійкі до відмов і більш жорсткі.
Хоча RPC може бути підходящим для строго контрольованих середовищ, гнучкість і стійкість REST роблять його кращим вибором для великих, гетерогенних розподілених систем.
Як зробити правильно
Одна з найбільших проблем, що стоїть на шляху впровадження REST — це величезний обсяг непорозумінь та дезінформації, що оточують цю технологію.
Терміни REST
Занадто часто "RESTful" API насправді є просто RPC, упакованим для передачі через HTTP, і не реалізують архітектурні принципи REST.
Це також стосується багатьох "REST" API.
Цінність архітектурного патерну REST полягає в обмеженнях, які він накладає. Якщо ви ігноруєте або не розумієте ці обмеження, ви втрачаєте цю цінність.
Найточніше та найінформативніше описання REST міститься в докторській дисертації Роя Філдінга, РОЗДІЛ 5 — Перехідний стан представлення (REST). Це серйозна робота з професійної програмної архітектури — але варта зусиль, щоб навчитися та зрозуміти. Коли йдеться про мережеву та розподілену програмну архітектуру, це визначна праця.
Дякуємо за прочитане!
Ваші запитання та коментарі дуже бажані.
Ми розуміємо, що ця стаття лише зачепила поверхню різниць між REST і RPC. Ми намагаємося розпочати серйозну розмову, щоб продовжити ділитися тим, що ми дізналися — і щоб додати ваш досвід до цього обговорення!
Якщо ви знайшли це обговорення корисним, один аплауз буде сигналом, що вам це цікаво.
Рекомендуємо до прочитання: Трансформаційний підхід до розподілених застосунків
Перекладено з: Take a Closer Look at REST