Всім привіти. А ви писали новий сервер з нуля? Які технології використовували? А розглядали які-небудь варіанти крім старого доброго REST? А що є ще щось? З такими питаннями я колись прийшов до свого лідера. Так, для мене було відкриттям, що можна використовувати не тільки REST для обміну повідомленнями між сервером і клієнтом. Ах так, звичайно я знав про SOAP, але використовувати його вже дуже не хотілося. Виявилося, що ви можете спробувати використовувати Thrift або наприклад gRPC. Від Thrift довелося відмовитися з ряду причин, які не сильно важливі в даній статті. До речі, можливо Thrift це саме те що вам потрібно.
Так що ж таке gRPC і в чому його відмінність від, що вже став класичним, REST? Чи краще gRPC? Може gRPC це знову хіпстерська технологія, яку всі скоро забудуть?
Не для кого ні секрет, що REST домінує в сучасному світі API, особливо, коли мова йде про веб-додатки та інфраструктурах, на основі мікросервісів. Мало хто навіть згадає, про те що мікросервіси можуть спілкуватися по іншому. Це напевно найпопулярніша відповідь на співбесіді. Та якщо додати ще feign клієнта з Spring, то виходить зовсім краса і мінімальні трудовитрати. Але для певного набору сценаріїв використання модель gRPC почала відігравати невелику, але важливу роль. Давайте спробуємо розібратися, коли ж нам варто використовувати REST, а коли gRPC.
Щоб зрозуміти REST і gRPC, нам потрібно почати з API (інтерфейсів прикладного програмування). API-інтерфейси надають правила і визначення, які дозволяють додаткам обмінюватися даними і взаємодіяти один з одним. API визначає типи викликів і запитів, які один додаток може надсилати іншому, як виконувати ці запити, використовувані формати даних і угоди, якими повинні слідувати клієнти. API-інтерфейси також підтримують «підключуваність» додатків, які утворюють більшу систему, оскільки вони дозволяють двом додаткам - навіть якщо вони написані різними мовами програмування і працюють на різних платформах - спілкуватися і взаємодіяти один з одним. API-інтерфейси REST і API-інтерфейси gRPC належать до різних архітектурних стилів для створення API-інтерфейсів.
Про REST (передача репрезентативного стану) API всі знають: REST - це найпопулярніший архітектурний стиль для створення API-інтерфейсів, особливо для веб-додатків і порожніх на основі мікросервісів. REST визначає певні обмеження і принципи, які підтримують взаємодію між мікросервісами та інтернет-додатками. Цих обмежень і принципів розробники можуть слідувати, а можуть і не дотримуватися. Хоча REST API може отримувати і повертати повідомлення, написані в різних форматах, найпоширенішим форматом, виходячи з мого досвіду, є JSON. JSON - це текстовий, зручний для читання людиною формат, який є гнучким, ефективним і не залежить від мови і платформи.
gRPC (віддалений виклик процедур Google): gRPC - це архітектура RPC з відкритим вихідним кодом, розроблена Google для забезпечення високошвидкісного зв'язку між мікросервісами. gRPC дозволяє розробникам інтегрувати сервіси, написані різними мовами. gRPC використовує формат обміну повідомленнями Protobuf (буфери протоколу), який є високоефективним форматом обміну повідомленнями з високим ступенем упаковки для серіалізації структурованих даних. Для певного набору сценаріїв використання gRPC API може бути більш ефективним ніж REST API (докладніше про це пізніше).
Ось проста матриця, що порівнює основи REST API і gRPC (картинка взята з інтернету):
REST API і RPC API на прикладі мікросервісів.
Думаю, що одним з кращих способів зрозуміти і помацати тему API - це спробувати розглянути API в контексті розробки сучасних додатків, на основі мікросервісів.
Що таке програми на основі мікросервісів?
Монолітний додаток містить програмування всіх своїх сервісів і функцій в єдиній неподільній кодовій базі, яка управляє всіма сервісами і функціями програми. У той час як, додатки на основі мікросервісів долають найбільші обмеження традиційних монолітних додатків. Проблема в тому, що в міру того, як розробники підключають нові служби і функції до існуючої структури, стає все важче змінювати, оновлювати і масштабувати додаток. Зміна однієї частини програми може негативно вплинути на інші області. Після багаторазового масштабування, оновлення та зміни моноліту кодова база в кінцевому підсумку стає настільки взаємозалежною і важкою для розуміння, що виникає необхідність перепроектувати всю систему з нуля.
Мікросервісна архітектура вирішує цю проблему. Цей архітектурний стиль передбачає розбиття моноліту на його компонентні служби і запуск кожного компонента як автономної програми (званого мікросервісом). Потім ці окремі мікросервіси використовують API-інтерфейси для взаємодії один з одним. Разом ця група мікросервісів, підключених до API, формує велику архітектуру програми. API-інтерфейси дозволяють автономно працюючим мікросервісам, навіть тим що написані різними мовами і працюють на різних платформах, створити підключувану систему на основі компонентів. Очевидно, що оновлення окремих мікросервісів відбувається значно швидше і простіше, оскільки зміни, які ви вносите в автономно працюючу службу, мають менший вплив на всю систему. Масштабування простіше і ефективніше, оскільки ресурси можуть бути перенаправлені на мікросервіси, які цього потребують, залежно від вимог використання. Більш того, якщо один мікросервіс вийде з ладу або сповільниться, ймовірність виходу з ладу всієї інфраструктури менше. Все це призводить до створення більш ефективних, відмовостійких, масштабованих і гнучких систем, а API - це те, що робить все це можливим. Звичайно можна оскаржити переваги мікросервісів і знайти безлічі прикладів, коли моноліт перевершує мікросервісну архітектуру. Це величезна тема в яку зараз немає сенсу заглиблюватися.
REST API
REST описує організацію клієнт-сервер, в якій внутрішні дані надаються клієнтам через формат обміну повідомленнями JSON або XML. За словами Роя Філдінга, API кваліфікується як «RESTful», якщо відповідає таким обмеженням:
- Єдиний інтерфейс: API повинен надавати споживачам API певні ресурси програми.
- Незалежність клієнт-сервера: клієнт і сервер працюють незалежно. Клієнт буде знати тільки ті URI, які вказують на ресурси програми. Зазвичай вони публікуються в документації API.
- Без збереження стану: сервер не зберігає дані, що стосуються запиту клієнта. Клієнт зберігає ці «дані стану» на своєму кінці (через кеш).
- Кешовані: ресурси програми, що надаються API, повинні бути кешованими.
- Багаторівнева: архітектура є багаторівневою, що дозволяє підтримувати різні компоненти на різних серверах.
- Код за запитом (COD): це єдине необов'язкове обмеження REST. Це дозволяє клієнтові отримувати виконуваний код як відповідь від сервера. Іншими словами, саме сервер визначає, як будуть виконуватися конкретні дії.
Нарешті, архітектура REST API зазвичай спирається на протокол HTTP, а REST API є найбільш поширеним форматом для створення веб-програм і підключення мікросервісів. Коли REST API стає загальнодоступним як веб-служба, кожен компонент (або послуга), що надається веб-службою, представляється клієнтам як ресурс. Клієнти можуть отримати доступ до цих ресурсів через загальний інтерфейс, який приймає різні HTTP-команди, такі як GET, POST, DELETE і PUT.
API RPC
Як попередник REST, RPC (віддалений виклик процедур) являє собою програмну архітектуру, що сходить до 1970-х років. RPC надає вам можливість викликати функцію на віддаленому сервері у певному форматі і отримувати відповідь у тому самому форматі. Не має значення, який формат використовує сервер, який виконує запит, і не має значення, локальний це сервер або віддалений. RPC дозволяє викликати функцію на сервері і отримувати результат в тому ж форматі.
Основна концепція RPC API аналогічна концепції REST API. RPC API визначає правила взаємодії та методи, які клієнт може використовувати для взаємодії з ним. Клієнти надсилають виклики, які використовують «аргументи» для виклику цих методів. Однак у разі RPC API метод знаходиться в URL-адресі. Аргументи, що викликають методи, знаходяться в рядку запиту. Щоб проілюструвати це, ось як запит RPC API порівнюється із запитом REST API:
RPC: запит RPC API може використовувати POST/deleteSmth і мати рядок запиту, який говорить {«» id «»: 777}
REST: запит REST API записує цей запит як DELETE/smth/777.
Занурення в API gRPC
Як варіант архітектури RPC, gRPC був створений Google для прискорення передачі даних між мікросервісами та іншими системами, яким необхідно взаємодіяти один з одним. Порівняно з REST API, gRPC API унікальні в таких відносинах:
- Протобуф (Protobuf) замість JSON
- Побудовано на HTTP 2 замість HTTP 1.1
- Створення власного коду замість використання сторонніх інструментів, таких як Swagger
- Передача повідомлень у 7-10 разів швидша
- Довша імплементація і реалізація, ніж REST
Думаю, варто детальніше розібрати кожну з цих відмінностей між API REST і gRPC.
Protobuf замість JSON/XML
І REST API, і RPC API відправляють і отримують повідомлення з використанням форматів обміну повідомленнями JSON або XML. Вони також можуть використовувати інші формати, але найбільш поширені JSON і XML. З них JSON став найпопулярнішим форматом, оскільки він гнучкий, ефективний, платформно-незалежний і не залежить від мови. Він також заснований на тексті і удобочитаємо для людини, що спрощує роботу операторам. Проблема в тому, що для певних випадків використання JSON недостатньо швидкий або легковісний при передачі даних між системами.
На відміну від REST і RPC, gRPC долає проблеми, пов'язані зі швидкістю і вагою, і пропонує велику ефективність при передачі повідомлень, використовуючи формат обміну повідомленнями Protobuf (буфери протоколу). Ось кілька подробиць про Protobuf:
- Незалежність від платформи та мови, наприклад JSON
- Серіалізує і десеріалізує структуровані дані для передачі в двійковому форматі.
- Оскільки він є сильно стиснутим форматом, він не забезпечує зручності JSON.
- Прискорює передачу даних, видаляючи безліч обов'язків, якими управляє JSON, тому він може зосередитися виключно на серіалізації і десеріалізації даних.
- Передача даних відбувається швидше, тому що Protobuf зменшує розмір повідомлень і служить легким форматом обміну повідомленнями.
Побудовано на HTTP 2 замість HTTP 1.1
Ще один спосіб підвищення ефективності gRPC - використання протоколу HTTP 2.
API-інтерфейси REST зазвичай побудовані на HTTP 1.1, який використовує модель взаємодії запит-відповідь. Це означає, що коли мікросервіс отримує кілька запитів від більш ніж одного клієнта, він повинен обслуговувати їх по одному, що уповільнює роботу всієї системи. API REST також можуть використовувати HTTP 2, вони як і раніше обмежені моделлю запит-відповідь і не використовують підтримку HTTP 2 для двонаправленого потокового зв'язку.
На відміну від цього, gRPC використовує HTTP 2 і користується перевагами підтримки HTTP 2 як для взаємодії з клієнтом, так і для двонаправленого зв'язку. Таким чином, gRPC може керувати «унарними» взаємодіями, аналогічними HTTP 1.1 (коли клієнт відправляє один запит, а сервер надсилає одну відповідь). Водночас клієнти можуть також відкривати довготривалі з'єднання, в яких кожен виклик RPC відкриває новий потік HTTP 2, також відомий як двонаправлений, «мультиплексований» або потоковий зв'язок.
У HTTP 2, коли мікросервіс отримує кілька запитів від більш ніж одного клієнта, він досягає мультиплексування, обслуговуючи безліч запитів і відповідей одночасно. У цьому відношенні API-інтерфейси gRPC відступають від обмежень API-інтерфейсів REST в їх здатності безперервно передавати інформацію.
GRPC надає три типи потокової передачі:
- На боці сервера: клієнт надсилає повідомлення на сервер. Сервер повертає відповідь клієнтові. Після завершення відповідей сервер надсилає повідомлення про стан (і в деяких випадках кінцеві метадані), що завершує процес. Після отримання всіх відповідей клієнт завершує свій процес.
- На боці клієнта: клієнт надсилає запити на сервер. Сервер повертає одну відповідь клієнтові. Він (зазвичай) надсилає відповідь після отримання всіх запитів від клієнта і повідомлення про стан (і в деяких випадках кінцевих метаданих).
- Двонаправлений: клієнт і сервер передають дані один одному без особливого порядку. Клієнт - це той, хто ініціює такий вид двонаправленої потокової передачі. Клієнт також завершує з'єднання.
Вбудована генерація коду замість використання сторонніх інструментів
Функції генерації коду вбудовані в gRPC через вбудований компілятор протоколів. При використанні REST API необхідно використовувати сторонній інструмент, наприклад Swagger, для автоматичної генерації коду для викликів API різними мовами.
Компілятор protoc, що поставляється з gRPC, сумісний з широким спектром мов програмування. Це робить gRPC відмінним засобом для багатомовних середовищ, де ви підключаєте безліч різних мікросервісів, написаних різними мовами і працюють на різних платформах.
Навпаки, REST API не пропонує функцій генерації власного коду. Ви повинні використовувати сторонній інструмент, такий як Swagger, для генерації коду для викликів API різними мовами. Це не приносить незручностей, але варто зазначити, що gRPC не залежить від будь-яких зовнішніх інструментів для генерації коду.
Передача повідомлень у 7-10 разів швидша
Згідно з широко цитованими тестами, опублікованими Руваном Фернандо, з'єднання gRPC API значно швидше, ніж з'єднання REST API. Фактично, він повідомив, що вони в 7-10 разів швидше:
GRPC приблизно в 7 разів швидше REST при отриманні даних і приблизно в 10 разів швидше, ніж REST при відправці даних для цього конкретного корисного навантаження. В основному це пов'язано з щільною упаковкою буферів протоколу і використанням HTTP/2 в gRPC
Ось результати, які отримав Руван:
Довша реалізація та імплементація, ніж REST
Незважаючи на переваги у швидкості передачі повідомлень, реалізація gRPC API набагато повільніша, ніж реалізація REST API. За словами Руана Фернандо, впровадження простої служби gRPC займає близько 45 хвилин. Реалізація веб-API або REST API займає всього близько 10 хвилин.
Фернандо повідомляє, що додатковий час впровадження відображає відсутність вбудованої підтримки gRPC у сторонніх інструментах. Це в першу чергу тому, що gRPC ще не отримав широкого поширення, особливо в порівнянні з повсюдним поширенням REST API. Ось що Фернандо говорить про час впровадження gRPC:
Мені довелося витратити приблизно 45 хвилин на впровадження цієї простої служби gRPC, з яких я витратив всього близько 10 хвилин на створення WebAPI. В основному це пов'язано з тим, що REST давно став мейнстрімом, і більшість основних фреймворків (наприклад, ASP.NET Core MVC) мають вбудовану підтримку для швидкого розгортання таких сервісів (за допомогою угод і шаблонів)
Коли краще використовувати REST або gRPC?
Давайте порівняємо, коли вам слід розглянути можливість використання REST API і gRPC API:
Коли використовувати REST API
Незалежно від того, чи створюєте ви внутрішню систему або відкриту систему, яка надає свої ресурси решті світу, REST API, ймовірно, залишаться фактичним вибором для інтеграції додатків протягом дуже довгого часу. Крім того, REST API ідеально підходять, коли системі потрібна високошвидкісна ітерація і стандартизація протоколу HTTP. Завдяки універсальній підтримці сторонніх інструментів REST API повинні бути вашим першим аргументом на користь інтеграції додатків, інтеграції мікросервісів і розробки веб-сервісів.
Коли використовувати API gRPC
Що стосується gRPC, у більшості сторонніх інструментів як і раніше відсутні вбудовані функції для сумісності з gRPC. Таким чином, gRPC в основному використовується для створення внутрішніх систем, тобто інфраструктури, закритої для зовнішніх користувачів. З урахуванням цього застереження, API-інтерфейси gRPC можуть бути корисні в наступних випадках:
- З "єднання з мікросервісами: зв'язок з низькою затримкою і високою пропускною здатністю gRPC робить його особливо корисним для підключення архітектур, що складаються з легких мікросервісів, де ефективність передачі повідомлень має першорядне значення.
- Системи, де використовується декілька мов програмування: завдяки підтримці генерації власного коду для широкого спектру мов розробки, gRPC відмінно підходить для управління з'єднаннями в середовищі з наявністю декількох мов.
- Потокова передача в реальному часі: якщо потрібно зв'язок в реальному часі, здатність gRPC керувати двонаправленою потоковою передачею дозволяє вашій системі відправляти і отримувати повідомлення в режимі реального часу, не чекаючи відповіді окремого клієнта.
- Мережі з низьким енергоспоживанням і низькою пропускною здатністю: використання gRPC серіалізованих повідомлень Protobuf забезпечує легкий обмін повідомленнями, велику ефективність і швидкість для мереж з обмеженим діапазоном пропускання і малопотужних мереж (особливо в порівнянні з JSON). Інтернет речей може бути прикладом такої мережі, в якій можуть бути корисні API gRPC.
Підведемо підсумок про REST і gRPC
Через різні переваги API-інтерфейсів gRPC, які ми розглянули досі, деякі розробники розглядають gRPC як «майбутнє». Однак ці розробники можуть забігати вперед. gRPC ще не отримав широкого поширення, і ще належить побачити, чи будуть його переваги стимулювати більш широке поширення в майбутньому.
Для порівняння, REST підтримується повсюдно, і практично кожна інфраструктура на основі мікросервісів повністю залежить від API-інтерфейсів REST як сполучної ланки, що об'єднує їх. Якщо ваш варіант використання не вимагає реалізації gRPC, ризикувати прийняттям gRPC на цьому етапі (до широкого поширення) недоцільно і не потрібно.
