Когато проектирате приложение, използващо управлявани услуги, трябва да знаете ограниченията на услугата, за да не получите изненади в производството

Като архитект на решения посещавам сравнително редовно срещи за проектиране на проекти.

Едно от нещата, които винаги слушам на тези срещи, е фразата „не можем да използваме услуга X, защото лимитът на услугата е твърде нисък“.

Вярвате или не, чувам го доста редовно.

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

Ограниченията на услугата съществуват с причина.

Преди да избягате и да поискате увеличение на лимита на услугата, запитайте се „защо изобщо съществува този лимит?“ AWS не иска да правите това по някаква причина и опитът да заобиколите ограничение звучи като лоша идея.

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

Политики за филтриране на SNS

Amazon SNS има ограничение по подразбиране от 100 000 теми на акаунт (или 1000 FIFO теми). Можете обаче да имате само 200 политики за филтър за абонамент на акаунт.

Това изглежда като странно разпределение. Ако достигнете максимално и двете граници, това означава, че само 0,2% от вашите теми могат да имат филтър за абонамент (ако приемем, че сте имали един абонамент за тема).

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

Да вземем пример от реалния свят.

Имате приложение с множество клиенти, което позволява на интеграторите да се абонират за събития. Приложението има нарастващ брой събития за абониране, тъй като развитието продължава.

Първият път, когато внедрих архитектура, за да удовлетворя този сценарий, не знаех за ограничението на филтъра за абонамент. Бях измислил план, при който всички абонаменти са на една и съща тема. Политика за филтриране беше добавена към всяка тема, за да включва наемател, събитие(а) и други филтри.

Това работеше... докато не свърши. След като достигнах квотата на абонаментната филтърна услуга за SNS, трябваше бързо да преосмисля решението.

Вместо да създам една тема, през която минават всички абонаменти, в крайна сметка отидох с много теми, които бяха създадени динамично без филтри.

Този модел ви позволява да се възползвате напълно от огромното количество теми, които можете да създадете в акаунт. Недостатъкът е, че сега трябва да управлявате кога да публикувате конкретни теми. Това може да звучи като обезсърчаваща задача, но не е нищо, с което „моделът на данни DynamoDB едно към много“ да не може да се справи.

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

Размер на резултата на Lambda Authorizer

Lambda Authorizers са Lambda функции, които се намират върху вашия API Gateway, за да извършват персонализирано оторизиране. Упълномощителят потвърждава самоличността на потребителя и връща IAM политика, която включва ARN на крайните точки, до които повикващият има достъп. Размерът на тази политика има ограничение от 8 KB.

Преди известно време представих идеята за „споделяне на Lambda авторизатор в цялата ви екосистема“. Изградете веднъж механизма за удостоверяване и го централизирайте във вашето приложение. Едно извикване ще върне политика, която включва всички крайни точки във вашето приложение, до които потребителят има достъп. Това беше чудесно за целите на кеширането, но отново се натъкваме на проблеми, когато говорим за мащаб.

Приложението, което създавах, имаше десетки микроуслуги, като всяка микроуслуга съдържаше API с десетки крайни точки. Създавахме приложение, което имаше дефинирани от системата роли, така че използването на заместващи символи в правилата не беше опция. Всяка крайна точка трябваше да бъде изрично посочена в правилата.

Освен сложното бреме от управлението на това между услугите за всяка роля, той създаде гигантски политики, които в крайна сметка надхвърлиха това ограничение от 8KB. Още веднъж трябваше да се върнем назад и да внедрим нашето решение по различен начин, за да се справим с ограничението на размера.

Вместо да имаме един авторизатор, който знае за всички микроуслуги (което така или иначе е не-не), ние избрахме да съдържаме Lambda авторизатори във всяка микроуслуга. Това не само намали размера на политиката, която беше върната в резултата, но също така ни даде повече гъвкавост за обогатяване на „контекста на авторизатора“.

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

При този сценарий смятахме, че няма начин да достигнем ограничението от 8KB, когато първоначално проектирахме решението. Но ние не мислехме за бъдещето си. Винаги вземайте предвид мащаба на недалечното бъдеще във вашите проекти. Ще надрасне ли този мащаб квота за услуги? В моя случай стана.

Цели на правилото EventBridge

EventBridge маршрутизира събития до различни дестинации чрез правила. Правилата определят какво търси EventBridge и дефинират целта или дестинацията, която се задейства от събитието. Всяко правило има ограничение от пет цели.

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

Ако имате събитие, което трябва да уведоми повече от петима абонати, имате късмет. Можете да използвате SNS за „разпръскване към множество цели“. Просто направете SNS тема една от вашите цели и сте готови.

Целите на EventBridge наистина са свързани с различни процеси. Може би трябва да следите всички събития за целите на одита. Или трябва да трансформирате събитието и да го предадете на друго приложение. Или просто трябва да уведомите абонатите за събитието. Всеки един от тях е отделен процес, който трябва да бъде своя цел.

Имайте предвид, че ограниченията съществуват с причина. Понякога заобикалянето на лимита на услугата по „умен“ начин може да ви създаде проблеми. Използвайте инструментите, както са предназначени във вашия дизайн. Интелигентността може да свърши работата, но прави вашия код значително по-труден за поддръжка.

Подобно на целевия лимит на EventBridge, има най-добри практики при работа с потребители на DynamoDB Stream. Когато обработвате потоци, се препоръчва да имате най-много два манипулатора, за да предотвратите дроселиране.

Ако имате множество процеси, които трябва да се изпълняват в резултат на DynamoDB поток, можете да използвате същия подход, както направихме за целите на правилото EventBridge: разклоняване със SNS. Или запазването на съдържанието в S3 и публикуването на обектния ключ в SNS съобщение, или предаването на съдържанието директно в съобщението ще ви позволи да получите толкова потребители на записите на потока, колкото са ви необходими.

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

Когато мислите за потребителите на асинхронен процес, представете си ги като отделни работни потоци. Един потребител на изолирано действие. Приближаването към дизайн с нагласата „всеки абонат трябва да бъде обслужван с инфраструктура“ просто изисква проблеми.

Ограничения за размера на заявката на DynamoDB

На по-ниско ниво DynamoDB има „ограничение за размера на заявката“, което трябва да отчетете. При извършване на операция за сканиране или заявка върху таблица DynamoDB, максималният размер на резултата, който може да върне, е 1MB. Ако вашата заявка съответства на повече от 1MB данни, DynamoDB ще върне свойство LastEvaluatedKey в отговора, за да ви уведоми, че има още резултати за обработка.

В предишна статия навлязох в подробности за това как проектирахме нашето приложение, без да имаме предвид това ограничение. Когато субектите достигнаха определен мащаб в нашето приложение, данните започнаха да „липсват“ в нашите отговори на API.

Това е така, защото не сме взели предвид ограничението за максимален размер на заявката. Отговорът връщаше правилно подмножество от данни и свойството LastEvaluatedKey, но ние го игнорирахме, защото не бяхме взели това под внимание в първоначалния си дизайн.

За да смекчите това, имате няколко различни опции.

  • Проектирайте своя модел на данни, така че заявките да не могат да достигнат 1 MB
  • Създайте вашето приложение, като имате предвид пейджинг

Когато следвате „дизайн на една таблица“, вие структурирате своя модел на данни по начин, по който можете да извличате обекти и свързани обекти с прости заявки. Обикновено това е под формата на претоварен съставен ключ, който съчетава ключа за разделяне и ключа за сортиране на вашите обекти и ги променя, за да представят различни типове обекти.

Ако умишлено положите усилия в дизайна предварително, може да успеете да избегнете ограничението за заявка от 1 MB.

Но не винаги можете да проектирате по такъв начин. Ако трябва да имате неограничени данни или вашите обекти са изключително големи, ще бъде невъзможно да избегнете това ограничение. Така че изграждането на DynamoDB пейджинг във вашето приложение е следващата най-добра стъпка.

Не искате неочаквана загуба на данни, така че вземете предвид дизайна („особено когато ставате на първо място с API“) предварително, а не в отговор на критичен проблем.

Заключение

Ограниченията на услугите са предназначени да действат като предпазни парапети при изграждането на вашата инфраструктура. Ако приложението ви срещне проблем с квота на друго ниво на мащаб, преосмислянето на вашия дизайн вероятно е правилният отговор. Харесайте, ако имате нужда от 10 000 SNS филтъра за абонамент вместо само 200.

В някои случаи може да е по-добре „квотата да се увеличи“, например когато трябва да стартирате 1200 едновременно ламбда функции вместо 1000.

Който и път да решите, уверете се, че не се борите с инфраструктурата. Ограниченията са там, за да ви попречат да направите нещо глупаво. Не бъди тъп

Проектирането е трудна работа, а познаването на квотите за услуги за всички услуги, които консумирате, е още по-трудно. Когато измисляте своя дизайн, не забравяйте да препратите към страницата с квота за услуга в конзолата на AWS, за да видите списък с всички ограничения за конкретна услуга.

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

Повечето лимити на услугата могат да бъдат увеличени, но за тези, които не могат — оставате с дизайнерско решение. Ако направите крачка назад и се запитате „защо е толкова ниско?“ може да разберете и да разберете екосистемата малко по-добре.

Успех и се надявам да вземете това предвид следващия път, когато изграждате система.

Приятно кодиране!