Një faqe që përgjigjet për 200 ms me Redis lokal kërkon katër sekonda sapo klienti ndodhet pas një VPN, ndërsa numëruesit e serverit mbeten në punë të humbur. Slow Log nuk tregon asgjë mbi një milisekondë, grafiku i CPU-së është i sheshtë dhe instanca u shërben klientëve të tjerë pa u ankuar. Ajo që ndryshoi është distanca, dhe ajo që e shumëfishon distancën është numri i herëve që kodi juaj ndalon dhe pret. Ec rrugën e kërkesës nga klienti nga jashtë dhe rregullimi është pothuajse gjithmonë më pak pritje sekuenciale, jo një server më i shpejtë.

Fillo nga klienti, jo nga metrikat e serverit

Vëzhgo procesin e klientit midis komandës së parë dhe të fundit. Nëse gjurmimi tregon një përgjigje, një pauzë dhe pastaj komandën tjetër, po paguan një raund të plotë për çdo komandë dhe asnjë rregullim i serverit nuk e ndryshon këtë. Slow Log është instrumenti i gabuar këtu, sepse regjistron kohën e ekzekutimit dhe i përjashton qëllimisht I/O-t e komunikimit. Një Slow Log i pastër pranë një endpointi të ngadaltë është nënshkrimi i një problemi raundesh.

Masa vetë rrugën përpara se të prekësh kodin. redis-cli -h redis.example.internal --latency dërgon PING të përsëritur dhe shtyp kohën mesatare të kërkesës dhe përgjigjes, që është kostoja për çdo shkëmbim. Shumëzoje me numrin e komandave sekuenciale në një veprim të përdoruesit dhe ke një dysheme për endpointin.

Numëro raundet që një veprim i përdoruesit kërkon vërtet

Merr një endpoint të vetëm dhe shkruaj me radhë çdo thirrje Redis, përfshirë ato të fshehura brenda një ORM, një session middleware ose një kërkimi feature flag. Shumica e endpointëve të ngadaltë bëjnë njëzet ose tridhjetë thirrje aty ku mjaftojnë tri, dhe ato të fshehurat zakonisht janë shumica.

Një zinxhir varësie nuk mund të shembet: nëse komanda e dytë i duhet çelësi i kthyer nga e para, pritja është reale dhe opsionet e vetme janë një model tjetër i dhënash ose një operacion në server që e shpreh të gjithë hapin përnjëherë. Leximet e pavarura janë rast tjetër, sepse asgjë nuk të detyron të presësh përgjigjen e parë përpara se të dërgosh të dytën. Shëno çdo thirrje si të varur ose të pavarur përpara se të ndryshosh çdo gjë, dhe forma e rregullimit bëhet e qartë.

Numri që ka rëndësi janë pritjet sekuenciale, jo komandat totale. Tridhjetë komanda në një batch kushtojnë akoma një pritje.

Bëj batch vetëm komandat që nuk varen nga njëra-tjetra

Një pipeline i vendos komandat e pavarura në radhë dhe i mbledh përgjigjet me radhë, duke i kthyer N pritje në një. Shumica e klientëve e ekspozojnë si bllok, callback ose context manager, jo si mënyrë të veçantë lidhjeje, ndaj kontrollo API-në që ofron versioni i instaluar. Përfitimi rritet me kohën e raundit, dhe pikërisht për këtë ka rëndësi në VPN dhe mezi vërehet në localhost.

import redis

r = redis.Redis(host="redis.example.internal", port=6379, socket_timeout=2)
pipe = r.pipeline(transaction=False)
for key in ("user:1001", "user:1002", "user:1003"):
    pipe.get(key)
print(pipe.execute())

Kalo transaction=False kur dëshiron vetëm batching. Me parazgjedhjen klienti e mbështjell batch-in në MULTI dhe EXEC, gjë që e bën atomik dhe ndryshon atë që klientët e tjerë shohin gjatë fluturimit. Atomiciteti është një vendim korrektësie, jo një çelës performancë, dhe një pipeline nuk është transaksion vetëm sepse të dyja pakësojnë raundet.

Lexo çdo përgjigje, jo vetëm dorëzimin e batch-it. Një komandë në radhë mund të kthejë një gabim ndërsa batch-i në tërësi përfundon, dhe një klient që hedh listën e përgjigjeve e kthen një shkrim të dështuar në një të heshtur. Krahaso gjatësinë e listës së përgjigjeve me numrin e komandave që vendose në radhë.

Mbaj lidhjen gjallë midis veprimeve

Çdo lidhje e re paguan zgjidhjen e emrit, një handshake TCP, një handshake TLS dhe një AUTH, dhe mbi një VPN secili prej tyre është një raund që nuk mund ta heqësh me batch. Krijo klientin një herë për proces dhe ripërdore, ose përdor pool-in që ofron biblioteka jote me një madhësi të kufizuar. Rilidhja për çdo kërkesë është shkaku i dytë më i zakonshëm i këtij simptomi pas pritjes për çdo komandë.

Mbaj hostname-in privat në konfigurim, jo si adresë literale. Validimi i certifikatës dhe identiteti i shërbimit vlejnë akoma në një rrjet privat, dhe fiksimi i një IP thyhet në momentin që ofruesi rinumeron një subnet. Nëse zgjidhja e emrit është pjesa e ngadaltë, rregullo rrugën e resolverit, jo vargun e lidhjes.

Vendos një socket timeout të qartë që një tunel i ngecur të dështojë shpejt, në vend që të varë një worker. Pastaj konfirmo që pool-i ripërdoret vërtet duke regjistruar krijimin e lidhjeve në klient.

Përcakto madhësinë e batch-it para se të bëhet problem memorie

Redis mban përgjigjet në radhë për kohëzgjatjen e batch-it, dhe klienti e mban rezultatin e analizuar më pas. Një pipeline me dhjetë mijë vlera të mëdha shkëmben pritjet e rrjetit me kërcime memorie dhe pauza të gjata në të dy skajet.

Zgjidh madhësinë e batch-it sipas vëllimit të përgjigjeve, jo sipas numrit të komandave. Disa qindra komanda të vogla në një batch është zakonisht e rehatshme, ndërsa njëqind payload-e disa kilobyte nuk është. Ndaj sipas bajteve dhe sipas numrit, dhe mbaj çdo batch brenda buxhetit të latencës që endpointi ka vërtet.

Masa nga fillimi në fund pas ndryshimit: redis-cli -h redis.example.internal --latency-history tregon nëse vetë rruga është e qëndrueshme, dhe kohëmatësi yt i kërkesave tregon nëse endpointi u përmirësua. Nëse endpointi është akoma i ngadaltë ndërsa historia e latencës është e sheshtë, kostoja e mbetur është punë në server ose serializimi yt, dhe hapi tjetër është një profil i handler-it, jo një ndryshim tjetër batch-i.

Artikuj të ngjashëm