Как се мащабира MongooseIM?

Когато говорим за сървъри, този въпрос се задава отново и отново и MongooseIM не прави изключение. Как се мащабира? Мащабира се добре, това знаем. Направихме много тестове за натоварване в различни среди, създадохме множество производствени клъстери, някои от които обработваха значителен товар. Но по-точно как се мащабира?

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

215 км/ч
Това е, което моята спецификация на колата казва, че е максималната й скорост. Означава ли това, че мога да го карам толкова бързо? На първо място, не, защото няма да опитвам. Дори и да го направих, със сигурност няма да успея, поради различни причини - колата не е чисто нова, условията за шофиране никога не са перфектни, имам редовни гуми, които са предназначени за сигурност, а не за превишена скорост и др. производителят наистина казва, че (а) няма да вървите по-бързо от това, каквото и да правите, и (б) нещо като 180 км/ч е напълно наред (ако е законно).

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

Настройвам

Проведохме тестовете си за AWS - това е най-често използваната облачна среда с общо предназначение. Резултатите оттам могат да служат като еталон. Набор от ansible скриптове осигури EC2 екземпляр, инсталира и конфигурира MongooseIM. След това стартирахме „клиентски“ екземпляри EC2 един по един, като всеки установяваше редица XMPP връзки, представящи се за реални клиенти. Продължихме с него, докато или новите връзки не започнаха да се провалят, или времето до края на доставката, след което прекратихме целия тест.

Сървърът MongooseIM беше „обикновена ванилия“ - целта беше да се тестват само основните функционалности, като например обработка на връзки и маршрутизиране на съобщения. Ако беше използван клъстер от сървъри, клиентите щяха да се свързват на случаен принцип с някой от наличните възли - нямаше балансиращ товар, който да пречи.
Поведението на клиента също беше елементарно - един-единствен „клиент“ щеше да установи поток, да удостовери и след това да поддържа връзките отворени, като изпращаше по едно кратко съобщение всяка минута и получаваше каквото влезе. Съобщенията съдържаха времеви клейма, за да можем да проследяваме от край до край време до доставката.

Първи резултати

Типове екземпляри

След експериментиране с редица типове екземпляри установихме, че линията c5 е перфектен баланс. С предполагаемия ни модел на използване, този хардуерен профил осигурява точно правилната комбинация от памет и мощност на процесора. Оптимизираните за памет екземпляри с подобен размер предлагат подобна производителност, като същевременно са много по-скъпи - няма какво много да спечелите, като добавите повече памет. Също така, резултатите от стартираните оптимизирани за памет екземпляри бяха нестабилни, тъй като използването на процесора на MongooseIM имаше много скокове, които могат да нарушат тестовете по всяко време. Ето няколко примера:

mongooseim

Честота на съобщенията

Нашият въображаем среден потребител изпраща едно съобщение в минута - със 137k връзки на c5.large екземпляр, това означава, че MongooseIM маршрутизира около 2.3k съобщения в секунда. Ами ако нашите потребители станат по-активни или по-малко активни - как това променя максималното натоварване, с което можем да се справим?

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

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

Тестване на мащабируемост в две измерения

Вертикален

Сега, след като знаем, че линията c5 осигурява перфектен баланс, как ще помогне използването на по-мощен вариант? Отново линейно ли е? Дали удвояването на цифрата преди буквата „x“ всъщност удвоява товара, с който можем да се справим? Има ли граница за това?

Това беше сложно, тъй като има много ограничения на ниво OS и настройки на Erlang VM, които могат да спрат вашия възел да приема повече връзки. За подробности как сме конфигурирали нашите сървъри, направете справка с документацията на MongooseIM, достъпна онлайн.

Проведохме теста си за по-големи типове екземпляри, до c5.9xlarge. На това ниво MongooseIM успя да обработи почти 2,5 милиона връзки, предавайки 45 хиляди съобщения в секунда. И не бяха открити проблеми, така че изглежда не съществува истинско твърдо ограничение. Тъй като обаче това вече беше много повече, отколкото се стремихме, и провеждането на тези тестове води до значителни разходи, както по отношение на времето, така и на парите, решихме да спрем дотук. Това не е краят, но има шанс някой ден да се опитаме да го прокараме още по-далеч.

Хоризонтално

Как се скалира MongooseIM хоризонтално? Линейно ли е и ако да, с колко потребители може да се справи всеки нов възел? Можем ли да мащабираме ad infinitum или има лимит, над който има намаляващи възвръщаемости или дори неуспех? Искахме да разберем и това беше най-отнемащата време част от цялото изследване.

Събирахме клъстери MongooseIM на c5.large екземпляри и ги тествахме под стрес, докато не се провалиха. Продължихме и продължихме и мащабирането беше почти линейно, като наклонът на линията се колебаеше около 51 хиляди (което означава, че всеки нов възел увеличава способността на клъстера с 51 хиляди връзки, като прехващането е около 80 хиляди).

И така, докато стигнахме до петнадесет възла, с над 1,2 милиона потребители и 22 хиляди съобщения в секунда, не се виждаше ограничение. В този момент решихме да скочим напред и да опитаме двадесет възли. Това се оказа твърде много. Връзките между възлите от време на време изтичаха, причинявайки netsplits и несъответствия в базата данни на Mnesia, а клъстерът по принцип не функционираше.

Причината за това е начинът, по който работи дистрибуцията на Mnesia и по-общо Erlang. Всеки клъстерен възел Erlang поддържа активни връзки към всички останали възли, така че броят на връзките нараства с нарастваща скорост. С двадесет възела вече имаше 190 връзки за поддържане и обмен на данни.

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

Защо не и двете?

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

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

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

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

Трето измерение - федерация

Ако натоварването е трудно за управление за един клъстер, можете също да надхвърлите това - няма правило, според което всички потребители трябва да използват един и същ център за данни. С федерацията можете да настроите множество центрове за данни, всеки под собствен домейн, като по този начин умножите възможното натоварване, с което може да се справи цялата ви система. Освен това ще ви даде допълнителна полза от това да доближите сървърите си до вашите географски разпределени приложения. Федерацията също има своите идиосинкразии, но това е извън обхвата на тази статия (има шанс да се върнем към нея в една от бъдещите вноски).