Am construit un serviciu dedicat de stocare pentru loguri, XML, JSON, alte fișiere text și documente PDF.

Context

Serviciul este un API REST. Baza lui de date păstrează doar metadatele fiecărui fișier; conținutul se păstrează în foldere pe disc. Volumul de fișiere este mare, așa că am decis să comprimăm conținutul.

Provocarea

Comprimarea a economisit mult spațiu, dar fișierele mari se obțineau greu: clientul aștepta până se dezarhiva tot fișierul, abia apoi primea primul byte.

Întrebarea era dacă mai are rost să comprimăm.

Abordarea

Am păstrat comprimarea și am schimbat felul în care fișierele se scriu și se citesc.

  • Flux, nu dezarhivare întâi. Răspunsul se decomprimă din mers, în timp ce se trimite, așa că primii bytes pleacă imediat, iar memoria folosită nu depinde de mărimea fișierului.
  • Bytes comprimați, când clientul îi acceptă. Când un client acceptă codificarea în care e stocat fișierul, bytes-ii stocați pleacă așa cum sunt, cu antetul Content-Encoding. Serverul nu mai decomprimă nimic, iar prin rețea circulă mai puține date.
  • Un codec mai rapid. Fișierele noi se scriu cu Zstandard (zstd), care decomprimă de câteva ori mai repede decât gzip, la o rată de comprimare similară sau mai bună. Codecul se păstrează în metadatele fiecărui fișier, așa că fișierele vechi și cele noi se servesc în paralel.
  • Comprimăm doar ce se micșorează. Documentele PDF sunt deja comprimate în interior. Un fișier se păstrează comprimat doar dacă așa devine vizibil mai mic; altfel se păstrează așa cum e, fără codec în metadate.
HTTP
GET /files/7f3a…/content HTTP/1.1
Accept-Encoding: zstd, gzip

HTTP/1.1 200 OK
Content-Type: application/xml
Content-Encoding: zstd

Rezultatul

Fișierele rămân comprimate pe disc. Un fișier mare începe să sosească imediat ce e cerut, nu după ce a fost dezarhivat, iar clienții care acceptă răspunsuri comprimate primesc de câteva ori mai puține date.