Оптимизация CDN и latency reduction
1) Цели и карта задержек
Latency = DNS + TCP/TLS + TTFB (сервер/ориджин/кэш) + доставка контента (RTT×объемы) + рендер клиента.
Оптимизация = сокращаем количество RTT, уменьшаем байты и переносим вычисления/кэш ближе к пользователю.
2) Архитектура CDN
Anycast POPs — ближний узел по BGP-маршрутизации.
Tiered caching / Origin Shield — «зонтичный» промежуточный слой, снижающий miss-шторм на ориджине.
Geo-/Regional routing — привязка тенанта/юрисдикции (суверенитет данных, лицензии).
Failover — резервный ориджин/регион, health-пробы и быстрый переключатель.
3) Кэш: ключи, заголовки, стратегии
3.1 Ключи кэша (cache key)
По умолчанию: `scheme + host + path +?query`.
Добавляйте только нужные параметры (`?v=`, `?lang=`, `?tenant=`). Остальные — в ignore-params.
`Vary` — минимальный: `Accept-Encoding`, `Accept-Language` (если правда нужен), `Authorization` обычно ломает кэш.
3.2 Политики
Public статика: `Cache-Control: public, max-age=31536000, immutable` + rev (hash в имени).
Полудинамика (каталоги, правила, FAQ): `s-maxage=300, stale-while-revalidate=600, stale-if-error=86400`.
API-GET: используйте ETag/Last-Modified, `SWR/SIE`, включайте coalescing (один запрос на горячий ключ).
Private: персональные ответы — на периметре через edge-compute (ESI/kv) или пер-тенант кэш.
3.3 Анти-шторм
Request coalescing — схлопывать одновременные miss запросы.
Serve-stale — отдавать устаревший объект при сбое ориджина.
Background revalidation — обновлять в фоне.
4) HTTP/2–3, TCP/TLS и ранняя отдача
HTTP/2: мультиплекс, сжатие заголовков; ограничьте `max concurrent streams`, крупные заголовки.
HTTP/3 (QUIC): крупное снижение TTFB на мобильных/высоких потерь; следите за Initial-порогами и Retry.
TLS 1.3: 1-RTT handshake; OCSP stapling; HSTS.
0-RTT: только для идемпотентных `GET` и если риски replay учтены.
103 Early Hints: ранние `Link: rel=preload` для критичных ресурсов.
Preconnect / DNS-prefetch: `<link rel="preconnect" href="https://cdn.example">`.
5) Edge-compute и «тонкая персонализация»
На краю: перепись заголовков, гео/тенант-фиксация, A/B-маркировка, легкая персонализация без запроса к ориджину.
Правило: не хранить PII на POP-узлах; кэшировать только агрегаты/публичные данные.
6) Оптимизация медиа и форматов
Изображения: автоматическая конверсия в WebP/AVIF, resize-on-edge, `srcset/sizes`, `lazyload`.
Компрессия: Brotli для текстов (HTML/CSS/JS/JSON), gzip fallback.
Видео: HLS/DASH, CDN-segment caching, `preload=metadata`, постер.
Шрифты: subset + `font-display: swap`; хостить с долгим кэшем.
Критический CSS: инлайн первый экран; остальное — async.
7) API-паттерны и кэширование
Idempotent GET — кэшируем по ключам запроса (включая версию данных).
ETag: сильный хеш полезной нагрузки + `If-None-Match`.
Surrogate-Control (CDN-специфика) для отличия от `Cache-Control` клиента.
Signed URLs — для приватной статики/медиа.
GraphQL: нормализуйте кеш-ключ по операции/переменным; используйте partial caching/резолвер-кэш.
WebSockets: для real-time — сокращайте сообщения, сжимайте (permessage-deflate), располагайте WS-шарды ближе к пользователю.
8) Примеры конфигураций
8.1 NGINX (ориджин: кэшируем API-GET)
nginx
We give SWR and ETag location/api/v1/catalog/{
proxy_cache api_cache;
proxy_cache_key "$scheme$request_method$host$uri$is_args$args";
proxy_cache_valid 200 5m;
proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
add_header Cache-Control "public, s-maxage=300, stale-while-revalidate=600, stale-if-error=86400";
add_header ETag $upstream_http_etag;
proxy_ignore_headers Set-Cookie; # do not break the Set-Cookie proxy_hide_header cache;
proxy_pass http://catalog;
}
8.2 Fastly VCL (SWR, coalescing, ignore cookies)
vcl sub vcl_recv {
set req. hash_ignore_busy = true; # coalescing if (req. url. qs ~ "^(?!.(lang v)=)") { remove req. url. qs; }
if (req. http. Cookie) { remove req. http. Cookie; }
}
sub vcl_backend_response {
set beresp. ttl = 300s;
set beresp. stale_if_error = 86400s;
set beresp. stale_while_revalidate = 600s;
if (beresp. http. Set-Cookie) { unset beresp. http. Set-Cookie; }
}
8.3 Cloudflare (Transform Rules, Cache Rules, Early Hints — псевдо)
json
{
"cache_rule": {
"if": "http. request. uri. path matches \"/assets/.\"",
"action": {"cache": {"eligibility":"eligible", "ttl": 31536000}}
},
"transform_rule": {
"set_headers": [{"name":"Cache-Control","value":"public, s-maxage=300, stale-while-revalidate=600"}]
},
"early_hints": {"enable": true}
}
9) Мобильные сети и «неустойчивый» интернет
Агрессивно используйте HTTP/3; уменьшайте размер критического пути (HTML+critical CSS < 14 KB).
Priority H2/H3: расставьте приоритеты (HTML→CSS→JS→медиа позже).
Ретрай-политика с джиттером, idempotency для API.
Size-budgets и бандлинг: код-сплиттинг, deferred JS, удаление неиспользуемого CSS/JS.
10) Наблюдаемость и SLO
RUM: TTFB, LCP, INP, CLS по регионам/ASN/тенантам; распределения p95/p99.
Синтетика: контрольный маршрут «/health/cdn» по POP-ам.
Кэш-метрики: hit-ratio overall и per-key; origin fetch rate; coalescing savings.
Алерты: падение hit-ratio, рост origin-egress, деградация H3-долей, 5xx на shield.
11) Специфика iGaming/финансов
Каталоги игр/коэффициенты: короткое `s-maxage` + SWR; region-aware ключ (`tenant|region|lang`).
Событийные пики (матчи, розыгрыши): прогрев кэша (pre-warm), «заморозка» тяжелых персонализаций, mirror-источники.
Платежные/кабинет: не кэшировать приватные, но ускорять через H3 + edge-TLS и близкий регион.
Юрисдикции: разделенные домены/пути per-регион; контроль `Vary: X-Region`.
12) Антипаттерны
`Vary: ` на все подряд; кэш-ключ зависит от лишних куки/заголовков.
Отсутствие SWR/SIE → «черные экраны» при коротких сбоях ориджина.
Очистка кэша «по всему» вместо точечной инвалидации по тегам/ключам.
Ресурсы без ревизии имен и с `max-age=0`.
Глобальный deny-cache для `Authorization` даже там, где отдается public.
Отсутствие coalescing → шторм на ориджине.
Преждевременная «тяжелая» персонализация на POP.
13) Чек-лист prod-готовности
- Anycast POP + tiered/shield; health-проверки и origin failover.
- Ключи кэша минимальны; игнор лишних query/cookies; `Surrogate-Control`.
- SWR/SIE включены, coalescing активен; serve-stale при ошибках.
- HTTP/3 включен; TLS 1.3; 103 Early Hints настроен для критичных ресурсов.
- Изображения: AVIF/WebP, resize-on-edge; Brotli для текстов.
- API-GET с ETag/Last-Modified; идемпотентность/ретраи; не кэшировать приватные профили.
- Preconnect к доменам статики; критический CSS инлайн.
- Метрики: hit-ratio, origin-egress, TTFB/LCP p95, H3-доля, по регионам/тенантам.
- План прогрева кэша перед событиями; точечная инвалидация (теги).
- Документация Vary/keys/TTL; плейбук инцидентов (падение hit-ratio).
14) TL;DR
Сведите походы к ориджину к минимуму: tiered/shield + правильные cache-keys + SWR/SIE + coalescing. Включите HTTP/3/TLS 1.3, используйте 103 Early Hints и preconnect. Сжимайте и конвертируйте медиа на краю, инлайньте критический CSS. Для API — ETag, аккуратный `Vary`, идемпотентность и разумное кэширование `GET`. Мерьте hit-ratio, TTFB/LCP p95, origin egress и заранее прогревайте кэш на пиках.