Paĝo, kiu respondas en 200 ms kontraŭ loka Redis, bezonas kvar sekundojn post kiam la kliento sidas malantaŭ VPN, dum la servilaj kalkuliloj restas neaktivaj. La malrapida protokolo montras nenion super unu milisekundo, la CPU-grafiko estas ebena, kaj la instanco servas aliajn klientojn sen plendo. Kio ŝanĝiĝis estas la distanco, kaj tio, kio multobligas la distancon, estas la nombro da fojoj, kiam via kodo haltas kaj atendas. Trairu la petan vojon de la kliento eksteren kaj la solvo preskaŭ ĉiam estas malpli da sinsekvaj atendoj anstataŭ pli rapida servilo.

Komencu de la kliento, ne de la servilaj metrikoj

Observu la klientan procezon inter la unua kaj la lasta komando. Se la spuro montras respondon, paŭzon, kaj poste la sekvan komandon, vi pagas plenan reiron por komando kaj neniu kvanto da servila agordado tion ŝanĝos. La malrapida protokolo estas la malĝusta instrumento ĉi tie, ĉar ĝi registras plenumtempon kaj intence ekskludas komunikadan I/O. Pura malrapida protokolo apud malrapida finpunkto estas la signo de reira problemo.

Mezuru la vojon mem antaŭ ol tuŝi kodon. redis-cli -h redis.example.internal --latency sendas ripetajn PING-ojn kaj presas la mezan petan kaj respondan tempon, kio estas via kosto por interŝanĝo. Multipliku tion per la nombro da sinsekvaj komandoj en unu uzula ago kaj vi havas suban limon por la finpunkto.

Kalkulu la reirojn, kiujn unu uzula ago efektive bezonas

Prenu unu finpunkton kaj skribu ĉiun Redis-vokon laŭorde, inkluzive tiujn kaŝitajn en ORM, sesia meza programo aŭ serĉo de trajto-flag. Plej multaj malrapidaj finpunktoj montriĝas fari dudek aŭ tridek vokojn tie, kie tri sufiĉus, kaj la kaŝitaj kutime estas la plimulto.

Dependeca ĉeno ne povas esti kunfaldita: se la dua komando bezonas la ŝlosilon redonitan de la unua, la atendo estas reala kaj la solaj ebloj estas alia datena modelo aŭ servila operacio, kiu esprimas la tutan paŝon samtempe. Sendependaj legoj estas alia kazo, ĉar nenio devigas vin atendi la unuan respondon antaŭ ol sendi la duan. Marku ĉiun vokon kiel dependa aŭ sendependa antaŭ ol redakti ion ajn, kaj la formo de la solvo fariĝos evidenta.

La nombro, kiu gravas, estas sinsekvaj atendoj, ne totalaj komandoj. Tridek komandoj en unu bloko ankoraŭ kostas unu atendo.

Blokigu nur la komandojn, kiuj ne dependas unu de la alia

Pipelino enkolekciigas sendependajn komandojn kaj kolektas la respondojn laŭorde, turnante N atendojn en unu. Plej multaj klientoj montras ĝin kiel blokon, retro-vokon aŭ kuntekstan administrilon anstataŭ aparta konekta reĝimo, do kontrolu la API-on, kiun liveras via instalita versio. La gajno skaliĝas kun la reira tempo, kaj ĝuste tial ĝi gravas tra VPN kaj preskaŭ ne sentiĝas en 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())

Transdonu transaction=False kiam vi volas nur blokigon. Kun la defaŭlta la kliento envolvas la blokon en MULTI kaj EXEC, kio faras ĝin atoma kaj ŝanĝas, kion aliaj klientoj povas observi dumvoje. Atomeco estas decido pri ĝusteco, ne rendimenta butono, kaj pipelino ne estas transakcio nur ĉar ambaŭ malpliigas reirojn.

Legu ĉiun respondon anstataŭ nur la blokan sendon. Enkolekciigita komando povas redoni eraron dum la bloko kiel tuto finiĝas, kaj kliento, kiu forĵetas la respondan liston, turnas malsukcesan skribon en silentan. Komparu la longon de la responda listo kun la nombro da komandoj, kiujn vi enkolekciigis.

Tenu la konekton viva inter agoj

Ĉiu nova konekto pagas por nomrivelado, TCP-manpremo, TLS-manpremo kaj AUTH, kaj tra VPN ĉiu el tiuj estas reiro, kiun vi ne povas blokigi. Kreu la klienton unufoje por procezo kaj reuzu ĝin, aŭ uzu la naĝejon, kiun via biblioteko provizas, kun limigita grandeco. Rekonekti por ĉiu peto estas la dua plej ofta kaŭzo de ĉi tiu simptomo post atendoj por komando.

Tenu la privatan gastignomon en la agordo anstataŭ laŭvorta adreso. Atestila validigo kaj serva identeco ankoraŭ validas en privata reto, kaj fiksado de IP rompiĝas en la momento, kiam la provizanto renumeras subreton. Se rivelado estas la malrapida parto, riparu la rivelan vojon anstataŭ la konektan ĉenon.

Agordu eksplicitan soketan tempolimon, por ke ŝtopita tunelo malsukcesu rapide anstataŭ pendigi laboranton. Poste konfirmu, ke la naĝejo vere reuziĝas, registrante konektokreadon en la kliento.

Grandigu la blokon antaŭ ol ĝi fariĝos memora problemo

Redis tenas enkolekciigitajn respondojn dum la tuta daŭro de bloko, kaj la kliento poste tenas la analizitan rezulton. Pipelino de dek mil grandaj valoroj interŝanĝas retajn atendojn kontraŭ memoraj pintoj kaj longaj paŭzoj ĉe ambaŭ finoj.

Elektu blokan grandecon laŭ responda volumeno anstataŭ laŭ komanda nombro. Kelkcent malgrandaj komandoj en unu bloko kutime estas komfortaj, dum cent plurkilobajtaj ŝarĝoj ne estas. Dividu laŭ bajtoj same kiel laŭ nombro, kaj tenu ĉiun blokon ene de la latenteca buĝeto, kiun la finpunkto efektive havas.

Mezuru de komenco ĝis fino post la ŝanĝo: redis-cli -h redis.example.internal --latency-history montras, ĉu la vojo mem estas stabila, kaj via propra peta tempigilo montras, ĉu la finpunkto pliboniĝis. Se la finpunkto ankoraŭ malrapidas dum la latenteca historio estas ebena, la restanta kosto estas servila laboro aŭ via propra serialigo, kaj la sekva paŝo estas profilo de la traktilo anstataŭ plia blokiga ŝanĝo.

Rilataj artikoloj