NaplóindexDockup / terepjegyzet
Note / unexpected-egress-charges

Váratlan egressköltségek: honnan jönnek a sávszélességszámlák?

A váratlan egressköltségek általában négy szokásra vezethetők vissza: média kiszolgálása az alkalmazásból, hiányzó cache headerek, túl sok API-kommunikáció és régiók közötti forgalom. Derítsd ki a forrást, és csökkentsd a számlát szolgáltatóváltás nélkül.

Megérkezik a számla, és négyszer akkora, mint amire számítottál. A compute költsége nagyjából megfelel a tervezettnek. Az eltérő tétel az egress — az infrastruktúrádat elhagyó bájtok —, és jó eséllyel még egyszer sem gondoltál rá.

A váratlan egressköltségek jelentik az egyik leggyakoribb meglepetést az alkalmazások hosztolásakor, ennek pedig strukturális oka van: a fejlesztési folyamatodban semmi nem méri a bájtokat. A laptopod nem számláz értük. A staging környezetben nincsenek felhasználók. A sávszélesség először a számlán válik láthatóvá, addigra viszont már élesítetted az azt okozó szokást.

Nézzük meg, honnan származik valójában, a leggyakoribb okok sorrendjében.

1. Média kiszolgálása az alkalmazásból

Ez messze felülmúlja a többi okot, és szinte mindig véletlenül történik.

Beteszel egy videót a /public könyvtárba, hogy bemutass valamit. Működik, ezért ott marad. Mostantól minden oldalmegnyitáskor ez a fájl streamelődik ki a konténeredből. Egy 40 MB-os videó egy havi ezer látogatót fogadó oldalon 40 GB forgalmat jelent — egy olyan fájl miatt, amit eredetileg csak ideiglenesnek gondoltál.

Ugyanez vonatkozik a termékképekre, PDF-ekre, felhasználói feltöltésekre és fontfájlokra is. Amikor hozzáadod őket, egyik sem tűnik infrastruktúrát érintő döntésnek.

A megoldás nem bonyolult: a statikus médiafájloknak egy CDN mögötti object storage-ban van a helyük, nem az alkalmazásod fájlrendszerében. Az alkalmazásod HTML-t és JSON-t szolgáljon ki. Amint minden látogatónak egy 4 MB-os hero képet szolgál ki, a CDN feladatát végzi, csak éppen a CDN gazdaságossági előnyei nélkül.

2. Hiányzó cache headerek

Ha a válaszaidban nincsenek cache headerek, minden látogató minden oldalbetöltéskor letölti az összes assetet. A visszatérő látogatók újra letöltik az egészet. Egy crawler naponta több tucatszor is letöltheti őket.

# Fingerprinted build assets never change — cache them for a year
Cache-Control: public, max-age=31536000, immutable

# HTML changes — revalidate but allow a short window
Cache-Control: public, max-age=0, must-revalidate

# Anything user-specific
Cache-Control: private, no-store

Ez válaszosztályonként egyetlen sor módosítása, amely rendszeresen a sávszélességszámla nagy részét eltünteti, mivel a megszüntetett forgalom teljes egészében ismétlődésből származik.

3. A kliens által fel nem használt adatokat is visszaadó API-k

Egy listázó endpoint, amely teljes objektumokat ad vissza, miközben a UI csak három mezőt jelenít meg, minden egyes kérésnél újra és újra elküldi a különbséget. Profilozáskor ez sosem tűnik fel, mert gyors — egyszerűen csak nagy.

A legforgalmasabb endpointjaidon két dolgot ellenőrizz:

  • Be van kapcsolva a tömörítés? A Content-Encoding: gzip vagy br JSON esetén jellemzően 70–80%-kal csökkenti a méretet. Ez egy middleware-sor, mégis gyakran hiányzik.
  • Küldesz olyan mezőket, amelyeket senki nem olvas? A teljes sor szerializálása azért, mert az ORM-mel így volt a legegyszerűbb, a legtöbb codebase alapértelmezett működése.

Egy pollingot használó kliens mindkét problémát annyival súlyosbítja, ahányszor percenként lekérdez.

4. Régiók és szolgáltatások közötti forgalom

Ha az alkalmazásod az egyik régióban, az adatbázisod pedig egy másikban található, minden lekérdezési eredmény egy díjköteles határon halad át. Ezt könnyű véletlenül előidézni: először létrehozod az adatbázist, gondolkodás nélkül kiválasztasz egy régiót, majd hetekkel később máshová helyezed az alkalmazást.

A saját szolgáltatásaid közötti forgalom is egressnek számíthat, ha elhagyja a privát hálózatot, majd egy publikus hostname-en keresztül tér vissza. Ha két, ugyanabban a workspace-ben lévő szolgáltatás a publikus URL-jén kommunikál egymással, kétszer fizetsz egy olyan beszélgetésért, amelynek valójában nem kellett volna elhagynia a hálózatot.

A Dockupon ezt a konkrét hibát nehéz elkövetni, mert a szolgáltatások belső név alapján érik el egymást. Az egyik szolgáltatás a main-db.internal:5432, egy másik pedig a <slug>.internal alias segítségével érhető el — a workspace hálózatán belül maradó forgalom sosem ér el publikus listenert. Ez az oka annak is, hogy az adatbázis alapértelmezés szerint nem kap publikus hostname-et: így nincs mit véletlenül azon keresztül továbbítani.

Ne találgass, hanem keresd meg a forrást

Ha találgatod, a négy ok közül melyikről van szó, elpazarolsz egy számlázási ciklust. Inkább mérj:

A hozzáférési naplót bájtok, ne kérések száma alapján olvasd. A leggyakoribb válaszok helyett a kiszolgált bájtok teljes mennyisége alapján rendezd a válaszokat. A legtöbb adatot küldő endpoint ritkán az, amelyiket a legtöbbször hívják.

Ellenőrizd a legnagyobb statikus asseteket. Ha bármi egy megabájtnál nagyobb fájlt szolgál ki az alkalmazásodból, azt helyezd át elsőként.

# What is the service actually doing right now
dockup metrics my-project/my-api --json

# And what is it logging
dockup logs my-project/my-api -n 1000

Figyelj a crawlerekre. Egy rosszul működő bot, amely ismételten nagy fájlokat tölt le, egy szerény emberi forgalmú webhely havi egressforgalmának nagy részét is generálhatja. A robots.txt és a preview környezeteken beállított noindex olcsó megoldás.

A senki által nem számolt környezetek

Két szokás olyan egressforgalmat generál, amely senkinek nem szerepel a mentális modelljében:

Preview környezetek. Pull requestenként egy preview környezet valóban hasznos, és közben észrevétlenül megsokszorozza az infrastruktúrádat. Öt nyitott PR öt példányt jelent a stackből, mindegyik saját forgalommal — gyakran ugyanazoktól a crawlerektől, mivel a preview URL-ek indexelődnek, ha nem állítod meg őket.

Hosszú életű staging. Egy nyolc hónapja futó staging környezetet, amelyet senki nem látogat, továbbra is töltenek az image-ek, továbbra is crawlerek keresik fel, és továbbra is futtatja a cron jobokat.

Egyik sem ok arra, hogy felhagyj a használatukkal. Mindkettő ok arra, hogy korlátozd őket: a PR lezárásakor járjanak le a preview környezetek, és állítsd be rajtuk a noindex értéket, hogy a keresőmotorok ne töltsék le őket helyetted.

dockup noindex my-project/my-api --on

Így néz ki a jó számlázás

Még a számla megérkezése előtt tudnod kell válaszolni három kérdésre:

  1. Mi fut jelenleg? Azokat is beleértve, amelyekről megfeledkeztél.
  2. Mennyit fogyasztott mindegyik? A compute- és az átviteli költséget külön bontva, nem egyetlen számként.
  3. Mi történik, ha megugrik a forgalom? Egy szolgáltatásokat leállító limit kellemetlen. Egyáltalán nem létező limit még rosszabb.

A Dockup az infrastruktúrát a plantól külön méri, így a plan díja nem rejti el a használat költségét — a Pro plan 20 dolláros kreditje pedig erre a használatra vonatkozik, nem a díjból ad kedvezményt. A lényeg, hogy lásd, melyik költség melyik.

Röviden

Helyezd át a médiafájlokat object storage-ba. Állíts be cache headereket. Kapcsold be a tömörítést. Tartsd az alkalmazásokat és az adatbázisaikat egy régióban, és hagyd, hogy a publikus internet helyett a privát hálózaton kommunikáljanak. Járasd le a preview környezeteket, és zárd ki őket a keresési találatokból.

Ez az öt szokás szinte minden váratlan sávszélességszámlát kezel, és egyikhez sem kell megváltoztatnod, hol hosztolod a rendszert.

Gyakran ismételt kérdések

Mi az egress? Az infrastruktúrádat az internet felé elhagyó adat. A felhasználóknak küldött válaszok, a letöltött fájlok és az API-payloadok mind ide tartoznak. A bejövő forgalom általában ingyenes, a kimenő viszont többnyire nem.

Miért magasabb az egressszámlám, mint a compute költsége? Szinte mindig azért, mert az alkalmazás olyan fájlokat szolgál ki, amelyeknek egy CDN-en lenne a helyük. Egy népszerű oldalon egyetlen nagy asset több heti requestkezelés költségét is meghaladhatja.

Tényleg csökkenti ezt egy CDN? Igen, ha cache-el. Az origin edge-enként egyszer szolgálja ki a fájlt, nem minden egyes látogatónak, a CDN gigabájtonkénti ára pedig jellemzően töredéke egy alkalmazásplatforménak.

A preview környezetek ugyanannyiba kerülnek, mint a production? Annyiba kerülnek, amennyit fogyasztanak — ez gyakran több a vártnál, mert mindegyik egy teljes példány, és a preview URL-eket crawlerek keresik fel, ha nem akadályozod meg.