Redis oor 'n VPN voel stadig: minder retoereise per versoek
'n VPN maak nie 'n afgeleë Redis-oproep plaaslik nie. Begroot retoereise per versoek, hergebruik verbindings en hou pyplyne weg van transaksies.
'n Bladsy wat in 200 ms teen 'n plaaslike Redis antwoord, neem vier sekondes sodra die kliënt agter 'n VPN sit, terwyl die bediener se tellers ledig bly. Die stadige logboek wys niks bo 'n millisekonde nie, die CPU-grafiek is plat, en die instansie bedien ander kliënte sonder klagte. Wat verander het, is die afstand, en die ding wat die afstand vermenigvuldig, is die aantal kere wat jou kode stop en wag. Volg die versoekpad van die kliënt uit en die oplossing is byna altyd minder opeenvolgende wagte eerder as 'n vinniger bediener.
Begin by die kliënt, nie by die bediener se maatstawwe nie
Kyk na die kliëntproses tussen die eerste opdrag en die laaste. As die spoor 'n antwoord wys, dan 'n pouse, dan die volgende opdrag, betaal jy 'n volle retoer per opdrag en geen mate van bedienerinstelling sal dit verander nie. Die stadige logboek is die verkeerde instrument hier, want dit teken uitvoeringstyd op en sluit kommunikasie-I/O doelbewus uit. 'n Skoon stadige logboek langs 'n stadige eindpunt is die kenmerk van 'n retoerprobleem.
Meet die pad self voordat jy aan kode raak. redis-cli -h redis.example.internal --latency stuur herhaalde PING's en druk die gemiddelde versoek- en antwoordtyd, wat jou koste per uitruiling is. Vermenigvuldig dit met die aantal opeenvolgende opdragte in een gebruikersaksie en jy het 'n vloer vir die eindpunt.
Tel die retoereise wat een gebruikersaksie werklik nodig het
Neem 'n enkele eindpunt en skryf elke Redis-oproep in volgorde neer, insluitend dié wat in 'n ORM, 'n sessiemiddleware of 'n feature-flag-soektog weggesteek is. Die meeste stadige eindpunte blyk twintig of dertig oproepe te maak waar drie sou volstaan, en die weggesteektes is gewoonlik die meerderheid.
'n Afhanklikheidsketting kan nie ineengestrengel word nie: as die tweede opdrag die sleutel nodig het wat die eerste teruggee, is die wag werklik en die enigste opsies is 'n ander datamodel of 'n bedienerkant-operasie wat die hele stap gelyktydig uitdruk. Onafhanklike lesings is 'n ander geval, want niks dwing jou om op die eerste antwoord te wag voordat jy die tweede stuur nie. Merk elke oproep as afhanklik of onafhanklik voordat jy iets wysig, en die vorm van die oplossing word duidelik.
Die getal wat saak maak, is opeenvolgende wagte, nie totale opdragte nie. Dertig opdragte in een bondel kos steeds een wag.
Bondel net die opdragte wat nie van mekaar afhanklik is nie
'n Pyplyn tou onafhanklike opdragte en versamel die antwoorde in volgorde, wat N wagte in een verander. Die meeste kliënte bied dit as 'n blok, 'n callback of 'n konteksbestuurder eerder as 'n aparte verbindingsmodus, so kyk na die API wat jou geïnstalleerde weergawe lewer. Die wins skaal met retoertyd, wat juis is waarom dit op 'n VPN saak maak en op localhost skaars merkbaar is.
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())
Gee transaction=False wanneer jy net bondeling wil hê. Met die verstek draai die kliënt die bondel in MULTI en EXEC, wat dit atomies maak en verander wat ander kliënte in die middel kan waarneem. Atomisiteit is 'n korrektheidsbesluit eerder as 'n prestasieknoppie, en 'n pyplyn is nie 'n transaksie net omdat albei retoereise verminder nie.
Lees elke antwoord in plaas van net die bondelindiening. 'n Getoude opdrag kan 'n fout teruggee terwyl die bondel as geheel voltooi, en 'n kliënt wat die antwoordlys weggooi, verander 'n mislukte skryf in 'n stille een. Vergelyk die lengte van die antwoordlys met die aantal opdragte wat jy getou het.
Hou die verbinding lewendig tussen aksies
Elke nuwe verbinding betaal vir naamresolusie, 'n TCP-handdruk, 'n TLS-handdruk en 'n AUTH, en oor 'n VPN is elkeen van daardie 'n retoer wat jy nie kan wegbondel nie. Skep die kliënt een keer per proses en hergebruik dit, of gebruik die poel wat jou biblioteek bied met 'n begrensde grootte. Herverbinding per versoek is die tweede mees algemene oorsaak van hierdie simptoom ná wagte per opdrag.
Hou die private gasheernaam in die konfigurasie eerder as 'n letterlike adres. Sertifikaatvalidering en diensidentiteit geld steeds op 'n private netwerk, en die vaspen van 'n IP breek die oomblik wanneer die verskaffer 'n subnet hernommer. As resolusie die stadige deel is, maak die resolverpad reg eerder as die verbindingstring.
Stel 'n eksplisiete sokettimeout sodat 'n gestopte tonnel vinnig misluk eerder as om 'n werker te laat hang. Bevestig dan dat die poel werklik hergebruik word deur verbindingskepping in die kliënt te log.
Bepaal die bondelgrootte voordat dit 'n geheueprobleem word
Redis hou getoude antwoorde vir die duur van 'n bondel, en die kliënt hou die ontleede resultaat daarna. 'n Pyplyn van tienduisend groot waardes ruil netwerkwagte vir geheuespytte en lang pouses aan beide kante.
Kies 'n bondelgrootte teen antwoordvolume eerder as opdragtelling. 'n Paar honderd klein opdragte in een bondel is gewoonlik gemaklik, terwyl 'n honderd multi-kilobyt-ladings dit nie is nie. Verdeel volgens grepe sowel as volgens telling, en hou elke bondel binne die latencybegroting wat die eindpunt werklik het.
Meet van punt tot punt ná die verandering: redis-cli -h redis.example.internal --latency-history wys of die pad self stabiel is, en jou eie versoektydhouer wys of die eindpunt verbeter het. As die eindpunt steeds traag is terwyl die latencygeskiedenis plat is, is die oorblywende koste bedienerkantwerk of jou eie serialisering, en die volgende stap is 'n profiel van die handler eerder as nog 'n bondelverandering.