Edge-кеши и POP
1) Что такое POP и зачем «край»
POP (Point of Presence) — узел сети доставки контента (CDN/edge), географически близкий к пользователю. Edge-кеш — слой хранения ответов прямо в POP, который уменьшает:- Латентность (меньше RTT до клиента).
- Нагрузку и стоимость на origin (offload).
- Трафик между регионами/облаками (egrеss-экономия).
Edge — это не только кеш. Современные POP поддерживают L7-маршрутизацию, WAF/бот-фильтры, rate-limit, A/B/канареечки, трансформации и edge-compute (скрипты/функции).
2) Архитектуры edge-кеширования
2.1 Плоская vs многоуровневая (tiered)
Плоская: каждый POP ходит на origin. Просто, но дорого для origin.
Tiered/Shield: POP → Shield POP (центральный кэш) → origin. Shield аккумулирует кеш-промахи, создает «зонтик» для origin.
2.2 Региональные сегменты
Разделяйте кэширующие домены по регионам/юрисдикциям (GDPR/локализация данных).
Вариант: «EU-only POPs» и «Global POPs», раздельные ключи/правила.
2.3 Anycast + latency/geo-aware роутинг
Anycast приводит клиента в ближайший POP по BGP.
Geo/latency-aware переключает между POP/региональными пулами по активным измерениям RTT/ошибок.
3) Ключи кэша, `Vary`, TTL и свежесть
3.1 Дизайн ключей
Нормализуйте запросы: сортируйте query-параметры, удаляйте шум (utm, ref).
Включайте семантические оси: `tenant`, `locale`, «версию схемы» (`v=3`), но избегайте PII.
Для приватного контента — разделять публичный и приватный кеш (см. §7).
3.2 Контроль кэширования (HTTP)
Заголовки:- `Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=60, stale-if-error=120`
- `ETag`/`Last-Modified` для условных GET (304).
- Vary: минимизируйте кардинальность (`Accept-Encoding`, `Accept-Language`, иногда `Authorization`/`Cookie` для приватных путей).
- Micro-cache для «почти-динамики»: 1–5 секунд + SWR.
3.3 Stale стратегии
SWR (stale-while-revalidate): отдаем устаревший ответ и фоном обновляем.
SIE (stale-if-error): при ошибке origin используем кеш до `SIE`-TTL.
Soft/Hard TTL: мягкий срок (можно stale), жесткий (полный промах).
4) Инвалидация: как обновлять «край»
4.1 По ключу и по тегам
PURGE/BAN по URL/префиксу — грубо, но быстро.
Surrogate-Key/Tags: присваивайте объектам теги (`article:42`, `category:7`), баньте по тегу — массовая инвалидация без перебора URL.
4.2 Событийная инвалидация
При изменении данных в origin публикуйте события (Kafka/NATS) → edge-инвалидаторы вызывают BAN/PURGE/soft-expire.
4.3 Версионирование артефактов
Для статики — content-hash в имени файла.
Для API — меняйте версию ключа (`v=4`) при несовместимых изменениях.
5) Защита origin и производительность
5.1 Origin shielding
Включайте Shield POP как единственную точку промахов → кратно снижает шторма по origin.
5.2 Coalescing/single-flight
На краю один запрос «пробивает» кеш при промахе; остальные ждут (нет догоняющего stampede).
5.3 Rate-limit/Queue/Shedding на edge
При перегрузке — сбрасывайте низкоприоритетные/анонимные запросы в POP, а не на origin.
5.4 Signed URL / Signed Cookie
Origin скрыт за edge. Доступ к приватному контенту — по подписанным ссылкам/куки с TTL и атрибутами (IP/Geo/Path), чтобы не раздавать «всем».
6) Транспорт и трансформации
6.1 HTTP/2–3 и QUIC
HTTP/2: мультиплексирование, хедер-компрессия.
HTTP/3/QUIC: меньше HOL-блокировок и лучше на потерьных каналах → ниже p95/p99 TTFB.
6.2 Компрессия и образы
Brotli для текста, AVIF/WebP для изображений, image-resizing на краю (responsive sizes, DPR).
Кеш-варианты по формату/размеру: ключи включают `width/format` (или `Vary: Accept`/Client-Hints).
6.3 TLS/0-RTT (аккуратно)
Ресъмплинг сессий ускоряет установку, 0-RTT может быть уязвим к replay → включайте только для идемпотентных GET.
7) Публичный vs приватный edge-кеш
7.1 Публичный
`Cache-Control: public, s-maxage=…` и минимальный `Vary`.
Подходит для каталога, новостей, изображений, CDN статики.
7.2 Приватный/персонифицированный
Опции:- Не кэшировать на шаред-уровне: `Cache-Control: private` (кеш браузера).
- Key-segmentation: включайте tenant/user-id (или токен-хэш) в ключ и помечайте как private-shared (осторожно с хранилищем и PII).
- Signed cookies и Edge-auth: кеш публичен, но доступ по подписи (варианты с encrypted session state на краю).
8) Edge-compute (Workers/Functions)
Легкие функции на POP: переписывание пути/заголовков, A/B-сплит, нормализация ключей, SWR-логика, prefetch соседних ресурсов.
Локальный KV/Cache API на POP для миллисекундных операций.
Ограничения: короткие таймауты/память, отсутствие долгоживущих соединений, внимательная работа с PII/региональностью.
Псевдо-пример (Workers-like)
js export default {
async fetch(req, env) {
const key = normalize(req);
let res = await caches. default. match(key);
if (res) return withHitHeader(res, "HIT");
res = await fetch(req, { cf: { cacheEverything: true }});
const ttl = computeTTL(res);
eventWaitUntil(caches. default. put(key, res. clone(), { expirationTtl: ttl }));
return withHitHeader(res, "MISS");
}
}
9) Примеры конфигураций
9.1 Nginx: micro-cache + SWR
nginx proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api:200m inactive=30m;
map $request_method $skip_cache { default 0; POST 1; PUT 1; DELETE 1; }
server {
location /api/list {
proxy_cache api;
proxy_cache_key "$scheme://$host$uri$is_args$args";
proxy_cache_valid 200 2s; # micro-cache proxy_cache_use_stale error timeout updating;# SIE + SWR proxy_cache_background_update on;
add_header X-Edge-Cache $upstream_cache_status;
proxy_pass http://origin_pool;
}
}
9.2 Varnish: surrogate keys и BAN
vcl sub vcl_recv {
if (req. method == "BAN") {
if (req. http. Surrogate-Key) {
ban("obj. http. Surrogate-Key ~ " + req. http. Surrogate-Key);
return (synth(200, "Banned"));
}
}
}
sub vcl_deliver {
set resp. http. Surrogate-Key = "article:42 tag:author:7";
set resp. http. Cache-Control = "public, s-maxage=300, stale-while-revalidate=60";
}
9.3 Envoy (edge-cache фильтр)
yaml http_filters:
- name: envoy. filters. http. cache typed_config:
"@type": type. googleapis. com/envoy. extensions. filters. http. cache. v3. CacheConfig typed_config:
"@type": type. googleapis. com/envoy. extensions. http. cache. simple_http_cache. v3. SimpleHttpCacheConfig
9.4 CloudFront-style поведение (эскиз)
Behavior A: `/images/` — длинный TTL, компрессия, vary по форматам.
Behavior B: `/api/` — короткий TTL, SWR, signed cookie, WAF/бот-защита.
Origin Shield включен, статусы 500/502/504 → `stale-if-error`.
10) Наблюдаемость, SLO и отчетность
10.1 Метрики
cache_hit_ratio (по POP/региону/route), byte_hit_ratio.
origin_offload = 1 − (origin_requests / edge_requests).
TTFB/TTL по квантилям, stale_responses_total, revalidations_total.
stampede_prevented_total, coalesced_waiters.
shield_hit_ratio (при tiered), origin_egrеss_bytes (стоимость).
10.2 Логи/трейсы
Логи с метками `HIT/MISS/STALE/UPDATING/BYPASS`, ключ, TTL, POP, tenant.
В распределенных трейсах отмечайте источник (`edge`, `origin`) и причину (revalidate/stale/error).
10.3 SLO-примеры
«Для `/api/list`: p99 TTFB ≤ 250 мс, edge hit ≥ 70%, byte-hit ≥ 80%, origin error-offload ≥ 90%».
«Доля `stale-if-error` ответов ≤ 1% за сутки».
11) Безопасность, приватность, соответствие
WAF/бот-менеджмент — на edge для фильтрации до origin.
Региональность данных: храните приватные артефакты только в допустимых POP; используйте регионо-специфичные ключи и ACL.
Подписи и токены на edge, не отдавайте приватные ответы из публичного кеша.
PII-минимизация: не включайте персональные данные в ключи; шифруйте cookie; короткие TTL для персонализации.
12) Типовые рецепты
12.1 «Почти динамика» (ленты/списки)
Micro-cache 1–3 с + SWR на edge, shield включен, single-flight, negative-cache для пустых результатов 1–5 с.
12.2 Облака изображений/медиа
Edge-ресайз/форматирование (WebP/AVIF), кэш-варианты по `width/format`, длинные TTL, инвалидация по тегам контента.
12.3 API с персонализацией
`Cache-Control: private` или signed cookie + ключ-сегментация (tenant), короткие TTL, SWR для «почти публичных» частей ответа.
12.4 Большие распродажи/пики
Прогрев ключевых ресурсов (prewarm), увеличение TTL на статику, агрессивный SWR/SIE, жесткие лимиты на origin, включенный Shield.
13) Анти-паттерны
Без `Vary` при различающихся ответах → утечки/неправильные данные.
Огромный `Vary` → кардинальность → низкий hit.
Общий кэш для prod/experiments → загрязнение.
Нет single-flight → шторм промахов на origin.
SWR без ограничений → гонки обновления и лавина validate-запросов.
Edge-кеш приватных ответов как public → инциденты безопасности.
Отсутствие tiered/shield при worldwide-нагрузке → перегрев origin.
14) Чек-лист внедрения
- Картируйте POP-покрытие, включите anycast + latency-routing.
- Выберите tiered/shield и политики single-flight/coalescing.
- Спроектируйте ключи и Vary (минимальная кардинальность, без PII).
- Настройте TTL / SWR / SIE (soft/hard TTL) и negative-cache.
- Включите signed URL/cookie, спрячьте origin, включите WAF/бот-фильтры.
- Организуйте инвалидацию: Surrogate-Key/BAN + event-driven.
- Поднимите метрики hit/byte-hit/offload/TTFB и дашборды per-POP.
- Прогрев перед пиками, runbooks на шторм/перегрузку.
- Тесты на приватность/региональность, аудит ключей и политик.
- SLO/ошибочный бюджет для edge и критерии авто-твиков TTL/SWR.
15) FAQ
Q: Как выбрать TTL на краю?
A: Оттолкнитесь от допустимой устарелости и цели hit-ratio. Для «почти-динамики» — 1–5 с + SWR; для справочников/изображений — минуты/часы с инвалидацией по событиям/тегам.
Q: Когда нужен Shield POP?
A: При глобальном трафике или горячих ключах: shield резко снижает промахи на origin и стабилизирует «догоняющие» волны.
Q: Как кэшировать авторизованные ответы?
A: Либо `private` (браузер), либо public с signed cookie/URL и сегментацией ключа (без PII), либо вообще bypass для критичных персональных данных.
Q: Что делать с HTTP/3?
A: Включать: особенно выигрывает мобильный/потерьный канал. Контролируйте совместимость прокси и fallback на HTTP/2.
16) Итоги
Edge-кеши и сеть POP — фундамент скоростных и экономных платформ. Успех определяется правильным ключом и `Vary`, разумными TTL/SWR/SIE, инвалидацией по тегам/событиям, tiered/shield защитой origin, а также наблюдаемостью (hit/offload/TTFB) и дисциплиной безопасности/приватности. Следуйте чек-листу — и «край» станет вашим ускорителем, а не источником сюрпризов.