JSON-RPC? Вземете хитър REST

JSON-RPC? Вземете хитър REST

Сигурен съм, че заглавието е предизвикало здравословна реакция — "Сега отново започна..." Но позволявайте ми да привлека вашето внимание за 5–10 минути и ще се постарая да не ви разочаровам.

Структурата на статията ще бъде следната: взема се стереотипно твърдение и се разкрива "природата" на възникването на този стереотип. Надявам се, че това ще ви накара да погледнете избора на парадигма за обмен на данни в проектите си от нов ъгъл.

За да бъде ясно какво представлява RPC, предлагам да разгледаме стандарта JSON-RPC 2.0. С REST няма яснота. И не бива да има. Всичко, което трябва да знаете за REST — той е неразличим от HTTP.

RPC заявките са по-бързи и ефективни, защото позволяват извършването на пакетни заявки.

Става въпрос за това, че в RPC можете в една заявка да извикате няколко процедури наведнъж. Например, да създадете потребител, да добавите аватар и в същата заявка да го запишете за определени теми. Само една заявка, а колко ползи!

Наистина, ако имате само една nod backend, това ще изглежда по-бързо при пакетна заявка. Защото три REST заявки ще изискват три пъти повече ресурси от една nod за установяване на връзките.

JSON-RPC? Вземете хитър REST

Обърнете внимание, че първата заявка при REST трябва да върне идентификатор на потребителя, за да се извършат последващите заявки. Това също отрицателно влияе на общия резултат.

Но такива инфраструктури могат да се срещнат, по-скоро, в in-house решения и в Enterprise. В крайни случаи, в малки WEB проекти. Но истинските WEB решения, наречени HighLoad, не трябва да се строят по този начин. Тяхната инфраструктура трябва да отговаря на критерии за висока наличност и натовареност. И картината се променя.

JSON-RPC? Вземете хитър REST

Зелените са маркирани каналите на активност в инфраструктурата при един и същи сценарий. Обърнете внимание как се държи RPC сега. Заявката използва инфраструктурата само по едно рамо от балансировчика към backend. Докато REST все още губи при първата заявка, но наваксва пропуснатото, използвайки цялата инфраструктура.

Достатъчно е в сценария да въведете не две заявки за обогатяване, а, да кажем, пет или десет... и отговорът на въпроса "кой печели сега?" става неочевиден.

Предлагам да погледнем по-широко на проблема. На схемата се вижда как се използват каналите на инфраструктурата, но инфраструктурата не се ограничава само до каналите. Важна част от инфраструктурата с високо натоварване са кешовете. Нека получим някакъв артефакт от потребителя. Няколко пъти. Да кажем 32 пъти.

JSON-RPC? Вземете хитър REST

Вижте как значително се е "поправила" инфраструктурата на RPC, за да отговаря на изискванията за високо натоварване. Всичко е в това, че REST използва цялата мощ на HTTP протокола, за разлика от RPC. На предоставената схема тази мощност се реализира чрез метода на заявката — GET.

HTTP методите, наред с останалите, имат стратегии за кеширане. Можете да се запознаете с тях в документацията на HTTP. За RPC се използват POST заявки, които не се считат за идемпотентни, тоест многократното повторение на същите POST заявки може да връща различни резултати (например, след изпращане на всяко мнение, ще се появи нова копия на това мнение) (източник).

Следователно, RPC не е в състояние ефективно да използва инфраструктурните кешове. Това води до необходимостта от „внедряване“ на софтуерни кешове. На схемата в тази роля е представен Redis. Софтуерният кеш, от своя страна, изисква от разработчика допълнителен кодов слой и съществени промени в архитектурата.

Нека сега да изчислим, колко заявки "роди" REST и RPC в разглежданата инфраструктура?

Запитвания
Входящи
к backend
к СУБД
к софтуерния кеш (Redis)
ИТОГА

REST
1/32*
1
1
0
3 / 35

RPC
32
32
1
31
96

[*] в най-добрия случай (ако се използва локален кеш) 1 заявка (една!), в най-лошия 32 входящи заявки.

В сравнение с първата схема, разликата е поразителна. Сега става очевиден успехът на REST. Но предлагам да не спираме на постигнатото. Развитата инфраструктура включва CDN. Често тя също решава въпроса с противодействието на DDoS и DoS атаки. Получаваме:

JSON-RPC? Вземете хитър REST

Тук за RPC всичко става напълно плачевно. RPC просто не е в състояние да делегира работата с натоварването на CDN. Остава само да се надяваме на системи за противодействие на атаки.

Може ли да завършим с това? И отново, не. HTTP методите, както вече споменахме, имат своя „магия“. И не е случайно, че методът GET е изключително използван в интернет. Обърнете внимание, че този метод може да адресира част от съдържанието, може да поставя условия, които да интерпретират инфраструктурните елементи още преди да предадат управлението на вашия код и т.н. Всичко това позволява създаването на гъвкави, управляеми инфраструктури, способни да обработват наистина големи потоци от заявки. А в RPC този метод... се игнорира.

Но защо така устойчив остава мита, че batch заявките (RPC) са по-бързи? Лично на мен ми се струва, че повечето проекти просто не достигат до такова ниво на развитие, когато REST може да покаже своята сила. Освен това, в малките проекти той охотно демонстрира своите слабости.

Изборът между REST и RPC не е индивидуален избор на човек в проекта. Този избор трябва да отговаря на изискванията на проекта. Ако проектът успее да извлече максимума от REST и това наистина е необходимо, то REST ще бъде отличен избор.

Но ако за получаването на всички предимства на REST трябва да се наемат девопси за бързо мащабиране на инфраструктурата, администратори за управление на инфраструктурата, архитект за проектиране на всички слоеве на уеб услугата... а проектът в същото време продава три опаковки маргарин на ден... бих се спрял на RPC, тъй като този протокол е по-утилитарен. Той не изисква дълбоки знания за работа с кешове и инфраструктура, а фокусира разработчика върху простите и ясни извиквания на нужните му процедури. Бизнесът ще бъде доволен.

RPC заявките са по-надеждни, тъй като могат да изпълняват batch-заявки в рамките на една транзакция.

Тази характеристика на RPC е несъмнено предимство, тъй като е лесно да се поддържа базата данни в консистентно състояние. А що се отнася до REST, става по-сложно. Заявките могат да идват несъгласувано на различни ноди на backend.

Този „недостатък“ на REST е обратната страна на неговото предимство, описано по-горе — способността ефективно да използва всички ресурси на инфраструктурата. Ако инфраструктурата е проектирана лошо, а особено, ако архитектурата на проекта и базата данни в частност са проектирани лошо, то наистина това е голяма болка.

Но дали batch запитите са толкова надеждни, колкото изглеждат? Нека разгледаме случая: създаваме потребител, обогатяваме профила му с някакво описание и му изпращаме SMS с код за завършване на регистрацията. Т.е. три извиквания в един batch запит.

JSON-RPC? Вземете хитър REST

Нека разгледаме схемата. На нея е представена инфраструктура с елементи на висока достъпност. Има два независими канала за комуникация с SMS шлюзове. Но… какво виждаме? При изпращане на SMS възниква грешка 503 — услугата временно не е налична. Тъй като изпращането на SMS е опаковано в batch запит, цялото запитване трябва да бъде отменено. Действията в СУБД се анулират. Клиентът получава грешка.

Следващият опит — лотария. Или запитването отново ще попаде на същия нод и отново ще върне грешка, или ще имаме късмет и ще бъде извършено. Но основното е, че поне веднъж нашата инфраструктура вече е работила напразно. Беше натоварване, а печалба няма.

Добре, нека си представим, че сме се напрегнали (!) и сме обмислили вариант, при който запитването може успешно да се изпълни частично. А остатъкът, ще опитаме да изпълним отново след определен интервал от време (Какъв? Решава фронт?). Но лотарията остана същата. Запитването за изпращане на SMS с вероятност 50/50 отново ще се провали.

Съгласете се, от страна на клиента, услугата не изглежда толкова надеждна, колкото бихме искали… а какво ще кажете за REST?

JSON-RPC? Вземете хитър REST

REST отново използва "магията" на HTTP, но сега с кодове на отговорите. При възникване на грешка 503 на SMS шлюза, бекендът предава тази грешка на балансировчика. Балансировчикът, получавайки тази грешка и без да прекъсва връзката с клиента, насочва запитването към друг нод, който успешно обработва запитването. Т.е. клиентът получава очаквания резултат, а инфраструктурата потвърдява своето високо звание "високодостъпна". Потребителят е щастлив.

И отново, това не е всичко. Балансировчикът не просто получи код за отговор 503. Този код, при отговор, по стандарт е желателно да бъде снабден с заглавие "Retry-After". Заглавието дава да се разбере на балансировчика, че не е необходимо да безпокои този нод по този маршрут в течение на зададеното време. И следващите запитвания за изпращане на SMS ще бъдат насочвани директно към нод, който няма проблеми с SMS шлюза.

Както виждаме, надеждността на JSON-RPC е преувеличена. Наистина, по-лесно е да се организира консистентност в БД. Но жертвата в такъв случай ще бъде надеждността на системата като цяло.

Изводът е в голяма степен аналогичен на предишния. Когато инфраструктурата е проста, очевидността на JSON-RPC безспорно е в негова полза. Ако проектът предполага висока наличност с голямо натоварване, REST изглежда по-правилно, макар и по-сложно решение.

Прагът за влизане в REST е по-нисък.

Мисля, че горният анализ, който развенчава утвърдените стереотипи относно RPC, ясно показа, че прагът за влизане в REST определено е по-висок от този в RPC. Това е свързано с необходимостта от дълбоко разбиране на работата на HTTP, както и с необходимостта от достатъчни познания относно съществуващите инфраструктурни елементи, които могат и трябва да се прилагат в WEB проектите.

Така че защо много хора мислят, че REST ще бъде по-прост? Личното ми мнение е, че тази привидна простота произтича от самите манифести на REST. Т.е. REST не е протокол, а концепция… REST няма стандарт, а има някои препоръки… REST не е по-сложен от HTTP. Привидната свобода и анархия примамва “свободните художници”.

Безспорно, REST не е по-сложен от HTTP. Но самият HTTP е добре обмислен протокол, който е доказал своята стойност десетилетия наред. Ако няма дълбоко разбиране за HTTP, не може да се съди и за REST.

Но за RPC — може. Достатъчно е да вземете неговата спецификация. Нужен ли ви е глупав JSON-RPC?? Или все же хитрый REST? Решать вам.

Искрено се надявам, че не съм загубил времето ви напразно.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster