如何识别代理数据采集中的陈旧缓存响应

代理请求可以快速完成并返回 200,但其信息仍可能过旧,无法用于价格检查、库存监控、市场研究快照或本地化审计。轮换出口 IP 也不保证获得新表示:浏览器缓存、共享中间层、CDN、Service Worker、应用缓存和源站本身都可能复用数据。

新鲜与褪色的数据块通过全球互联网代理中继,并在验证棱镜处分流

正确问题不是“是否使用了缓存”。缓存通常正常且合理。真正的问题是:“响应是否满足本任务的新鲜度契约,以及能否证明由哪一层提供?”

公开来源说明:RFC Editor,RFC 9111《HTTP Caching》,2022 年 6 月。

用业务语言定义新鲜度

请求前先写明最大可接受年龄:

工作流新鲜度契约示例
市场研究目录必须在计划采集窗口内观察
价格或库存检查表示年龄不得超过批准阈值
广告或本地化 QA素材与落地状态适用于活动窗口
合规归档保存指定 UTC 时间实际观察到的表示
静态参考数据即使字节不变,也需验证器确认仍有效

不要设定一个全局阈值。季度目录的“新鲜”不适用于短时促销。将契约与结果一起保存,便于之后解释通过原因。

理解各响应头能证明什么

记录响应头,但不要把任何单个字段视为绝对事实:

  • Date 表示源站声明的消息生成时间。
  • Age 在复用缓存响应时报告其在缓存中的估计时间。
  • Cache-Control 描述缓存与再验证指令。
  • Expires 可以定义过期时间。
  • ETagLast-Modified 是条件请求可用的验证器。
  • Vary 指出哪些请求字段参与缓存选择。
  • Warning 或中间层专有诊断字段可补充上下文,但可移植逻辑不应依赖未公开的供应商字段。

时钟偏差会扭曲时间比较。时间戳使用同步 UTC,请求耗时使用单调时钟,详见代理时钟偏差指南

缺少 Age 不证明响应直达源站;存在 Age 也不代表正文不可接受。所有证据都必须与任务契约比较。

建立受控样本

使用可自行更新的已授权端点,在正文中返回无敏感信息的版本标记,并支持 ETagLast-ModifiedCache-ControlDate 及条件请求。

至少执行以下阶段:

  1. 发布版本 A,通过直连对照与每条代理线路获取。
  2. 在声明的新鲜期内重复请求,确认合理复用。
  3. A 仍在新鲜期时发布版本 B,记录业务契约是否允许继续使用 A。
  4. 等待进入必须验证的阶段后再请求。
  5. 使用版本 A 的验证器发送条件请求。
  6. 模拟已授权的源站故障,观察是否明确允许提供陈旧响应。
  7. 恢复源站并确认线路最终收敛到版本 B。

不要使用随机生产页面作为样本。内容若不可预测变化,就无法区分缓存行为与源站差异。

保存结果信封

每次尝试记录:

test_case_id
observed_at_utc
route_id
exit_region
session_id_hash
request_header_profile
final_status
redirect_chain_digest
date_header
age_seconds
cache_control
expires
etag_hash
last_modified
vary
content_type
body_byte_count
body_digest
semantic_version_marker
duration_ms
freshness_contract_seconds
freshness_result

验证器可能包含内部标识时应保存摘要。不得记录代理凭据、授权头、Cookie、令牌、个人数据或完整敏感正文。

使用请求头完整性测试证明对照和代理请求采用相同相关字段。如果 Accept-Language、编码偏好、Cookie 或授权信息不同,正文差异可能是正确变体而非陈旧数据。

重试前先分类

使用明确状态:

  • 新鲜且等价: 满足契约,版本或验证器符合预期,业务语义正确。
  • 新鲜但属于变体: 满足契约,但因 Vary、地区、账号或实验维度而不同。
  • 陈旧但允许: 超过正常新鲜期,但响应策略明确允许且任务可以接受。
  • 陈旧且不可接受: 超出业务契约,或必须验证后仍持续返回旧内容。
  • 源站已更新、缓存未收敛: 受控源站为 B,某条线路在策略外仍返回 A。
  • 无法判断: 缺少时钟、响应头、正文或对照证据。
  • 内容无效: 拦截页、登录外壳、残缺正文或错误模式;新鲜度无法补救。

不要把所有摘要差异标记为“新鲜”。不同的错误页不是有效新表示。传输成功后仍需检查必需字段、语言、记录数和版本标记。

再验证时保留首次证据

先执行原始请求并保存结果。随后在源站契约允许时,使用已记录验证器发起受控再验证。304 Not Modified 可以确认已存储表示仍有效,但不会提供新正文。

测试需要强制验证时可使用 Cache-Control: no-cache,不要把它与 no-store 混淆,也不要默认添加随机查询参数。缓存破坏参数可能改变应用资源、服务器行为、分析或签名要求,而且测试的是另一个缓存键。

若必须测试唯一 URL,只能使用自有或已授权受控端点,并将其标记为独立实验。不得对第三方网站执行无边界的缓存破坏。

每次只改变一个维度

矩阵至少包括:

  • 直连对照与代理线路;
  • 各目标地区;
  • 新连接与复用连接;
  • 干净与有记录的浏览器配置;
  • 普通获取与条件验证;
  • 完全相同的 URL、方法、相关请求头和账号状态;
  • 源站健康及已批准故障模拟。

同时改变出口 IP、Cookie、语言、浏览器版本、请求头和 URL 会破坏归因。代理连接池年龄测试可帮助分离连接复用与响应复用。

常见故障模式

旧正文相同,Age 持续增加

在响应或业务新鲜期到期前可能完全合理。超出策略后,保存缓存指令、验证器行为、线路和正文摘要再升级处理。

旧正文相同,但没有 Age

检查浏览器缓存、Service Worker、应用响应和源站。没有 Age 不等于直达源站。

轮换 IP 后正文不同

确认语言、账号状态、实验分组和 Vary 输入。新正文可能只是地区变体,而不是更新的表示。

返回 304,但业务数据仍显得陈旧

验证器可能正确确认表示未变化,而源站应用本身的数据已经陈旧。缓存验证证明的是相对于验证器的表示状态,不是业务事实。

把快速响应当作缓存命中

延迟不是可靠的缓存证据。附近源站可以很快,拥塞缓存也可能很慢。应使用响应头、验证器、受控版本变化和正文摘要。

操作检查清单

  • 为每项任务定义新鲜度阈值。
  • 记录准确 URL、方法、请求头、线路、地区及客户端构建。
  • 保存 DateAgeCache-ControlExpires、验证器和 Vary
  • 对正文计算摘要并验证业务语义。
  • 与受控直连线路对比。
  • 在再验证或重试前保存首次结果。
  • 每次只改变一个维度。
  • 区分合理变体与陈旧内容。
  • 避免无边界查询参数缓存破坏。
  • 脱敏凭据、标识符、Cookie 和敏感正文。
  • 针对契约失败告警,而不是针对使用缓存告警。

常见问题

轮换住宅代理是否保证内容最新?

不保证。轮换改变网络出口,但浏览器、中间层、CDN、Service Worker、应用或源站缓存仍可能复用表示,也可能只产生不同地区变体。

Age: 0 能否证明源站生成了新正文?

不能。它只是一个缓存信号。还需结合验证器、受控版本标记、正文摘要和直连对比。

每个采集请求都应使用 no-cache 吗?

不应。这会增加源站负载并失去合理性能收益。只在业务需要验证且目标允许时使用,并与已记录的新鲜度契约一致。

陈旧响应是否可能被接受?

可以,前提是 HTTP 策略允许且业务契约接受,例如已批准源站故障期间的非关键参考数据。必须明确标记,不能简单称为新鲜。

合规说明

只测试你获准使用的端点、账号、数据集和代理基础设施。遵守缓存指令、访问控制、合同、隐私、版权、适用的 robots 规则和速率限制。控制样本流量,不得利用缓存测试绕过限制或迫使源站承受过量负载。