Как няколко основни промени драстично увеличиха ефективността на нашето приложение.

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

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

Вие просто не бихте проектирали самосвал, както бихте проектирали Ferrari, и все пак те струват еднакво, производителността не е единствената причина да се направи кола.

Това, което казвам е, че тук, в Reeport, не сме създали Ferrari.
Построихме нещо по-близко до самосвал, защото това беше необходимото.

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

Тук свършва паралелът между софтуерното инженерство и производството на автомобили. Защото дълго време нашият самосвал беше БЪРЗ.

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

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

Докато не ни напомниха, че сме направили самосвал.

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

Страховитият момент, в който някой ви казва „Приложението е бавно, направете го по-бързо“.

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

Това е историята за това как разрешихме тези две и подобрихме времето за зареждане с коефициент около 14 пъти.

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

Имаше ясно, видимо и измеримо забавяне в каскадата от заявки, което знаехме, че можем да заобиколим.

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

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

Приспособлението прави HTTP заявка с искане за своите данни и след това получава ИД на работа. Този идентификатор на задание се използва за получаване на резултатите от заданието за данни на приспособлението, което се изпраща до предния край чрез уебсокет.

И така, за да обобщим: всяка от джаджите изпраща HTTP заявка, за да инициира зареждане, и след това слуша уебсокет за своите данни. Това е мястото, където можем да подобрим нещо.

Един проницателен читател, който има опит с този тип неща, може вече да е разбрал накъде отива това (подсказка: това е в заглавието).

Виждате ли, ето нещото:
Какво става, ако имате 15 уиджета на страница?
Какво ще кажете за 150?

Е, въпреки че данните не се изпращат ОБРАТНО от сървъра чрез първоначалната HTTP заявка, зареждането все още се инициира чрез този метод.

Инструментът за балансиране на натоварването на Reeport работеше на HTTP/1.1, това означава, че можем да имаме максимум 5 едновременни постоянни връзки на сървър/прокси.

Това означаваше, че само 5 заявки за започване на зареждане могат да бъдат изпратени наведнъж.

Това е причината за отчетливото, видимо и измеримо забавяне в каскадата от заявки, спомената по-рано.

Ако погледнете изображението по-горе, което е екранна снимка, направена от мрежовия раздел на браузъра, ще забележите (благодарение на масивната червена линия), че 5 задания се заявяват наведнъж, а 6-тото започва едва след като едно приключи .

Това означава, че 6-тата джаджа на страницата ще ЗАПОЧНЕ да зарежда цяла .6s закъснение и като гледаме това, можем да си представим, че 7-та ще е започнала с колосалните 1,1s по-късно.
Сега си представете времето за зареждане на страница с 20 уиджета, което е много често.

Това е неприемливо, трябва да бомбардираме нашия бекенд със заявки възможно най-бързо.

Тук влиза в действие чудесната актуализация на HTTP, която беше приета от браузърите в края на 2015 г., ето: HTTP/2.

Има един хитър трик, който е възможен с новата версия на протокола, нещо, което има възхитително сложното име „мултиплексиране на заявки през TCP“.

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

Без да навлизаме в техническото обяснение как работи (има много друго страхотно онлайн съдържание за това), най-важното нещо, което трябва да знаем е, че това премахва ограничението от 5 едновременни заявки!

И така, след превключване на балансиращото натоварване да използва HTTP/3, което включва актуализацията, спомената по-горе, както и някои други спретнати подобрения, като използването на протокола QUIC, как изглеждат нашите заявки?

Точно така, всички заявки от уиджетите за стартиране на задачите се изпълняват едновременно, независимо от броя на уиджетите на страница!

Така че сега, когато бомбардираме нашия бекенд със заявки възможно най-бързо, свършихме, нали?

Е, това е, което си помислихме в началото.

Бенчмарковете се връщат със забележимо увеличение на производителността, но не винаги, а понякога дори е ПО-БАВНО!

Ако вашият преден край ще говори, вашият бекенд трябва да върви по пътя.

Така че сега, след като имаме тази прекрасна корекция, която помага за намаляване на времето за зареждане на цели секунди, защо нещата не достигат главоломните скорости, предвидени?

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

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

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

В моменти като тези е добре да имаме разнообразен екип.

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

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

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

Хайде да поговорим с нашия добър стар приятел Kubernetes, той знае отговора.

„А, да, доста е очевидно какво се случва.“

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

Работниците в задната част бяха ограничени до 100 реплики в някои случаи и 40 в други.

По принцип: почти през цялото време увеличавахме броя на наличните работници.

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

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

Можете ли да кажете, че пиша това, когато съм гладен?

След като повиши лимитите с МНОГО (2000 реплики уауууу!), приложението започна да се държи точно както трябваше почти мигновено.

Нашият самосвал отново кара като ферари.

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

Лично аз си взех няколко поуки от това начинание.

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

Друг урок беше относно важността на четенето на част от знанията, достъпни онлайн: идеята за HTTP/2 идва от мен, когато се натъкнах на нишка в Reddit, докато небрежно разглеждах. Не мисля, че бихме се сетили за това сами, поне не първоначално.

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

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