← Cloudflare Workers / workers / cache
Отладка
Если кеширование работает не так, как вы ожидаете, Cf-Cache-Status заголовок ответа стоит проверить в первую очередь. Он присутствует в каждом ответе, и его значение точно показывает, что произошло с этим запросом.
Изучите Cf-Cache-Status
Отправьте два запроса на один и тот же URL и сравните заголовки:
curl -I https://my-worker.example.workers.dev/api/users/42
curl -I https://my-worker.example.workers.dev/api/users/42Сопоставьте значение статуса со сценариями ниже.
Мой Worker запускается при каждом запросе
Cf-Cache-Status отсутствует. Убедитесь, что версия wrangler не ниже 4.69.0 и что
wrangler.toml или wrangler.jsonc содержит cache.enabled = true для этого воркера.
Cf-Cache-Status это MISS при каждом запросе, или DYNAMIC, или BYPASS. Кеш ничего не сохраняет, либо срабатывает правило обхода.
Проверьте Cache-Control заголовок. Ответ должен содержать директивы, которые делают его кешируемым:
public, max-age=N: кешируется в Cloudflare и браузерах наNсекунд.
Ответ с Cache-Control: private или no-store не сохраняется, и Cf-Cache-Status это BYPASS.
Ответ с Cache-Control: no-cache является сохранён, но Cloudflare считает каждый последующий запрос устаревшим и обращается к вашему Worker перед его отдачей. Точный Cf-Cache-Status зависит от того, stale-while-revalidate также задан:
- Всего с
Cache-Control: no-cache, каждый последующий запрос запускает встроенную ревалидацию.Cf-Cache-StatusэтоREVALIDATEDесли ваш Worker возвращает304 Not Modified(тело получено из кеша), либоEXPIREDесли ваш Worker возвращает новый200(тело заменено). - С
Cache-Control: no-cache, stale-while-revalidate=N, кешированное тело ответа отдаётся немедленно, а Worker выполняется в фоновом режиме.Cf-Cache-StatusэтоUPDATINGдля окна SWR.
Если вам нужны долгоживущие попадания в кэш, используйте max-age вместо этого. См. no-cache не является обходом.
Если ответ содержит нет Cache-Control заголовка вообще, поведение зависит от кода статуса: Workers Caching применяет Эвристическая свежесть (RFC 9111) ↗ и кеширует коды состояния, кешируемые по умолчанию, на эвристический TTL: например, 200 кешируется на 2 часа, а 404 в течение 3 минут. Полную таблицу значений TTL по умолчанию см. в Ответы без Cache-Control заголовка по-прежнему кэшируются в справочнике по конфигурации. Если не хотите применять ни одно из этих значений по умолчанию, задайте Cache-Control явно в ответе.
Проверьте метод запроса. Только GET и HEAD запросы кешируются. Всё остальное относится к BYPASS. GET и HEAD запросы к одному и тому же URL используют одну и ту же запись кеша: см. Ключи кеша о том, как Cloudflare заполняет кеш в обоих случаях.
Проверьте условия автоматического обхода кеша. Cloudflare обходит кеш в следующих случаях:
- Ответ включает
Set-Cookieзаголовок. - Запрос включает
Authorizationзаголовок, если только ответ явно не задаётCache-Control: public,must-revalidate, илиs-maxage.
Если ваш Worker безусловно устанавливает Set-Cookie (например, cookie сессии в каждом ответе), ответ никогда не кэшируется. Либо удалите cookie из кэшируемых ответов, либо разделите установку cookie и кэшируемые ответы на разные маршруты.
Проверьте код статуса. Workers Caching следует RFC 9111 ↗. Ответы со статус-кодами, которые по умолчанию не кэшируются (например, 401, 403, 500) не сохраняются, если вы явно не пометите их директивами кеширования.
Некоторые коды состояния никогда не кэшируются, даже при явном Cache-Control:
520-526считаются аварийными ответами Cloudflare и никогда не сохраняются.206 Partial Contentвозвращаемый вашим Worker, не сохраняется. Workers Caching обрабатываетRangeзапросы самостоятельно, получая полное тело от вашего Worker и нарезая его из закешированной записи: если ваш Worker возвращает собственный206, такой ответ считается некешируемым. Возвращайте полный200вместо этого. См.Rangeзапросы.
Мой Worker продолжает работать даже после первого запроса
Cf-Cache-Status это MISS при первом запросе, но всё же MISS при последующих запросах.
Кэш, скорее всего, разделён на части. Ключ кеша включает путь запроса, целевую точку входа и параметр вызова ctx.props. Два запроса, которые выглядят одинаково, могут давать разные ключи кеша, если хотя бы один из этих параметров отличается.
Частые причины:
- Путь URL или строка запроса отличаются между запросами (важны даже завершающие слеши).
- Вызывающий Worker передаёт разные
ctx.propsдля каждого запроса, например разный ID пользователя. - Запросы попадают на разные именованные точки входа того же Worker.
Cloudflare пока не раскрывает структуру ключа кэша, поэтому вычисленный ключ нельзя увидеть напрямую. Вместо этого пройдите по компонентам, перечисленным в Ключи кеша и убедитесь, что каждое значение совпадает для обоих запросов.
Мой коэффициент попаданий в кэш снизился после деплоя
Это ожидаемое поведение при конфигурации по умолчанию. По умолчанию Версия Worker входит в состав ключа кеша, поэтому каждая новая версия начинается с холодного кеша и не может повторно использовать закешированные ответы предыдущей версии. Первые запросы после деплоя оказываются промахами, пока кеш новой версии заполняется, после чего доля попаданий восстанавливается.
Если вы часто выполняете развертывание, а ваши ответы между развертываниями почти не меняются, включите cache.cross_version_cache чтобы совместно использовать кешированные ответы для разных версий и избежать сброса кеша при каждом развёртывании. Обратная сторона в том, что изменения, влияющие на кеш, перестают применяться сразу же; подробнее см. ниже.
Мой кэш все еще отдает старый контент после деплоя
По умолчанию развёртывание вступает в силу немедленно, поскольку версия Worker входит в ключ кеша, а новая версия начинает работу с холодного кеша. Если вы всё ещё видите ответы от предыдущей версии, значит у вас cache.cross_version_cache включено, что позволяет использовать общие записи кеша между версиями. Чтобы деплой вступил в силу немедленно, сохранив при этом cross_version_cache при:
- Вызовите
ctx.cache.purge({ purgeEverything: true })после развертывания. Это самый простой способ. - Помечайте каждый закешированный ответ версией, которая его сформировала с помощью привязка метаданных версии, затем очистите кеш по этому тегу при откате. См. Очистка кэша для конкретной версии.
Мой кэш никогда не обновляется после изменения контента
Если данные источника изменились, а запросы всё ещё возвращают устаревший контент:
- Проверьте TTL. Ответ остаётся в кеше в течение
max-ageсекунд. Возможно, вы видите ответ, который все еще находится в пределах окна свежести. - Очистите затронутые ответы. Используйте
ctx.cache.purge()с тегами или префиксом пути, чтобы сбросить определенные записи. См. Очистка кеша. - Добавляйте теги в момент записи. Если вы не задали
Cache-Tagзаголовков, очистка по тегам недоступна. Добавьте теги к своим кешированным ответам, разверните изменения, и после записи новых записей их можно будет очищать.
Два вызова получают кешированные ответы друг друга
Этого не должно происходить, если вы используете ctx.props для контекста авторизации конкретного вызывающего. Если это так, верно одно из следующего:
- Вы аутентифицируете вызывающие стороны с помощью заголовка или параметра запроса, который не входит в ключ кеша. Перенесите данные авторизации в
ctx.props. См. Безопасность мультиарендной среды сctx.props. - Вы вызываете service binding с пользовательским параметром запроса, который отсутствует. Строка запроса входит в ключ кеша: убедитесь, что путь запроса у каждой вызывающей стороны действительно отличается.
Cf-Cache-Status: UPDATING появляется постоянно
UPDATING означает, что ответ был отдан из кеша, хотя и устаревший, а ваш Worker в фоновом режиме обновляет его. Это ожидаемое поведение при использовании stale-while-revalidate.
Если вы видите UPDATING чаще, чем вы ожидаете:
- Ваш
max-ageменьше частоты поступления ваших запросов. Каждый запрос, поступивший после того, какmax-ageистекает, происходит повторная проверка актуальности кеша. - С
max-age=0, stale-while-revalidate=<large>, каждый запрос запускает ревалидацию. Это поведение «всегда отдавать из кеша», а не «не запускать Worker». См. Выберите значения TTL и stale-while-revalidate.
Cf-Cache-Status: UPDATING никогда не появляется
UPDATING генерируется только тогда, когда all из следующих условий выполняется:
- Кэшированная запись существует, но срок ее актуальности истек (устарела).
- Ответ содержит
stale-while-revalidate=N, и запрос поступает в течениеNсекунд с момента, когда запись устарела. - Ответ не также содержат
s-maxage,must-revalidate, илиproxy-revalidate.
Если хотя бы одно из этих условий не выполняется, запросы к устаревшим записям обрабатываются через встроенную ревалидацию, что приводит к EXPIRED (Worker вернул новое тело ответа) либо REVALIDATED (Worker вернул 304 Not Modified).
Частые причины UPDATING не отображается:
- Нет
stale-while-revalidateдирективу в ответе. Стандартное окно SWR составляет0, поэтому без явной директивы каждый устаревший запрос ревалидируется синхронно. s-maxage,must-revalidate, илиproxy-revalidateприсутствует. За RFC 9111 §4.2.4 ↗, эти директивы запрещают отдачу устаревшего контента, поэтому Cloudflare отключаетstale-while-revalidate(иstale-if-error) если присутствует хотя бы один из них. Используйтеmax-ageдля окна актуальности edge, если вы хотите, чтобы работала отдача устаревшего контента.- Окно SWR истекло. Если ваш ответ использует
max-age=60, stale-while-revalidate=120, вы увидитеUPDATINGдля запросов, поступивших в течение 120 секунд после того, как запись устарела. Запросы, поступившие позже, обрабатываются через встроенную ревалидацию.
Cf-Cache-Status: STALE появляется неожиданно
STALE означает, что Cloudflare отдал ранее закешированный ответ, потому что при запросе, который должен был его обновить, в Worker произошла ошибка: например, Worker выбросил исключение, превысил время ожидания или вернул 5xx ответ. Это stale-if-error поведение. См. Отдавайте устаревший контент при ошибке с stale-if-error.
Если вы видите STALE и не ожидали этого:
- Ваш Worker не справляется с заполнением кэша или его ревалидацией. См. Панель наблюдаемости Workers на наличие ошибок в запросах, которые должны были получить свежий ответ. То, что клиенты видят устаревший ответ вместо
5xxмаскирует реальный сбой. - Вы не задали
stale-if-errorявно, и ваш ответ не включаетs-maxage/must-revalidate/proxy-revalidate. В этом случае по умолчанию Cloudflare бессрочно отдаёт устаревшие ответы при ошибке Worker, пока кешированная запись не будет очищена. Если вы хотите, чтобы ошибки быстро доходили до клиентов, задайтеstale-if-error=0вCache-Control. Подробности см. в Отдавайте устаревший контент при ошибке сstale-if-error. - Обслуживается ранее развёрнутая версия. Если вы развернули исправление, но
STALEпродолжает появляться, кешированная запись от неисправной версии по-прежнему отдаётся при каждой ошибке. Очистка затронутые записи, чтобы принудительно заполнить их заново из текущей версии.
Чтобы отличить STALE от обычного HIT в системе наблюдаемости на стороне клиента логируйте Cf-Cache-Status вместе с ответом: STALE это единственный сигнал того, что Worker выходит из строя, а клиенты этого не видят.
Мой ответ превышает лимит размера
Если ответ слишком большой для кеширования, Cloudflare не сохраняет его. Вы увидите Cf-Cache-Status: MISS при каждом запросе, даже если ответ в остальном выглядит кешируемым.
Ограничения размера ответа по тарифным планам см. в Ограничения размера для кеширования. Обратите внимание, что на момент запуска все ответы Workers Caching подчиняются ограничению размера тарифа Free, см. Размер ответа для получения подробностей.
Мне нужна дополнительная видимость
На момент запуска основными инструментами отладки являются Cf-Cache-Status заголовок ответа и информацию о попаданиях в кеш для каждого вызова в Панель наблюдаемости Workers.