SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Өнімділікті талдау және баптау тұтынушылар үшін өнімділікті сәйкестендірудің қуатты құралы болып табылады.

Баптау эксперименттерін сынауға ғылыми тәсілді қолдану арқылы бағдарламадағы кедергілерді тексеру үшін өнімділікті талдауды пайдалануға болады. Бұл мақала мысал ретінде Go веб-серверін пайдалану арқылы өнімділікті талдау мен реттеудің жалпы тәсілін анықтайды.

Go бұл жерде әсіресе қолайлы, өйткені оның профильдеу құралдары бар. pprof стандартты кітапханада.

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Стратегия

Құрылымдық талдауымыз үшін жиынтық тізім жасайық. Біз интуиция немесе болжам негізінде өзгерістер енгізудің орнына шешім қабылдау үшін кейбір деректерді пайдалануға тырысамыз. Ол үшін мынаны орындайық:

  • Оңтайландыру шекараларын (талаптарын) анықтаймыз;
  • Жүйе үшін транзакция жүктемесін есептейміз;
  • Біз сынақты орындаймыз (деректерді құру);
  • қарау;
  • Біз барлық талаптардың орындалғанын талдаймыз?
  • Біз ғылыми жолмен орнатамыз, гипотеза жасаймыз;
  • Біз бұл гипотезаны тексеру үшін эксперимент жасаймыз.

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Қарапайым HTTP серверінің архитектурасы

Бұл мақала үшін біз шағын Golang HTTP серверін қолданамыз. Осы мақаладағы барлық кодты табуға болады осында.

Талданатын қолданба әрбір сұрау үшін Postgresql сұрауын жүргізетін HTTP сервері. Сонымен қатар, қолданба мен жүйелік көрсеткіштерді жинау және көрсету үшін Prometheus, node_exporter және Grafana бар.

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Қарапайымдылық үшін біз көлденең масштабтау (және есептеулерді жеңілдету) үшін әрбір қызмет пен дерекқор бірге орналастырылғанын қарастырамыз:

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Біз мақсаттарды анықтаймыз

Бұл кезеңде біз мақсатты анықтаймыз. Біз нені талдауға тырысамыз? Аяқталатын уақытты қайдан білеміз? Бұл мақалада біз клиенттеріміз бар екенін және біздің қызмет секундына 10 000 сұранысты өңдейтінін елестетеміз.

В Google SRE кітабы таңдау және модельдеу әдістері жан-жақты қарастырылады. Дәл солай істейік, модельдер құрастырайық:

  • Кешігу: сұраулардың 99%-ы 60 мс-тен аз уақыт ішінде аяқталуы керек;
  • Құны: Қызмет ақылға қонымды деп ойлайтын ақшаның ең аз мөлшерін тұтынуы керек. Ол үшін біз өткізу қабілетін барынша арттырамыз;
  • Сыйымдылықты жоспарлау: жалпы масштабтау мүмкіндігін қоса, қанша қолданба данасын іске қосу қажет болатынын және бастапқы жүктеме мен қамтамасыз ету талаптарын қанағаттандыру үшін қанша дана қажет болатынын түсіну және құжаттау артықтық n+1.

Кідіріс талдауға қосымша оңтайландыруды қажет етуі мүмкін, бірақ өткізу қабілетін анық талдау қажет. SRE SLO процесін пайдаланған кезде, кідірту сұрауы тұтынушыдан және/немесе өнім иесі ұсынған бизнестен келеді. Ал біздің қызметіміз бұл міндеттемені басынан бастап ешқандай баптаусыз орындайды!

Сынақ ортасын орнату

Сынақ ортасының көмегімен біз жүйемізге дозаланған жүктемені шығара аламыз. Талдау үшін веб-қызмет өнімділігі туралы деректер жасалады.

Транзакция жүктемесі

Бұл орта пайдаланады Вегета тоқтатылғанға дейін реттелетін HTTP сұрау жылдамдығын жасау үшін:

$ make load-test LOAD_TEST_RATE=50
echo "POST http://localhost:8080" | vegeta attack -body tests/fixtures/age_no_match.json -rate=50 -duration=0 | tee results.bin | vegeta report

Бақылау

Орындалу уақытында транзакциялық жүктеме қолданылады. Қолданба көрсеткіштеріне (сұраулар саны, жауап беру кідірісі) және операциялық жүйеге (жад, орталық процессор, IOPS) қоса, оның қай жерде проблемалары бар екенін, сондай-ақ CPU уақыты қалай жұмсалатынын түсіну үшін қолданба профилін жасау іске қосылады.

Профильдеу

Профильдеу - қолданба жұмыс істеп тұрған кезде CPU уақыты қайда кететінін көруге мүмкіндік беретін өлшем түрі. Ол процессордың қай жерде және қанша уақыт жұмыс істейтінін дәл анықтауға мүмкіндік береді:

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Бұл деректерді процессордың босқа кететін уақыты мен қажетсіз жұмыс туралы түсінік алу үшін талдау кезінде пайдалануға болады. Go (pprof) стандартты құралдар жинағын пайдаланып профильдерді жасап, оларды жалын графигі ретінде көрсете алады. Мен оларды пайдалану және орнату жөніндегі нұсқаулықты кейінірек мақалада қарастырамын.

Іске асыру, бақылау, талдау.

Эксперимент жасайық. Қойылым өзімізге сай келгенше орындап, бақылап, талдаймыз. Алғашқы бақылаулардың нәтижелерін алу үшін оны қолдану үшін біз ерікті түрде төмен жүктеме мәнін таңдаймыз. Әрбір келесі қадамда біз кейбір таралумен таңдалған масштабтау коэффициентімен жүктемені арттырамыз. Жүктеме сынағының әрбір жұмысы реттелетін сұраулар санымен орындалады: make load-test LOAD_TEST_RATE=X.

Секундына 50 сұрау

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Жоғарғы екі графикке назар аударыңыз. Жоғарғы сол жақта біздің қосымшамыз секундына 50 сұранысты өңдеп жатқанын көрсетеді (оның пікірінше), ал жоғарғы оң жақта - әрбір сұраудың ұзақтығы. Екі параметр де біздің өнімділік шекараларымызға сәйкес келетін-келмейтінімізді іздеуге және талдауға көмектеседі. Диаграммадағы қызыл сызық HTTP сұрауының кешігуі 60 мс-де SLO көрсетеді. Сызықтан біздің жауап беру уақытымыздың максималды уақытынан әлдеқайда төмен екенін көруге болады.

Құнды қарастырайық:

Секундына 10000 50 сұрау / бір серверге 200 сұрау = 1 сервер + XNUMX

Біз бұл көрсеткішті әлі де жақсарта аламыз.

Секундына 500 сұрау

Жүктеме секундына 500 сұрауға жеткенде қызықты нәрселер басталады:

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Тағы да, жоғарғы сол жақ графикте қолданбаның әдеттегі жүктемені алатынын көруге болады. Бұлай болмаса, қолданба жұмыс істеп тұрған серверде ақау бар. Жоғарғы оң жақтағы жауап күту графигі секундына 500 сұрау 25-40 мс жауап кідірісіне әкелетінін көрсетеді. 99-процентиль жоғарыда таңдалған 60 мс SLO-ға әлі де жақсы сәйкес келеді.

Құны бойынша:

Секундына 10000 500 сұрау / бір серверге 20 сұрау = 1 сервер + XNUMX

Әлі де жақсартуға болады.

Секундына 1000 сұрау

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Керемет ұшыру! Қолданба секундына 1000 сұрауды өңдегенін көрсетеді, бірақ кідіріс шегі SLO арқылы бұзылған. Мұны жоғарғы оң жақ диаграммадағы p99 сызығынан көруге болады. p100 желісі әлдеқайда жоғары болса да, нақты кешігулер максимум 60 мс шамасынан жоғары. Қолданбаның шын мәнінде не істейтінін білу үшін профильдеуге кірісейік.

Профильдеу

Профильдеу үшін біз жүктемені секундына 1000 сұранысқа орнаттық, содан кейін пайдаланыңыз pprof қолданбаның CPU уақытын қайда жұмсайтынын білу үшін деректерді алу. Мұны HTTP соңғы нүктесін белсендіру арқылы жасауға болады pprof, содан кейін жүктеу кезінде нәтижелерді curl көмегімен сақтаңыз:

$ curl http://localhost:8080/debug/pprof/profile?seconds=29 > cpu.1000_reqs_sec_no_optimizations.prof

Нәтижелерді келесідей көрсетуге болады:

$ go tool pprof -http=:12345 cpu.1000_reqs_sec_no_optimizations.prof

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

График қолданбаның CPU уақытын қайда және қанша жұмсайтынын көрсетеді. Сипаттамасынан Брендан Грегг:

x осі алфавит бойынша сұрыпталған стек профилін толтыру болып табылады (уақыт емес), y осі стектің тереңдігін көрсетеді, [жоғарғы] нөлден бастап санайды. Әрбір тіктөртбұрыш стек жақтауы болып табылады. Рамка неғұрлым кең болса, соғұрлым ол стектерде жиі кездеседі. Жоғарғы жағындағы процессорда жұмыс істейді, ал төменде - еншілес элементтер. Түстер әдетте ештеңені білдірмейді, бірақ кадрларды ажырату үшін жай ғана кездейсоқ таңдалады.

Талдау – гипотеза

Түзету үшін біз CPU уақытының босқа кетуін табуға тырысамыз. Біз қалдықтардың ең үлкен көздерін іздеп, оларды алып тастаймыз. Профильдеу қолданбаның CPU уақытын қай жерде өткізетінін дәл анықтайтынын ескере отырып, сізге мұны бірнеше рет орындау қажет болуы мүмкін, сонымен қатар қолданбаның бастапқы кодын өзгерту, сынақтарды қайта орындау және өнімділіктің жоспарланғанға жақындағанын көру қажет болады. .

Брендан Греггтің ұсыныстарына сүйене отырып, біз диаграмманы жоғарыдан төмен қарай оқимыз. Әрбір жол стек жақтауын (функция шақыруын) көрсетеді. Бірінші жол - бағдарламаға кіру нүктесі, барлық басқа қоңыраулардың ата-анасы (басқаша айтқанда, барлық басқа қоңыраулардың стекінде болады). Келесі жол қазірдің өзінде басқаша:

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Меңзерді графиктегі функция атауының үстіне апарсаңыз, оның жөндеу кезінде стекте болған жалпы уақыты көрсетіледі. HTTPServe функциясы уақыттың 65% болды, басқа функциялардың орындалу уақыты, runtime.mcall, mstart и gcқалған уақытты алды. Қызықты факт: жалпы уақыттың 5% DNS сұрауларына жұмсалады:

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Бағдарлама іздейтін мекенжайлар Postgresql-ге жатады. Басыңыз FindByAge:

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Бір қызығы, бағдарлама, негізінен, кідірістерді қосатын үш негізгі көз бар екенін көрсетеді: қосылымдарды ашу/жабу, деректерді сұрау және дерекқорға қосылу. График DNS сұраулары, ашу және жабу қосылымдары жалпы орындау уақытының шамамен 13% алатынын көрсетеді.

Гипотеза: Біріктіру арқылы қосылымдарды қайта пайдалану HTTP арқылы бір сұраудың уақытын қысқартуы керек, бұл жоғары өткізу қабілеті мен кідірістің төмендеуіне мүмкіндік береді..

Қолданбаны орнату – эксперимент

Біз бастапқы кодты жаңартамыз, әрбір сұрау үшін Postgresql қосылымын жоюға тырысамыз. Бірінші нұсқа - пайдалану қосылу пулы қолданба деңгейінде. Бұл экспериментте біз орнату Go үшін sql драйверімен қосылымды біріктіру:

db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)

if err != nil {
   return nil, err
}

Орындау, бақылау, талдау

Сынақты секундына 1000 сұраумен қайта іске қосқаннан кейін, p99 60 мс SLO кідірісімен қайта оралғаны анық!

Құны қанша?

Секундына 10000 1000 сұрау / бір серверге 10 сұрау = 1 сервер + XNUMX

Оны одан да жақсырақ етейік!

Секундына 2000 сұрау

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Жүктеменің екі еселенуі бірдей нәрсені көрсетеді, жоғарғы сол жақ диаграмма қолданбаның секундына 2000 сұранысты өңдеуге қабілеттілігін көрсетеді, p100 60 мс төмен, p99 SLO қанағаттандырады.

Құны бойынша:

Секундына 10000 2000 сұрау / бір серверге 5 сұрау = 1 сервер + XNUMX

Секундына 3000 сұрау

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Мұнда қолданба p3000 кідірісі 99 мс кем 60 сұрауды өңдей алады. SLO бұзылмайды және құны келесідей қабылданады:

Секундына 10000 сұраныс / бір серверге 3000 сұрау = 4 сервер + 1 (автор ең жақынға дейін дөңгелектенеді шамамен. аудармашы)

Талдаудың тағы бір кезеңін қолданып көрейік.

Талдау – гипотеза

Біз қолданбаны жөндеу нәтижелерін секундына 3000 сұраныспен жинаймыз және көрсетеміз:

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Әлі де уақыттың 6% қосылуға кетеді. Пул орнатуы өнімділікті жақсартты, бірақ әлі де қолданба дерекқорға жаңа қосылымдар жасауды жалғастыратынын көре аласыз.

Гипотеза: Қосылымдар біріктірілгеніне қарамастан, әлі де жойылуда және тазартылуда, сондықтан қолданба оларды қайта орнатуы керек. Күтудегі қосылымдар санын пул өлшеміне орнату қолданбаның қосылым жасауға жұмсайтын уақытын азайту арқылы кідіріспен көмектесуі керек..

Қолданбаны орнату – эксперимент

Орнатуға тырысуда MaxIdleConns бассейннің өлшеміне тең (сонымен бірге сипатталған осында):

db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)
db.SetMaxIdleConns(8)
if err != nil {
   return nil, err
}

Орындау, бақылау, талдау

Секундына 3000 сұрау

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

p99 әлдеқайда аз p60 кезінде 100 мс-тен аз!

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

Жалын графигін тексеру қосылымның енді көрінбейтінін көрсетеді! Толығырақ тексеру pg(*conn).query - бұл жерде де байланыс байқамайды.

SRE: өнімділікті талдау. Go бағдарламасында қарапайым веб-серверді пайдаланып конфигурациялау әдісі

қорытынды

Өнімділік талдауы тұтынушылардың күтулері мен функционалды емес талаптардың орындалатынын түсіну үшін өте маңызды. Бақылауларды тұтынушылардың күтулерімен салыстыру арқылы талдау ненің қолайлы және ненің келмейтінін анықтауға көмектеседі. Go талдауды қарапайым және қолжетімді ету үшін стандартты кітапханаға енгізілген қуатты құралдарды ұсынады.

Ақпарат көзі: www.habr.com

пікір қалдыру