Com a
Un dia em vaig despertar amb un correu electrònic descontent a causa dels llargs retards amb Alvin, que teníem previst llançar en un futur proper. Concretament, el client va experimentar una latència del percentil 99 en la regió de 50 ms, molt per sobre del nostre pressupost de latència. Això va ser sorprenent, ja que vaig provar el servei àmpliament, especialment en la latència, que és una queixa habitual.
Abans de posar l'Alvin en proves, vaig fer molts experiments amb 40 consultes per segon (QPS), tots mostrant una latència de menys de 10 ms. Estava disposat a declarar que no estava d'acord amb els seus resultats. Però fent una altra ullada a la carta, em vaig adonar d'alguna cosa nova: no havia provat exactament les condicions que van esmentar, el seu QPS era molt inferior al meu. Vaig provar a 40k QPS, però només a 1k. Vaig fer un altre experiment, aquesta vegada amb un QPS més baix, només per apaivagar-los.
Com que estic blogueant sobre això, probablement ja heu descobert que els seus números eren correctes. Vaig provar el meu client virtual una i altra vegada, amb el mateix resultat: un nombre baix de peticions no només augmenta la latència, sinó que augmenta el nombre de peticions amb una latència de més de 10 ms. En altres paraules, si a 40k QPS unes 50 sol·licituds per segon superaven els 50 ms, aleshores a 1k QPS hi havia 100 peticions per sobre de 50 ms cada segon. Paradoxa!
Reduint la cerca
Quan s'enfronta a un problema de latència en un sistema distribuït amb molts components, el primer pas és crear una llista curta de sospitosos. Aprofundim una mica més en l'arquitectura d'Alvin:
Un bon punt de partida és una llista de transicions d'E/S completades (trucades de xarxa/cerques de disc, etc.). Intentem esbrinar on és el retard. A més de l'evident E/S amb el client, l'Alvin fa un pas addicional: accedeix al magatzem de dades. No obstant això, aquest emmagatzematge funciona al mateix clúster que Alvin, de manera que la latència hauria de ser inferior a la del client. Així doncs, la llista de sospitosos:
- Trucada de xarxa del client a Alvin.
- Trucada de xarxa d'Alvin al magatzem de dades.
- Cerca al disc al magatzem de dades.
- Trucada de xarxa des del magatzem de dades a l'Alvin.
- Trucada de xarxa d'Alvin a un client.
Intentem esborrar alguns punts.
L'emmagatzematge de dades no hi té res a veure
El primer que vaig fer va ser convertir l'Alvin en un servidor de ping-ping que no processa sol·licituds. Quan rep una sol·licitud, retorna una resposta buida. Si la latència disminueix, un error a la implementació d'Alvin o del magatzem de dades no és gens inaudit. En el primer experiment obtenim el següent gràfic:
Com podeu veure, no hi ha cap millora en utilitzar el servidor ping-ping. Això vol dir que el magatzem de dades no augmenta la latència i la llista de sospitosos es redueix a la meitat:
- Trucada de xarxa del client a Alvin.
- Trucada de xarxa d'Alvin a un client.
Genial! La llista s'està reduint ràpidament. Vaig pensar que gairebé havia descobert el motiu.
gRPC
Ara és el moment de presentar-vos un nou jugador: gRPC
ben optimitzat i àmpliament utilitzat, aquesta era la primera vegada que l'utilitzava en un sistema d'aquesta mida i esperava que la meva implementació fos subòptima, com a mínim.
disponibilitat gRPC
a la pila va donar lloc a una nova pregunta: potser és la meva implementació o jo mateix gRPC
causant problemes de latència? Afegeix un nou sospitós a la llista:
- El client truca a la biblioteca
gRPC
- Biblioteca
gRPC
fa una trucada de xarxa a la biblioteca del clientgRPC
al servidor - Biblioteca
gRPC
contacte amb Alvin (sense operació en cas de servidor de ping-pong)
Per fer-vos una idea de com és el codi, la meva implementació client/Alvin no és gaire diferent de la de client-servidor
Nota: La llista anterior està una mica simplificada perquè
gRPC
fa possible utilitzar el vostre propi model de fils (plantilla?), en el qual la pila d'execució està entrellaçadagRPC
i implementació dels usuaris. Per simplificar, ens cenyim a aquest model.
El perfil ho solucionarà tot
Després d'haver ratllat els magatzems de dades, vaig pensar que gairebé havia acabat: "Ara és fàcil! Apliquem el perfil i esbrineu on es produeix el retard". jo
Vaig agafar quatre perfils: amb QPS alt (baixa latència) i amb un servidor de ping-pong amb QPS baix (alta latència), tant al costat del client com al costat del servidor. I per si de cas, també vaig agafar un perfil de processador de mostra. En comparar perfils, acostumo a buscar una pila de trucades anòmala. Per exemple, al costat dolent amb una alta latència hi ha molts més canvis de context (10 vegades o més). Però en el meu cas, el nombre de canvis de context era gairebé el mateix. Per al meu horror, no hi havia res significatiu allà.
Depuració addicional
Estava desesperat. No sabia quines altres eines podia utilitzar, i el meu següent pla era essencialment repetir els experiments amb diferents variacions en lloc de diagnosticar clarament el problema.
Què passa si
Des del principi, em preocupava la latència específica de 50 ms. Aquest és un moment molt gran. Vaig decidir que retallaria trossos del codi fins que pogués esbrinar exactament quina part estava causant aquest error. Després va venir un experiment que va funcionar.
Com és habitual, en retrospectiva sembla que tot era evident. Vaig col·locar el client a la mateixa màquina que l'Alvin i vaig enviar una sol·licitud a localhost
. I l'augment de la latència ha desaparegut!
Alguna cosa no funcionava amb la xarxa.
Aprendre habilitats d'enginyer de xarxes
He de reconèixer: el meu coneixement de les tecnologies de xarxa és terrible, sobretot tenint en compte que treballo amb elles cada dia. Però la xarxa era el principal sospitós i necessitava aprendre a depurar-la.
Afortunadament, Internet estima els que volen aprendre. La combinació de ping i tracert semblava un bon començament per depurar problemes de transport de xarxa.
En primer lloc, vaig llançar
Després ho vaig intentar
Per tant, no era el meu codi, la implementació de gRPC o la xarxa que estava causant el retard. Començava a preocupar-me que no ho entendria mai.
Ara en quin sistema operatiu estem
gRPC
molt utilitzat a Linux, però exòtic a Windows. Vaig decidir provar un experiment que va funcionar: vaig crear una màquina virtual Linux, vaig compilar Alvin per a Linux i la vaig desplegar.
I això és el que va passar: el servidor de ping-pong de Linux no va tenir els mateixos retards que un amfitrió similar de Windows, tot i que la font de dades no va ser diferent. Resulta que el problema està en la implementació de gRPC per a Windows.
algorisme de Nagle
Durant tot aquest temps vaig pensar que em faltava una bandera gRPC
. Ara entenc què és realment gRPC
Falta la bandera de Windows. Vaig trobar una biblioteca RPC interna que estava segur que funcionaria bé per a tots els indicadors establerts
Gairebé Fet: vaig començar a eliminar els indicadors afegits un a un fins que va tornar la regressió per poder identificar-ne la causa. Va ser infame
gRPC
aquesta marca es va establir a la implementació de Linux per a sockets TCP, però no a Windows. Sóc això
Conclusió
La latència més alta a QPS baix va ser causada per l'optimització del sistema operatiu. En retrospectiva, l'elaboració de perfils no va detectar la latència perquè es va fer en mode de nucli en lloc de fer-ho en
Pel que fa a l'experiment localhost, probablement no va tocar el codi de xarxa real i l'algoritme de Nagle no es va executar, de manera que els problemes de latència van desaparèixer quan el client va arribar a Alvin a través de localhost.
La propera vegada que vegeu un augment de la latència a mesura que disminueix el nombre de sol·licituds per segon, l'algoritme de Nagle hauria d'estar a la vostra llista de sospitosos.
Font: www.habr.com