ИТ развој

Mastering Microservices: Architecting for Predictable Performance

Совладување со микросервисите: Архитектура за предвидливи перформанси

Микросервисите не создаваат автоматски перформанси. Тие создаваат граници: меѓу кодни бази, тимови, бази на податоци, мрежи, начини на откажување и канали за распоредување. Тие граници може да го олеснат развојот на системот, но може и брзата локална операција да ја претворат во бавен синџир од далечински повици.

Предвидливите перформанси се покорисната цел. Систем што е доследно одзивен при очекувано оптоварување е полесен за управување од систем што повремено е спектакуларно брз, а повремено необјаснив. Архитектурата треба да ги направи доцнењето, капацитетот и откажувањата доволно видливи за да може да се размислува за нив пред клиентите да ги откријат.

Почнете со граници што ја оправдуваат својата цена

Границата на сервис не е граница на папка. Таа треба да претставува област со јасна сопственост, кохерентен модел на податоци и независна причина за промена. Разделувањето на PHP апликација на посебни сервиси само затоа што има модули често создава дистрибуирана сложеност без значајна автономија.

Пред да извлечете сервис, поставете практично прашање: што станува независно распоредливо, скалабилно или одржливо? Работно оптоварување за известување што извршува скапи барања можеби заслужува одделен капацитет од трансакцискиот тек за наплата. Компонента за известувања може да има корист од асинхрона обработка. На мал помошник за валидација веројатно не му е потребна HTTP крајна точка.

Секој далечински повик додава серијализација, управување со врски, мрежно доцнење, однесување при истек на време и нова зависност што треба да се надгледува. Одржувајте ги синхроните патеки на барања кратки. Ако едно API барање треба да повика пет надолни сервиси пред да врати одговор, неговото доцнење во опашката се одредува од најбавната зависност и интеракциите меѓу сите нив.

Намерно дизајнирајте ја критичната патека

Почнете со операцијата што корисникот ја чека. За крајна точка за нарачки, критичната патека може да го валидира внесот, да резервира залиха, да ја евидентира нарачката и да врати прифатен одговор. Испраќањето е-пошта, ажурирањето аналитика, создавањето фактури и освежувањето индекси за пребарување обично не мора да се случат пред тој одговор.

Преместете ја несуштинската работа во асинхрони пораки таму каде што е безбедно да го направите тоа. Целта не е сè да се направи асинхроно; туку да се заштити патеката на одговорот од работа што може да се заврши подоцна. Тој избор бара јасни очекувања за евентуална конзистентност. Ако клиентот очекува известување веднаш, договорот за производот и API-то мора да опише што значи „веднаш“.

Држете ја оркестрацијата блиску до случајот на употреба

API-порталот треба да обработува прашања како автентикација, рутирање и ограничување на стапката. Тој не треба да стане скриен дом на деловни правила и меѓусервисни работни текови. Исто така, сервисот не треба да прави широки fan-out повици само затоа што поврзани податоци постојат на друго место.

Претпочитајте експлицитен работен тек на ниво на апликација. На пример, сервисот за нарачки може да зачува нарачка во состојба на чекање и да објави настан откако трансакцијата со базата на податоци ќе успее. Сервисот за исполнување потоа го троши тој настан и ја извршува сопствената работа. Ова ги прави сопственоста и однесувањето при повторен обид појасни отколку кај кревок синџир на барања.

$order = $orderRepository->createPending($command);

$transactionManager->afterCommit(
    fn () => $eventBus->publish(new OrderPlaced($order->id()))
);

return new AcceptedOrderResponse($order->id());

Точниот механизам варира, но принципот е стабилен: не објавувајте работа на други сервиси пред промената во изворот на вистината да биде трајна.

Направете ги истеците на време, повторните обиди и идемпотентноста дел од API-то

Барање без истек на време е неразрешено ветување. Во PHP, конфигурирајте експлицитни истеци на време за поврзување и вкупно времетраење за излезни HTTP клиенти, двигатели за бази на податоци и потрошувачи на пораки. Истекот на време треба да се избере според достапниот буџет за доцнење на повикувачот, а не да се копира од стандардна вредност.

Повторните обиди може да ја подобрат отпорноста при привремени откажувања, но неселективните повторни обиди ги засилуваат прекините. Повторувањето на бавен надолен повик трипати низ стотици истовремени барања може да ги исцрпи пуловите на врски и да го отежне закрепнувањето. Повторувајте само операции што е безбедно да се повторат, користете ограничен експоненцијален backoff и престанете со повторни обиди кога повикувачот веќе нема време да чека.

  • Поставете краен рок за целото влезно барање.
  • Доделете помали временски буџети на надолните повици.
  • Повторувајте привремени откажувања само кога операцијата е идемпотентна.
  • Користете клуч за идемпотентност за надворешно активирани запишувања, како што се плаќање или создавање нарачка.
  • Вратете значаен одговор за неуспех наместо да чекате секоја зависност да закрепне.

Идемпотентноста е особено важна кога клиентите, порталите и работниците може сите да прават повторни обиди. Зачувајте го клучот со добиената операција или одговор. Кога истото барање повторно ќе пристигне, вратете го првичниот исход наместо да создадете дупликат работа.

Нека сопственоста на податоците ја обликува стратегијата за базата на податоци

Споделените бази на податоци се примамливи бидејќи спојувањата се практични. Но со текот на времето, тие создаваат поврзаност преку шеми, миграции, заклучувања и нејасна сопственост. Сервисот треба да ги поседува податоците што ги запишува и да ги изложува потребните информации преку API-ја, настани или наменски модели за читање.

Ова не значи копирање на секоја табела во секој сервис. Тоа значи избор на вистинската претстава за секој случај на употреба. Каталогот на производи може да објавува промени што градат локален индекс за пребарување. Контролната табла за нарачки може да користи модел за читање оптимизиран за барања за статус наместо да спојува оперативни табели низ повеќе сервиси во време на барање.

Перформансите на базата на податоци и понатаму се важни. Индексирајте колони што се користат за селективни филтри, спојувања во рамките на сервисот и патеки за подредување што навистина се користат. Проверувајте ги плановите за барања наместо да претпоставувате дека индексот помага. Избегнувајте неограничени множества резултати и користете пагинација базирана на курсор кога записите може да се променат додека корисниците се движат низ страниците.

Контејнеризирајте за повторливост, не за формалност

Docker помага кога развојот, тестирањето и продукцијата го извршуваат истиот артефакт на апликацијата со експлицитни зависности. PHP контејнерот треба да има јасен процес на градење, конфигурација соодветна за продукција и да не се потпира на запишлив код на апликацијата. Конфигурацијата припаѓа во околината или во управуван систем за конфигурација; тајните не треба да бидат вградени во сликите.

Проверките на здравјето треба да одговорат на вистинското прашање. Проверката на живост покажува дали процесот треба да се рестартира. Проверката на подготвеност покажува дали може безбедно да прима сообраќај. Третирањето на привремен проблем со базата на податоци како неуспех на живост може да предизвика јамки на рестартирање; третирањето на неподготвен работник како здрав може да му испрати работа што не може да ја обработи.

Мерете го однесувањето што сакате да го контролирате

Работата на перформансите почнува со набљудливост. Бележете ја стапката на барања, стапката на грешки, распределбите на доцнење, длабочината на редицата, пропусната моќ на работниците, употребата на конекции со базата на податоци и откажувањата на зависностите. Просеците се корисни за широки трендови, но ги прикриваат бавните барања што корисниците ги забележуваат. Следете процентили и поврзете ги со крајната точка, зависноста, верзијата на распоредувањето и оптоварувањето.

Користете идентификатор на барање или трага доследно низ логовите на порталот, логовите на PHP апликацијата, задачите во заднина и излезните повици. Кога крајната точка станува бавна, корисното прашање ретко е „дали сервисот е бавен?“ Туку: „која фаза го потроши буџетот и зошто?“

Микросервисната архитектура станува предвидлива кога секој сервис има мала, разбирлива одговорност и секоја интеракција има експлицитна цена.

Градете за смирени операции

Најсилните микросервисни системи не се оние со најмногу сервиси. Тоа се системите каде што развивачот може да ги објасни патеката на барањето, сопственоста на податоците, однесувањето при повторен обид и одговорот при неуспех без да нацрта лавиринт.

Одржувајте ја синхроната патека тесна. Дајте ѝ на секоја зависност истек на време. Направете ја повторената работа безбедна. Јасно поседувајте ги податоците. Мерете го реалното однесување под оптоварување. Тие навики ги претвораат микросервисите од организациски дијаграм во архитектура што останува одзивна кога лесните претпоставки престануваат да важат.

Портрет на автор на блогот

Mihajlo

Јас сум Михајло - развивач поттикнат од љубопитност, дисциплина и постојаната желба да создадам нешто значајно. Споделувам увиди, упатства и бесплатни услуги за да им помогнам на другите да ја поедностават својата работа и да растат во постојано развивачкиот свет на софтверот и вештачката интелигенција.