Astro SSR · 三层缓存 · 每站独立镜像
自营站点的工程架构
同一套底座,各站独立部署。HTML 在服务端生成后进入三层缓存;检索、数据库与容器按站隔离。以下为分层实现与生产实测数字。
一次请求经过的五层
页面不是每次访问都重新计算。绝大多数请求在边缘或进程内就结束, 数据库只承担缓存未命中的那部分流量。这也是几万个型号页能被爬虫完整抓取的前提。
买家 / 爬虫
│
├─ Cloudflare 边缘 ─ 命中即返回
├─ Caddy ─ 按域名分流
├─ Astro SSR ─ 渲染整页 HTML
├─ Redis ─ 数据与检索缓存
└─ PostgreSQL / Meilisearch aoctrl_ /
isd_ / icboms_)。页面与索引由同一份结构化数据生成,不各自维护。
输出完整 HTML,不依赖前端水合
icboms.com 首页的当前基线,2026 年 10 月线上实测,以传输字节为口径。 页面在服务端生成整页 HTML,正文、参数表与型号都在源码里。
| 指标 | 实测值 | 说明 |
|---|---|---|
| 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 在同一页面测得。 两者口径不同,不互相推导。
性能来自缓存,不来自机器配置
| 层 | 缓存内容 | 失效方式 | 命中后 |
|---|---|---|---|
| Cloudflare 边缘 | 整页 HTML(公开页) | 按 URL 或标签清理;内容更新时主动提交 | 不回到源站 |
| 进程内 HTML | 整页 HTML,icboms 900 条 / 128MB / LRU | 进程重启、超时或跨进程代际信号 | 不查询数据库 |
| Redis | 产品详情、类目列表、检索结果、聚合榜 | 按站命名空间与代际键清除 | 不执行 SQL 与检索 |
源站渲染 20–41ms
缓存预热后源站实测:首页 25ms、/products 20ms、
/category/plcs 41ms、/siemens 首访 99ms →
热 37ms。公开页在边缘全部命中。
14–22ms
源站相邻网络测得;第三方美国节点预热后 /siemens 70ms。
未预热的边缘节点首次访问 0.30–0.33s,这段耗时是节点与源站之间的往返,不是页面渲染。
容器内热渲染 2.6–4.7ms
边缘首页 20–36ms、产品页热缓存 19–31ms;进程冷启动后的首次渲染 200–300ms, 由进程内缓存吸收后续请求。
改一次内容,三处同时失效
后台保存后写入 Redis 代际键,各站进程轮询到变化即清空自己的 HTML 与数据缓存, 再向边缘提交清理。三条链路缺一条,线上就会停在旧页面。
源站整页缓存上线初期始终不落盘。原因是渲染层给每个 HTML 响应都带上
Vary: Accept,而缓存白名单只放行了 accept-encoding,
于是所有页面被判定为不可缓存。缓存层与渲染层的响应头必须对齐,
这类问题不会报错,只表现为「缓存配置看起来生效了,实际没有」。
万级型号走索引,不走数组遍历
Meilisearch 承担型号精确匹配与多条件筛选;PostgreSQL 承担结构化存储与聚合。
以下三条是当前实现的关键口径,数字为生产库 EXPLAIN ANALYZE 结果。
新类目×品牌组合的首次访问仍需约 120–200ms 的资产判定,由 Redis 二级缓存吸收重复访问。
每站一份镜像、一个数据库、一套配置
| 资源 | 隔离方式 | 影响 |
|---|---|---|
| 容器与镜像 | 每站独立镜像,独立容器 | 一个站的代码改动与重启不波及其他站 |
| 数据库 | 每站独立 PostgreSQL 数据库 | 表结构与数据量互不影响 |
| Redis | 每站独立数据库编号与键前缀 | 缓存清理按站执行,不误伤 |
| 检索索引 | 固定前缀 aoctrl_ / isd_ / icboms_ | 索引重建可以逐站进行 |
| 反向代理 | Caddy 按域名分流,每站一段配置 | 路由与证书按站管理 |
共享镜像能减少构建次数,但会把各站的运行风险绑在一起:一次发布同时影响全部站点, 一个站的数据量与查询特征还会影响另外两个站的缓存命中率。 换来的是故障边界清晰:一次发布只影响一个站,回滚也只回一个站。
这套架构解决什么
首字节在边缘完成
公开页 14–22ms 返回,买家与爬虫拿到的是同一份缓存。首屏不等待数据库,也不等待 JavaScript。
抓取不压数据库
几万个型号页的抓取由缓存承接。数据库连接实测 8 条(上限 100), 产品表累计索引扫描 3,050 万次,无长查询。
正文与参数在 HTML 源码里
关闭 JavaScript 后页面完整可读。AI 抓取与搜索引擎收录不依赖水合,也不需要渲染队列。
页面与索引同源
型号、参数与类目只存一份结构化数据,页面与检索结果由它生成。 改一次数据,前台与搜索不会出现两种答案。
故障边界按站划分
独立镜像、独立数据库、独立索引。一个站的发布事故不会同时影响其他站点。
成本可核算
一台 VPS 加 Cloudflare 免费额度,没有按请求计费的检索服务,也没有按席位计费的后台。 费用随机器规格变化,不随访问量突然跳档。
这些数字怎么测,客户怎么自己复核
本页所有数字均为 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 就绪等级。三者均为第三方工具。
不跨口径比较:不同测量位置、不同测量方法的数字不放在同一张表里混用; 不引用历史对照:只报当前实测值,不把改动前后的数字并列表述; 不承诺排名与询盘:性能可测,收录与成交受品类竞争与时间影响。