01 · 请求路径

一次请求经过的五层

页面不是每次访问都重新计算。绝大多数请求在边缘或进程内就结束, 数据库只承担缓存未命中的那部分流量。这也是几万个型号页能被爬虫完整抓取的前提。

请求路径
买家 / 爬虫
  │
  ├─ Cloudflare 边缘 ─ 命中即返回
  ├─ Caddy ─ 按域名分流
  ├─ Astro SSR ─ 渲染整页 HTML
  ├─ Redis ─ 数据与检索缓存
  └─ PostgreSQL / Meilisearch
01 Cloudflare 边缘
整页 HTML 按 URL 缓存,命中直接返回,不回到源站。公开页实测全部命中; 账户、登录、询价等含会话的路径不缓存,每次回源。
02 Caddy 反向代理
按域名把请求分发到对应站点的容器。同一台机器上,各站的配置、容器与镜像各自独立, 一个站的路由改动不会影响另外两个站。
03 Astro 服务端渲染
缓存未命中时按需渲染整页 HTML:取数据、拼参数表与正文、输出完整 HTML。 渲染结果写入进程内缓存(icboms 为 900 条 / 128MB / LRU),下一次请求直接读缓存。
04 Redis 数据缓存
产品详情、类目列表、检索结果、聚合榜单按站命名空间存放,各站使用不同数据库编号,键不交叉。 缓存未命中才查询 PostgreSQL 或 Meilisearch。
05 PostgreSQL 与 Meilisearch
每站一个独立数据库;Meilisearch 索引按站点前缀隔离(aoctrl_ / isd_ / icboms_)。页面与索引由同一份结构化数据生成,不各自维护。
02 · 页面生成

输出完整 HTML,不依赖前端水合

icboms.com 首页的当前基线,2026 年 10 月线上实测,以传输字节为口径。 页面在服务端生成整页 HTML,正文、参数表与型号都在源码里。

icboms.com 首页当前基线
指标实测值说明
HTML 原始体积 213 KB 含正文、参数表与型号
HTML gzip 体积 35.6 KB 实际传输体积
外部 JS 文件数 2 首屏只有主题与交互逻辑
首屏 JS 传输量(约) 16 KB 不含图片与字体
内联脚本 26.8 KB 主题切换、导航与表单

正文、参数表与型号由 HTML 直接输出,不在浏览器里重新序列化或挂载;首屏没有等待脚本执行的空白期。

当前基线

Lighthouse 移动端 0.97

icboms.com 首页,4G 网络 + 4 倍 CPU 节流下实测:总阻塞时间 0ms、布局偏移 0、 最大内容绘制 2.06s;桌面端启动耗时 74ms。

结果解释

正文不依赖 JavaScript

HTML 里直接包含型号、参数表与正文。关闭 JavaScript 后页面内容完整可读, 搜索引擎与 AI 抓取时不需要执行脚本,也不需要等待水合。

测量口径

体积与请求数为线上响应的传输字节实测;性能分由 PageSpeed Insights 在同一页面测得。 两者口径不同,不互相推导。

03 · 缓存分层

性能来自缓存,不来自机器配置

三层缓存的分工
层缓存内容失效方式命中后
Cloudflare 边缘 整页 HTML(公开页) 按 URL 或标签清理;内容更新时主动提交 不回到源站
进程内 HTML 整页 HTML,icboms 900 条 / 128MB / LRU 进程重启、超时或跨进程代际信号 不查询数据库
Redis 产品详情、类目列表、检索结果、聚合榜 按站命名空间与代际键清除 不执行 SQL 与检索
aoctrl.com

源站渲染 20–41ms

缓存预热后源站实测:首页 25ms、/products 20ms、 /category/plcs 41ms、/siemens 首访 99ms → 热 37ms。公开页在边缘全部命中。

边缘响应

14–22ms

源站相邻网络测得;第三方美国节点预热后 /siemens 70ms。 未预热的边缘节点首次访问 0.30–0.33s,这段耗时是节点与源站之间的往返,不是页面渲染。

icsourcedirect.com

容器内热渲染 2.6–4.7ms

边缘首页 20–36ms、产品页热缓存 19–31ms;进程冷启动后的首次渲染 200–300ms, 由进程内缓存吸收后续请求。

跨进程失效

改一次内容,三处同时失效

后台保存后写入 Redis 代际键,各站进程轮询到变化即清空自己的 HTML 与数据缓存, 再向边缘提交清理。三条链路缺一条,线上就会停在旧页面。

踩过的坑

源站整页缓存上线初期始终不落盘。原因是渲染层给每个 HTML 响应都带上 Vary: Accept,而缓存白名单只放行了 accept-encoding, 于是所有页面被判定为不可缓存。缓存层与渲染层的响应头必须对齐, 这类问题不会报错,只表现为「缓存配置看起来生效了,实际没有」。

04 · 检索与数据

万级型号走索引,不走数组遍历

Meilisearch 承担型号精确匹配与多条件筛选;PostgreSQL 承担结构化存储与聚合。 以下三条是当前实现的关键口径,数字为生产库 EXPLAIN ANALYZE 结果。

01 · 资产闸 118ms
类目与品牌交叉页需要判断每条产品是否具备可见资产。实现上先物化类目成员再求值, 单个品牌×类目组合 118ms 返回,不按品牌全量逐行解析 JSONB 规格。
02 · 停产榜 6 小时缓存 + 后台刷新
品牌页需要一条全站停产聚合。结果缓存 6 小时,过期后由后台刷新并在各进程间共享, 买家请求不触发重算。
03 · 样式 首页 CSS 102KB
样式按路由拆分,首页只加载本页需要的部分,102KB;固定部分约 63KB 由各页共担。
仍未消失的开销

新类目×品牌组合的首次访问仍需约 120–200ms 的资产判定,由 Redis 二级缓存吸收重复访问。

05 · 隔离与部署

每站一份镜像、一个数据库、一套配置

站点之间的隔离边界
资源隔离方式影响
容器与镜像 每站独立镜像,独立容器 一个站的代码改动与重启不波及其他站
数据库 每站独立 PostgreSQL 数据库 表结构与数据量互不影响
Redis 每站独立数据库编号与键前缀 缓存清理按站执行,不误伤
检索索引 固定前缀 aoctrl_ / isd_ / icboms_ 索引重建可以逐站进行
反向代理 Caddy 按域名分流,每站一段配置 路由与证书按站管理
为什么不用共享镜像加站点参数

共享镜像能减少构建次数,但会把各站的运行风险绑在一起:一次发布同时影响全部站点, 一个站的数据量与查询特征还会影响另外两个站的缓存命中率。 换来的是故障边界清晰:一次发布只影响一个站,回滚也只回一个站。

06 · 价值

这套架构解决什么

01

首字节在边缘完成

公开页 14–22ms 返回,买家与爬虫拿到的是同一份缓存。首屏不等待数据库,也不等待 JavaScript。

02

抓取不压数据库

几万个型号页的抓取由缓存承接。数据库连接实测 8 条(上限 100), 产品表累计索引扫描 3,050 万次,无长查询。

03

正文与参数在 HTML 源码里

关闭 JavaScript 后页面完整可读。AI 抓取与搜索引擎收录不依赖水合,也不需要渲染队列。

04

页面与索引同源

型号、参数与类目只存一份结构化数据,页面与检索结果由它生成。 改一次数据,前台与搜索不会出现两种答案。

05

故障边界按站划分

独立镜像、独立数据库、独立索引。一个站的发布事故不会同时影响其他站点。

06

成本可核算

一台 VPS 加 Cloudflare 免费额度,没有按请求计费的检索服务,也没有按席位计费的后台。 费用随机器规格变化,不随访问量突然跳档。

07 · 数据口径

这些数字怎么测,客户怎么自己复核

本页所有数字均为 2026 年 10 月在生产环境实测,并记录测量位置与工具。 缓存命中与响应头可以由任何人复现。

复核缓存与响应头
# 查看边缘缓存是否命中
curl -sD - -o /dev/null https://icboms.com/ | grep -i 'cf-cache-status'

# 查看源站整页缓存与响应耗时
curl -sD - -o /dev/null https://icboms.com/ | grep -i 'x-astro-cache'

# 关闭 JavaScript 后查看页面源码,确认正文与参数在 HTML 中
curl -s https://icboms.com/ | grep -c '<h1'
缓存与耗时

响应头 cf-cache-status 与 x-astro-cache 直接反映命中层级; curl -w 可读取各阶段耗时。

页面内容

关闭 JavaScript 查看网页源代码,或直接抓取 HTML:型号、参数表与正文应在源码中,不依赖脚本生成。

性能与收录

PageSpeed Insights 读取移动端指标;Search Console 读取收录与 sitemap 处理结果; isitagentready 读取 AI 就绪等级。三者均为第三方工具。

不做的事

不跨口径比较:不同测量位置、不同测量方法的数字不放在同一张表里混用; 不引用历史对照:只报当前实测值,不把改动前后的数字并列表述; 不承诺排名与询盘:性能可测,收录与成交受品类竞争与时间影响。

架构评估

提交品类与 SKU 数量。

本公司按产品数量、筛选维度与访问量给出架构建议,并说明对应的服务器规格与年度费用区间。

微信咨询 发邮件