Măsurarea performanței cu sincronizarea serverului

Publicat: 2022-03-10
Rezumat rapid ↬ Antetul Server Timing oferă o modalitate discretă și convenabilă de a comunica timpii de performanță a serverului backend instrumentelor pentru dezvoltatori din browser. Adăugarea de informații de sincronizare la aplicația dvs. vă permite să monitorizați performanța back-end și front-end într-un singur loc.

Când întreprindem orice fel de muncă de optimizare a performanței, unul dintre primele lucruri pe care le învățăm este că înainte de a putea îmbunătăți performanța, trebuie mai întâi să o măsurați. Fără a putea măsura viteza cu care ceva funcționează, nu putem spune dacă modificările efectuate îmbunătățesc performanța, nu au niciun efect sau chiar înrăutățesc lucrurile.

Mulți dintre noi vor fi familiarizați cu lucrul la o problemă de performanță la un anumit nivel. Acesta ar putea fi ceva la fel de simplu ca încercarea de a înțelege de ce JavaScript de pe pagina dvs. nu se activează suficient de curând sau de ce imaginile durează prea mult să apară pe rețelele Wi-Fi proaste ale hotelului. Răspunsul la acest fel de întrebări se găsește adesea într-un loc foarte familiar: instrumentele de dezvoltare ale browserului dvs.

De-a lungul anilor, instrumentele pentru dezvoltatori au fost îmbunătățite pentru a ne ajuta să depanăm acest tip de probleme de performanță în front-end-ul aplicațiilor noastre. Browserele au acum chiar și audituri de performanță integrate. Acest lucru poate ajuta la identificarea problemelor de la început, dar aceste audituri pot arăta o altă sursă de încetinire pe care nu o putem remedia în browser. Problema este legată de timpii de răspuns lenți ai serverului.

„E timpul până la primul octet”

Există foarte puține optimizări ale browserului pentru a îmbunătăți o pagină care este pur și simplu lent de construit pe server. Acest cost este suportat între browserul care face cererea pentru fișier și primirea răspunsului. Studierea diagramei în cascadă a rețelei în instrumentele pentru dezvoltatori va arăta această întârziere în categoria „În așteptare (TTFB)”. Acesta este cât timp așteaptă browserul între efectuarea cererii și primirea răspunsului.

Mai multe după săritură! Continuați să citiți mai jos ↓

În termeni de performanță, aceasta este cunoscută sub numele de Time to First Byte - cantitatea de timp necesară înainte ca serverul să înceapă să trimită ceva cu care browserul poate începe să lucreze. În acest timp de așteptare este cuprins tot ceea ce serverul trebuie să facă pentru a construi pagina. Pentru un site obișnuit, aceasta ar putea implica direcționarea cererii către partea corectă a aplicației, autentificarea cererii, efectuarea de apeluri multiple către sisteme backend, cum ar fi baze de date și așa mai departe. Ar putea implica rularea conținutului prin sisteme de șabloane, efectuarea de apeluri API către servicii terțe și poate chiar lucruri precum trimiterea de e-mailuri sau redimensionarea imaginilor. Orice lucru pe care serverul o face pentru a finaliza o solicitare este strivită în acel TTFB de așteptare pe care utilizatorul îl experimentează în browserul său.

Panoul de rețea din Chrome DevTools care arată inspecția unei singure solicitări de pagină
Inspectarea unei cereri de document arată timpul petrecut de browser în așteptarea răspunsului de la server.

Deci, cum reducem acest timp și începem să livrăm pagina mai rapid utilizatorului? Ei bine, aceasta este o întrebare mare, iar răspunsul depinde de aplicația dvs. Aceasta este munca de optimizare a performanței în sine. Ceea ce trebuie să facem mai întâi este să măsurăm performanța, astfel încât beneficiile oricăror modificări să poată fi judecate.

Antetul de sincronizare a serverului

Sarcina Server Timing nu este să vă ajute să cronometrați activitatea pe serverul dvs. Va trebui să faci singur cronometrarea folosind orice set de instrumente pe care platforma ta backend ți-l pune la dispoziție. Mai degrabă, scopul Server Timing este de a specifica modul în care acele măsurători pot fi comunicate browserului.

Modul în care se face acest lucru este foarte simplu, transparent pentru utilizator și are un impact minim asupra greutății paginii dvs. Informațiile sunt trimise ca un set simplu de anteturi de răspuns HTTP.

 Server-Timing: db;dur=123, tmpl;dur=56

Acest exemplu comunică două puncte de sincronizare diferite numite db și tmpl . Acestea nu fac parte din specificații - acestea sunt nume pe care le-am ales, în acest caz pentru a reprezenta anumite momente de bază de date și, respectiv, șablon.

Proprietatea dur indică numărul de milisecunde în care a durat operațiunea. Dacă ne uităm la cererea din secțiunea Rețea din Instrumente pentru dezvoltatori, putem vedea că timpurile au fost adăugate la diagramă.

Panoul Timings al unei solicitări de pagină în Chrome DevTools care arată o nouă secțiune Server Timing.
Apare o nouă secțiune de sincronizare a serverului, care arată intervalele setate cu antetul HTTP Server-Timing.

Antetul Server-Timing poate lua mai multe valori separate prin virgule:

 Server-Timing: metric, metric, metric

Fiecare măsurătoare poate specifica trei proprietăți posibile

  1. Un nume scurt pentru metrica (cum ar fi db în exemplul nostru)
  2. O durată în milisecunde (exprimată ca dur=123 )
  3. O descriere (exprimată ca desc="My Description" )

Fiecare proprietate este separată cu un punct și virgulă ca delimitator. Am putea adăuga descrieri la exemplul nostru astfel:

 Server-Timing: db;dur=123;desc="Database", tmpl;dur=56;desc="Template processing"
Panoul Timing al unei solicitări de pagină în Chrome DevTools care arată descrierile utilizate pentru valorile Server Timing.
Numele sunt înlocuite cu descrieri atunci când sunt furnizate.

Singura proprietate necesară este name . Atât dur cât și desc sunt opționale și pot fi utilizate opțional acolo unde este necesar. De exemplu, dacă trebuia să depanați o problemă de sincronizare care se întâmpla pe un server sau centru de date și nu pe altul, ar putea fi util să adăugați acele informații în răspuns fără o sincronizare asociată.

 Server-Timing: datacenter;desc="East coast data center", db;dur=123;desc="Database", tmpl;dur=56;desc="Template processing”

Acest lucru ar apărea apoi împreună cu timpul.

Panoul Timings al unei solicitări de pagină în Chrome DevTools care arată un Server Timing fără oră setată.
Este afișată valoarea „Centrul de date de pe coasta de est”, chiar dacă nu are calendare.

Un lucru pe care l-ați putea observa este că barele de sincronizare nu apar într-un model de cascadă. Acest lucru se întâmplă pur și simplu pentru că Server Timing nu încearcă să comunice secvența de timpi, ci doar valorile brute în sine.

Implementarea Timing Server

Implementarea exactă în cadrul propriei aplicații va depinde de circumstanțele dvs. specifice, dar principiile sunt aceleași. Pașii vor fi întotdeauna:

  1. Cronometrați unele operații
  2. Colectați împreună rezultatele calendaristice
  3. Ieșiți antetul HTTP

În pseudocod, generarea răspunsului ar putea arăta astfel:

 startTimer('db') getInfoFromDatabase() stopTimer('db') startTimer('geo') geolocatePostalAddressWithAPI('10 Downing Street, London, UK') endTimer('geo') outputHeader('Server-Timing', getTimerOutput())

Elementele de bază ale implementării a ceva în aceste linii ar trebui să fie simple în orice limbă. O implementare PHP foarte simplă ar putea folosi funcția microtime() pentru operațiunile de sincronizare și ar putea arăta ceva în sensul următorului.

 class Timers { private $timers = []; public function startTimer($name, $description = null) { $this->timers[$name] = [ 'start' => microtime(true), 'desc' => $description, ]; } public function endTimer($name) { $this->timers[$name]['end'] = microtime(true); } public function getTimers() { $metrics = []; if (count($this->timers)) { foreach($this->timers as $name => $timer) { $timeTaken = ($timer['end'] - $timer['start']) * 1000; $output = sprintf('%s;dur=%f', $name, $timeTaken); if ($timer['desc'] != null) { $output .= sprintf(';desc="%s"', addslashes($timer['desc'])); } $metrics[] = $output; } } return implode($metrics, ', '); } }

Un script de testare l-ar folosi ca mai jos, aici folosind funcția usleep() pentru a crea artificial o întârziere în rularea scriptului pentru a simula un proces care durează timp.

 $Timers = new Timers(); $Timers->startTimer('db'); usleep('200000'); $Timers->endTimer('db'); $Timers->startTimer('tpl', 'Templating'); usleep('300000'); $Timers->endTimer('tpl'); $Timers->startTimer('geo', 'Geocoding'); usleep('400000'); $Timers->endTimer('geo'); header('Server-Timing: '.$Timers->getTimers());

Rularea acestui cod a generat un antet care arăta astfel:

 Server-Timing: db;dur=201.098919, tpl;dur=301.271915;desc="Templating", geo;dur=404.520988;desc="Geocoding"
Panoul Timing al unei solicitări de pagină în Chrome DevTools care arată valorile de testare afișate corect.
Timingurile serverului setate în exemplu apar în panoul Timings cu întârzierile configurate în scriptul nostru de testare.

Implementări existente

Având în vedere cât de util este Server Timing, sunt relativ puține implementări pe care le-am putut găsi. Pachetul server-timing NPM oferă o modalitate convenabilă de a utiliza Server Timing din proiectele Node.

Dacă utilizați un cadru PHP bazat pe middleware, tuupola/server-timing-middleware oferă și o opțiune la îndemână. Am folosit asta în producție pe Notist de câteva luni și las întotdeauna activate câteva momente de bază dacă doriți să vedeți un exemplu în sălbăticie.

Pentru suport pentru browser, cel mai bun lucru pe care l-am văzut este în Chrome DevTools și asta am folosit pentru capturile de ecran din acest articol.

Considerații

Sincronizarea serverului în sine adaugă o suprasarcină foarte minimă răspunsului HTTP trimis înapoi prin fir. Antetul este foarte minim și, în general, poate fi trimis în siguranță fără să vă faceți griji cu privire la direcționarea numai către utilizatori interni. Chiar și așa, merită să păstrați numele și descrierile scurte, astfel încât să nu adăugați cheltuieli generale inutile.

O preocupare mai mare este munca suplimentară pe care ați putea-o face pe server pentru a cronometra pagina sau aplicația dvs. Adăugarea de timp și înregistrare suplimentară poate avea în sine un impact asupra performanței, așa că merită să implementați o modalitate de a activa și dezactiva acest lucru atunci când este necesar.

Utilizarea unui antet de sincronizare a serverului este o modalitate excelentă de a vă asigura că toate informațiile de sincronizare atât de la front-end, cât și de la back-end ale aplicației dvs. sunt accesibile într-o singură locație. Cu condiția ca aplicația dvs. să nu fie prea complexă, poate fi ușor de implementat și puteți fi operațional într-un interval de timp foarte scurt.

Dacă doriți să citiți mai multe despre sincronizarea serverului, puteți încerca următoarele:

  • Specificația de sincronizare a serverului W3C
  • Pagina MDN de pe Server Timing are exemple și detalii actualizate despre compatibilitatea browserului
  • Un articol interesant din partea echipei BBC iPlayer despre utilizarea de către ei a Server Timing.