# Diagnostika zpoždění HTTP požadavků: od vyvažovače zátěže po jádro Linuxu
Rost odpovědi nebo náhlé chyby 5xx v produkci vyžadují okamžitou a přesnou lokalizaci problému. Místo chaotické kontroly služeb je efektivnější použít systémový přístup, který rozdělí celý pipeline zpracování požadavku na síťový a aplikační segment. Probereme metodu rychlého hledání úzkých míst s využitím standardních logů Nginx, hlaviček Server-Timing a nízkourovňových metrik TCP_INFO.
Výchozí bod: analýza logů vyvažovače zátěže
Architektura typické webové aplikace zahrnuje několik vrstev: uživatel, CDN, vyvažovač zátěže (SLB), aplikace, pool spojení a databázový systém. Každá z nich může přidávat zpoždění, ale výchozím bodem pro diagnostiku by měl vždy být vyvažovač. Právě on je ve středu pipeline a umožňuje okamžitě určit směr hledání.
Pro Nginx jsou klíčové dvě proměnné: $request_time a $upstream_response_time. První zaznamenává celkový čas zpracování požadavku od přijetí prvního bajtu od klienta po odeslání posledního bajtu odpovědi. Druhá měří výhradně čas čekání na odpověď od upstream serveru. Pokud se tyto metriky ještě nesbírají, je nutné rozšířit formát logování:
log_format timing '$remote_addr - $request_uri '
'status=$status '
'rt=$request_time '
'uct=$upstream_connect_time '
'urt=$upstream_response_time';
access_log /var/log/nginx/access.log timing;
Interpretace dat vychází z jednoduchého porovnání. Pokud je $upstream_response_time blízko $request_time, úzké místo je vpravo od vyvažovače: v kódu aplikace, poolu spojení nebo databázi. Pokud je $upstream_response_time v normě a $request_time abnormálně vysoký, problém je lokalizován vlevo: v síťové infrastruktuře, směrování CDN nebo na straně klienta. Je důležité vzít v úvahu, že vkládání $request_time do hlaviček odpovědi přes add_header se pro přesné měření nedoporučuje, protože Nginx vytváří hlavičky před dokončením přenosu těla odpovědi. Spolehlivá data jsou dostupná pouze v access logu po uzavření spojení.
Lokalizace problémů na straně aplikace
Když vyvažovač ukazuje na zpoždění v upstream, je nutné detailizovat vnitřní operace aplikace. Standard W3C Server-Timing umožňuje předat klientovi nebo systému monitoringu přesné měření času provedení jednotlivých fází zpracování požadavku. Hlavička má tvar: Server-Timing: app;dur=120, db;dur=95, pool-wait;dur=18. To poskytuje průhlednost bez zavádění těžkých APM agentů.
Integrace hlavičky do stacku aplikace vyžaduje minimální změny. Příklady implementace pro oblíbené jazyky:
Go (net/http):
start := time.Now()
rows, err := db.QueryContext(ctx, query)
dbDur := time.Since(start)
w.Header().Set("Server-Timing",
fmt.Sprintf("db;dur=%.2f", float64(dbDur.Microseconds())/1000))
Python (Django middleware):
class ServerTimingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start = time.monotonic()
response = self.get_response(request)
dur = (time.monotonic() - start) * 1000
response["Server-Timing"] = f"app;dur={dur:.2f}"
return response
Node.js (Express):
app.use((req, res, next) => {
const start = process.hrtime.bigint();
res.on('finish', () => {
const ms = Number(process.hrtime.bigint() - start) / 1e6;
// už odesláno, ale pro logování:
console.log(`Server-Timing: app;dur=${ms.toFixed(2)}`);
});
// pro hlavičku – měříme do odpovědi:
const origEnd = res.end;
res.end = function(...args) {
const ms = Number(process.hrtime.bigint() - start) / 1e6;
res.setHeader('Server-Timing', `app;dur=${ms.toFixed(2)}`);
origEnd.apply(this, args);
};
next();
});
Pro předávání metrik samotného Nginx přes Server-Timing je nutné použít direktivu map, aby se zabránilo předávání prázdných hodnot při obsluze statiky nebo chyb:
Nginx (upstream timing jako Server-Timing):
# V http {} bloku nginx.conf:
map $upstream_header_time $server_timing_upstream {
"-" "";
default "ngx-upstream;dur=$upstream_header_time;desc=\"NgxUpstream\"";
}
# V location {} bloku vašeho serveru:
add_header Server-Timing-Ngx "ngx-total;dur=$request_time;desc=\"NgxTotal\"" always;
add_header Server-Timing-Ngx $server_timing_upstream always;
Všimněte si použití předpony Server-Timing-Ngx a proměnné $upstream_header_time. Prohlížeče očekávají hodnoty v milisekundách, zatímco Nginx vrací sekundy. Navíc $upstream_header_time zaznamenává okamžik přijetí hlaviček od upstream, což přesně odráží čas generování odpovědi, na rozdíl od $upstream_response_time, která se může vynulovat za určitých podmínek buferizace.
Analýza získaných dat umožňuje rychle klasifikovat incident:
- Dominance
db;durukazuje na neoptimální SQL dotazy, chybějící indexy nebo blokování tabulek. - Vysoké
pool-wait;dursignalizuje vyčerpání limitu spojení v PgBounceru nebo podobném pooleru. - Velké
app;durpři malémdb;durmluví o CPU-vázaných operacích, blokujícím I/O nebo únicích paměti v runtime. - Chyby 502/504 na vyvažovači při normálních timingách obvykle znamenají pád procesu aplikace nebo překročení timeoutu na úrovni orchestrátoru.
Síťový segment: fáze HTTP a metriky jádra
Pokud upstream odpovídá rychle a celkové zpoždění roste, problém je v síťové trase. Každý HTTP požadavek prochází šesti po sobě jdoucími fázemi: DNS, Connect (TCP handshake), TLS handshake, Send, Wait (TTFB) a Receive. Anomaly v konkrétních fázích okamžitě zúží okruh hledání. Dlouhý DNS ukazuje na problémy resolveru nebo složité řetězce CNAME. Vysoké hodnoty Connect a TLS svědčí o síťovém zpoždění do edge uzlu CDN, absenci TLS session resumption nebo použití zastaralých protokolů. Pokud jsou Connect a TLS minimální, ale Wait abnormálně vysoké, zpoždění vzniká na úrovni WAF, CDN workerů nebo při fetch požadavku k origin.
Pro hlubokou diagnostiku síťových problémů nestačí standardní HTTP breakdown. Je nutné obrátit se k metrikám jádra Linux přes getsockopt(TCP_INFO). Jádro sleduje každé TCP spojení a poskytuje přesná data: RTT, počet retransmitů, velikost congestion window (cwnd) a RTO. Tyto ukazatele jsou kriticky důležité, protože HTTP timingy nedokážou oddělit síťové zpoždění od času zpracování serveru, když odpověď vejde do jednoho TCP segmentu. Odečtením RTT jádra z fáze Wait technik získá reálný čas zpracování požadavku. Retransmity a stlačený cwnd přímo ukazují na ztrátu paketů a práci algoritmů kontroly přetížení, které přidávají stovky milisekund k každému požadavku. Kombinace aplikačních hlaviček a nízkourovňových síťových metrik vytváří úplný obrázek observability bez závislosti na externích vendorech.
Co je důležité
- Porovnání
$request_timea$upstream_response_timev Nginx okamžitě rozdělí zodpovědnost mezi sítí a aplikací. - Hlavička Server-Timing zajišťuje granulární viditelnost vnitřních zpoždění (DB, pooly, runtime) bez zavádění těžkých APM systémů.
- Analýza fází HTTP požadavku umožňuje přesně identifikovat problémy DNS, TLS handshaků a směrování CDN.
- Metriky TCP_INFO z jádra Linux poskytují objektivní obrázek síťových ztrát a zpoždění, které nelze zachytit na aplikační úrovni.
- Systémový přístup k diagnostice latence zkracuje MTTR a vylučuje chaotické restartování služeb během incidentů.
— Editorial Team
Zatím žádné komentáře.