CRS 内部控制台

抓取统计全域名合集 · crs.tongsou.com

频次、时间、异常三块的全局汇总。所有数值跨全部目标域名累计,不按单域名拆分。

本页的边界

CONTRACT.md §一 · CONVENTION.md 第三条

⚠️ 本页只统计下载器自己的请求。重抓周期(next_fetch_at)、优先级、熔断状态、异常信号判定全部属于调度器,CONTRACT.md §一 没有下载器读取它们的边,本页不显示、也不推断

⚠️ 本页不下任何结论。XHR 比例是否意味着后端挂了(DEV-scheduler.md §9.4)、状态码该不该熔断(§9.3)、域名该不该复核(§五),判定权都在调度器。下载器只算好数字随 report 回传。

抓取频次 · 逐小时

入口 A + 入口 B 的渲染请求 · 2026-08-14T08:00:00Z ~ 2026-08-15T08:00:00Z

08:00Z17:00Z 峰值 18,24006:00Z 谷值 9,84008:00Z

24h 合计
372,140
均值
4.3 页/秒
峰值小时
5.1 页/秒
谷值小时
2.7 页/秒

瓶颈在哪一侧

DEV-downloader-v1.md §十一 · 域名限速侧上限 vs 渲染侧上限

算式理论上限说明
域名限速侧 128,540 域名 × (1 / 1,000ms) 128,540 页/秒 几乎所有域名都早已过了 min_interval_ms,限速根本不触发
渲染侧 4 核 3~5 页/秒 实际瓶颈。无状态,可水平扩展
差距 约 4 个数量级 瓶颈彻底转到渲染 —— 正好是架构最想要的形状

⚠️ 这个结论在小规模时是反的。早期几百个域名时真实吞吐 ≈ 队列里的活跃域名数,限速才是瓶颈;到 10 万域名规模结论反转。看到本表就意味着已经进入反转后的区间,扩容思路应是加渲染机器,不是调限速。

入口分布与限速触发

downloader:domain_runtime:{domain} · 唯一写入方 下载器 · 近 24 小时

入口调用量

入口调用数占比是否入库
A · lease 循环365,22298.1%
B · POST /v1/render6,9181.9%依 should_store
C · POST /v1/probe12,405否,不计入渲染量

限速触发

入口次数超限时的行为
A1,204延迟执行
B96返回 429 + retry_after_seconds
C41返回 has_reached_origin = false

⚠️ 入口 C 超限不返回 429,而是 has_reached_origin = false —— 探针被我方自己的限速挡住,不是对方的问题。调度器收到后不退避、不计探针次数。少了这个字段,我方一抖,全库暂停域名的恢复时间集体翻倍。

⚠️ 本表的触发次数来自 downloader:domain_runtime。它与 scheduler:domain_runtime两个独立计数器,故意重复,不同步,两边数字对不上是设计如此,不是 bug。本层的作用是堵住入口 B 这条绕过调度器出队路径的通道。

⚠️ min_interval_ms 由采样器算好(已取 crawl_delay 与语种默认值的较大者),本服务直接用,禁止再取一次 max。入口 B 无此值时才落到全局默认。

抓取时间 · render_duration_ms

网页对象 render_duration_ms · 分母 340,492(done + empty),不含 not_modified 与 failed

P50
780 ms
P95
2,410 ms
脚本执行预算
30,000 ms 默认
≥ 10s 的页
2,043 0.6%
render_duration_ms页数占比占比说明
< 50071,50321.0%
500 ~ 1,000149,81644.0%主体,P50 落在此档
1,000 ~ 2,00088,52826.0%
2,000 ~ 3,00020,4306.0%P95 落在此档
3,000 ~ 10,0008,1722.4%重型 SPA
≥ 10,0002,0430.6%长尾坏站,v2 硬超时的主要目标

⚠️ 分母只含 done 与 emptynot_modifiedfailed 的统计字段全为 null,把 null 当 0 参与分位数计算,P50 会被拉低约 8%,且看不出是错的。

⚠️ 本页 P95 是 v2 硬超时阈值的唯一依据(DEV-downloader-v2.md §二)。阈值定下来之前,≥10s 那 0.6% 会一直占着 worker —— 长尾里总有坏站,卡 30 秒不值得。

⚠️ 渲染超时不丢弃:记录 console_errors 与当时 DOM 状态,report emptyfailed

等待策略与条件请求

DEV-downloader-v1.md §五 · 分母 347,950(进入渲染的页,已扣除 304 跳过的 24,190)

等待策略命中

策略页数占比可靠性
wait_selector261,41275.1%最可靠,队列消息里带
networkidle069,59020.0%通用,广告埋点会拖长
domcontentloaded + 固定延时16,9484.9%兜底

条件请求

口径
带 conditional_request 的任务96,412
304 命中24,190
命中率25.1%
省下的渲染 CPU≈ 5.2 小时

⚠️ wait_selector 由采样器推导、经调度器 lease 下发,是采样器最有价值的产出。命中率下滑意味着采样器推不出选择器的域名变多了,但该不该复核由采样器与调度器决定,本页不触发任何动作。

⚠️ ETag 由调度器从 scheduler:url_result 下发,下载器不查库。304 时跳过渲染,report fetch_status = not_modified,所有统计字段与 health_signal 留空 —— 留空是 null,不是 0,也不是空数组。

抓取异常 · 我方还是对方

判据只有一条:这次请求有没有真的到达对方服务器 · 近 24 小时 failed 合计 7,458

归属现象次数占 failed计入域名熔断
我方渲染超时(Obscura)2,91439.1% —— 我方问题,不是站点的
我方Obscura 崩溃 / OOM3885.2% —— 计入 v1 门槛二统计
对方限速信号(429 / 503 + Retry-After)2,05927.6%否 —— 不是失败,见下
对方5xx1,13415.2%按状态码分,见下
对方4xx75210.1%按状态码分,见下
对方网络层(无状态码)2112.8%

⚠️ 前两行合计 3,302 次,占 failed 的 44.3%,绝不能计入域名熔断。否则 Obscura 一抖,我们会自己停掉一批健康站,且完全查不出原因 —— 这是状态码处置全表最易错的一处。

⚠️ 入口 B 的 96 次 429 与入口 C 的 41 次 has_reached_origin = false 不在本表:它们是我方限速拒绝,压根没发出请求,不构成一次抓取失败。

对方侧状态码

网页对象 http_status · 「调度器处置」列引用 DEV-scheduler.md §9.3,本服务不执行

http_status次数粒度熔断调度器处置(引用,本服务不执行)
404502URL不重试,永久失败。CSR 站真 404 罕见 → 拿到即高置信
502372域名transient_server_error,网关够不到源站,必然整域
503 无 Retry-After259域名transient_server_error
504236域名transient_server_error
500194URL重试一次。单页 bug 极常见,不代表整站挂
403168域名连续 3 次暂停,access_denied,起 30 分钟退避到 24 小时
520 ~ 52755域名Cloudflare 系,521 / 523 是源站挂
41044URL永久失败,并从布隆与队列彻底移除。比 404 更硬
40021URL永久失败并记录告警 —— 大概率是我方规范化 bug
507 / 50818域名transient_server_error,退避加倍
4059URL不重试
4518域名legal_block,30 天探针。与 jurisdiction 联动,不做永久拉黑

⚠️ 500502 / 503 / 504 在本表必须分开看。500 是应用层抛异常,某条 URL 触发了 bug,其他 URL 好好的;按域名熔断会因一条坏 URL 停掉整个域名。

⚠️ 403 是全表唯一一处慢恢复优于快恢复。5xx 是对方自己有问题,多试无害;403 是对方在拒绝我们,每多试一次都在加深它的判断。

⚠️ 全系统 HTTP 状态只有一个名字:http_status。网页对象、report、探针响应、导出项一律相同,曾用的 status_code 已废弃。

限速信号(不是失败)

DEV-scheduler.md §9.5 · 429 与 503 + Retry-After 不进熔断体系 · 近 24 小时

情况次数调度器动作(引用,本服务不执行)
429,带 retry_after1,203throttle_until_at = now + Retry-After,严格遵守,不打折
429,无 retry_after639throttle_until_at = now + min_interval_ms × 4,指数递增,封顶 10 分钟
503,带 retry_after217严格按头处理

⚠️ 三条铁律:不计入 consecutive_failure_count;不计入 retry_count;不缩短 Retry-After。最后一条是「不把对方干崩」的唯一硬承诺。把 429 计入熔断,会把限速问题升级成可用性问题。

⚠️ throttle_until_at 是临时叠加,不修改 min_interval_ms,不写回规则副本。本页展示的 retry_after 取自网页对象的 response_headers,是原样记录,未做任何折算。

网络层异常(无状态码)

DEV-scheduler.md §9.3 网络层 · 近 24 小时

现象次数粒度熔断调度器的 suspend_reason(引用)
DNS 解析失败78域名dns_failure —— 疏探,域名可能已过期,封顶 24 小时
连接被拒 / 连接超时74域名transient_server_error
读超时33URL → 域名连续才计transient_server_error —— 单次可能是大页面
TLS 证书过期 / 无效26域名tls_failure —— 密探,证书续期通常 1 小时内完成

⚠️ DNS 与 TLS 必须分开。TLS 过期通常 1 小时内续上,密探有意义;DNS 无解析可能永远不回来,每 5 分钟探到天荒地老没有意义。合成一个 suspend_reason 就丢掉了这个区别。

health_signal 全局汇总

下载器侧算好、随 report 与探针响应回传 · 分母 340,492(done + empty)

字段24h 合计占比计算方式
xhr_total_count4,128,66312.1 / 页network_log 中 type = xhr 的条数
xhr_error_count96,4022.33%其中 http_status ≥ 500
xhr_throttled_count11,8470.29%其中 http_status = 429
xhr_denied_count8,2060.20%其中 http_status ∈ {401, 403}
has_console_error74,90822.0%console_errors 非空(布尔,不传内容)
redirect_target_hash340,492100%final_url 的 url_hash

⚠️ 不识别「取正文的那个 XHR」。一个 CSR 页面几十个 XHR,判据定不下来。下载器只回四个计数,比例判断由调度器做(§9.4)。本页同样只呈现比例,不给出「后端挂了」这类结论

⚠️ 这六项在下载器侧算,约 60 行代码,数据零额外采集。让调度器去 GET /v1/objects/{object_id} 自己算,单机每天数十万次额外读,且会把调度器与网页对象 schema 绑死 —— 拆分的意义就没了。

⚠️ fetch_statusnot_modifiedfailedhealth_signal 整体为 null,不参与本表任何分母;should_render = false 时只有 redirect_target_hash

待补项

CONVENTION.md 第二条「为什么失败」类字段 · 需三方确认后写入 DEV 文档

⚠️ fail_reason 的取值集尚未定义。同类的另外三个字段都有明确取值表:suspend_reason 见 DEV-scheduler.md §9.6,undetermined_reason 见 DEV-sampler.md §8.4,verdict_reason 是自由文本。只有 fail_reason 没有。

本页「我方 / 对方」与「网络层异常」两表按 DEV-scheduler.md §9.3 与 §十一 的现象分类展示,不是 fail_reason 的正式取值。正式取值定下来之前,前端不得把这些中文分类当枚举写死 —— 枚举取值全小写 snake_case,禁止缩写,且不得与字段名重名。