Skip to content
架构中级阅读约 1 分钟

架构实战 · 企业官网与内容资讯站 ​

本篇定位

面向「企业官网 + 内容资讯/博客/新闻」这类读多写极少的站点,讲清一套够用、省钱、好维护的架构:CMS 后台写稿、发布时静态化、CDN 扛读流量、MySQL 存内容、Redis 做缓存、表单留言异步落库。配套方法见 架构方法论、容量估算、高可用蓝图。

一、业务特点与规模估算 ​

典型场景:一家 B2B 科技公司官网(首页、产品页、解决方案、关于我们)+ 一个技术资讯/博客频道(每周更新 5~10 篇长文),外加「联系我们 / 预约演示」表单。这类站点 95% 以上请求是只读,写操作只有编辑在后台发文章、访客提交表单两类。

指标假设值说明
注册/登录用户50 万官网大多不登录,这里指 CMS 作者 + 表单留资用户
日活 UV3 万工作日白天 B 端流量为主
日 PV15 万人均浏览 5 个页面
峰值 QPS800早 10 点/下午 2 点两篇文章被行业媒体转载时冲高
峰值在线5000长连接少,主要是短 HTTP 请求
文章/页面总量5 万篇累计 5 年,单篇含图约 2MB
图片/附件素材2 TB全部走对象存储 + CDN
表单提交峰值50 QPS大促/发布会当天留资涌入
出口带宽峰值200 Mbps静态资源走 CDN 后,回源带宽只需很小

核心结论:这不是高并发系统,把静态资源全部推到 CDN、动态回源压到最低、数据库几乎不被直查,就赢了一大半。

1.1 容量怎么推出来的 ​

推算项计算结果
平均 QPS日 PV 15 万 ÷ 86400 ≈ 1.71.7 QPS
峰值 QPS平均 × 40 倍系数(白天集中)≈ 800 QPS
回源 QPSCDN 命中率按 90% 算源站仅 ≈ 80 QPS
出带宽峰值 800 QPS × 平均页面 100KB(含 CDN 缓存命中后仅回源小流量)回源 ≈ 20 Mbps,CDN 侧另计
MySQL 容量5 万篇 × 单篇含正文 5KB + 元数据≈ 5GB,500G 盘用不到 2%
年存储增长每周 8 篇 × 2MB ≈ 8MB/周一年 ≈ 400MB,图片素材另算

要点:真正打在源站和数据库上的流量,比表面 PV 小一个数量级。这也是为什么官网类项目 2 台 4C8G 应用 + 1 主 1 从 MySQL 就够,钱应该花在 CDN 和 OSS 上。

二、总体架构图 ​

分层说明:接入层(SLB+Nginx)→ CDN → 应用服务(CMS/动态渲染)→ 缓存(Redis)→ 消息(Kafka/RocketMQ)→ 数据库(MySQL 主从)→ 对象存储(OSS)→ 监控(Prometheus/Grafana)。SEO 关键在于页面可被蜘蛛抓取、URL 友好、有 SSR/静态化,所以架构上刻意把详情页做成静态 HTML 推到 CDN。

三、服务器清单 ​

角色数量CPU(核)内存系统盘/数据盘带宽安装软件 / 承担职责
CDN 节点云厂商---按流量计费全站静态缓存、图片/JS/CSS/HTML 边缘分发
负载均衡 SLB2(主备)24GESSD 100G50Mbps四层/七层负载,跨可用区
Nginx 接入层248GESSD 100G20Mbps反向代理、HTTPS 卸载、gzip、缓存、限流;见 Nginx 实战
CMS/动态应用248GESSD 100G10MbpsCMS 后台 + 动态渲染,Java/Node
静态化发布 Worker148GESSD 100G10Mbps消费发布消息,渲染 HTML 推 OSS
留言消费 Worker124GESSD 100G5Mbps消费表单队列,落库 + 发通知
MySQL 主1832GESSD PL1 500G / 5000 IOPS内网内容库写;见 MySQL
MySQL 从1832GESSD PL1 500G内网读分担 + 备份源
Redis1主1从48GESSD 100G内网页面缓存、CMS 会话;见 Redis
Kafka348GESSD 200G内网发布事件 + 表单队列;见 Kafka
对象存储 OSS云--标准型无限-图片附件 + 静态 HTML 托管
监控148GESSD 500G10MbpsPrometheus + Grafana + 日志;见 SLO

合计自建约 14 台(CDN/OSS/SLB 为云服务不计入)。与规模自洽:800 QPS 下 Nginx+应用各 2 台绰绰有余,MySQL 8C32G 对读多写少的内容库非常宽松。

四、服务依赖与各自解决的问题 ​

服务解决什么问题与谁交互同步/异步
CDN把 95% 读流量挡在边缘,源站几乎不被打访客/蜘蛛 ↔ 回源 Nginx同步请求,未命中才回源
NginxHTTPS 卸载、压缩、边缘缓存、限流SLB ↔ 应用同步反向代理
CMS 应用后台写稿、动态页面渲染MySQL 主、Redis同步查库/查缓存
Redis热门文章页缓存、降库压力CMS 应用同步读,旁路缓存
MySQL 主从文章/页面/留言持久化CMS 写主、读可走从同步写主,异步主从复制
Kafka解耦「发布」与「留言通知」CMS/Worker异步
静态化 Worker文章发布后渲染成 HTML 推 OSS+刷新 CDNKafka、OSS异步消费
留言 Worker表单留言落库 + 邮件/企微通知Kafka、MySQL、邮件异步消费
OSS图片附件与静态文件存储CDN、Worker同步上传/下载
Prometheus各层指标、告警全部节点异步采集

一次发布的完整时序:编辑在后台点发布 → CMS 写一条「待发布」记录到 MySQL 主 → 发一条「文章发布事件」到 Kafka → 静态化 Worker 消费,拉取正文渲染成 HTML → 上传 OSS → 调 CDN 刷新对应 URL → 回写发布状态。整条链路除了「写记录」是同步,其余全部异步,编辑几乎无感。

访客读一篇文章的时序:浏览器请求 URL → CDN 命中直接返回(90%+)→ 未命中才回源 Nginx → 查 Redis 缓存 → 未命中再查 MySQL 从库 → 回填 Redis 返回。数据库在正常情况下每天被直查的次数很少。

五、关键设计点与坑 / 注意事项 ​

  1. 静态化与缓存一致性:文章修改后必须刷新对应 CDN 缓存 + 失效 Redis key,否则线上看到旧版本。做法是发布事件带 URL 列表,Worker 调 CDN 刷新接口。
  2. SEO 细节:URL 用 /news/2026/09/xxx.html 静态化;详情页要有 <title>/description/canonical;面包屑 + 结构化数据;开 gzip/HTTP2;移动端适配。蜘蛛 UA 不要被限流误伤。
  3. 表单留言防刷:访客表单是机器人重灾区。必须加验证码(如滑块)、接口限流、蜜罐字段,留言先入 Kafka,Worker 识别垃圾后再落库,避免脏数据直接进 CRM。
  4. 图片处理:用户上传图不要直接存原图给 CDN,走 OSS 图片处理裁剪多尺寸,WebP 格式,省带宽。
  5. 不要让后台 CMS 暴露公网:管理端走 VPN/堡垒机 + IP 白名单,单独子域名 admin.xxx.com。
  6. 备份:MySQL 每日全备 + binlog,OSS 跨区域复制;静态化文件可随时重新渲染,无需备份。
  7. 发布与回滚:CMS 应用用蓝绿发布(两个版本各 2 台,SLB 切流)。文章内容误发不回滚代码,直接在后台改回再触发一次发布事件即可。
  8. SEO 监控指标:关注收录量、关键词排名、蜘蛛抓取量、页面加载速度(Core Web Vitals)。这些通过站长平台 + 前端监控看,不进业务监控。
  9. 表单留言安全:留言内容做 XSS 过滤(存展示都要转义),不要把留言直接渲染到后台 HTML,防止后台被打 XSS。
  10. 国际化/多语言:若有多语言站点,按语言路径 /en/news/ 静态化,hreflang 标签标注,避免重复内容惩罚。

5.1 典型配置参考(Nginx 关键片段) ​

nginx
location ~* \.(html|css|js|png|jpg|webp)$ {
    proxy_cache cache_one;
    proxy_cache_valid 200 10m;
    limit_req zone=static burst=50 nodelay;
}
location = /api/contact {
    limit_req zone=form burst=10 nodelay;   # 表单单独严格限流
    proxy_pass http://cms_upstream;
}

静态资源走 CDN,Nginx 只做兜底回源缓存;/api/contact 这类写接口单独限流,防止机器人刷库。

六、安全与高可用 ​

  • 边界防护:CDN 侧开 WAF、防 CC;Nginx 限流(limit_req);后台 IP 白名单 + VPN。
  • 鉴权授权:CMS 后台账号 + 角色(作者/审核/管理员),表单留言无需登录。
  • 数据加密:全站 HTTPS(Let's Encrypt 或云证书),MySQL 盘加密,密码 bcrypt 存储。
  • 消除单点:Nginx/应用各 2 台挂 SLB;MySQL 主从 + 故障切换;Redis 主从;Kafka 3 副本。
  • 降级预案:数据库挂了,CDN/Redis 里的静态页仍能读;Redis 挂了直查 MySQL(已限流保护)。
  • 多可用区:SLB/Nginx/应用跨 2 个可用区,OSS 多副本。

6.1 故障切换与限流降级清单 ​

层级单点风险消除手段故障时降级动作
CDN厂商整体故障备一家 CDN,DNS 可切切备用 CDN 或临时回源
Nginx单台宕机SLB 健康检查摘流剩余节点顶住
应用单实例 OOM两实例 + 自动拉起静态页仍可读
MySQL主库宕机MHA/Orchestrator 自动切从切 VIP,写短暂失败
Redis缓存失效主从直查 MySQL + 限流兜底
Kafka队列宕3 副本表单先落本地,恢复后补投

6.2 关键监控指标 ​

指标告警阈值说明
CDN 回源率> 15%缓存命中率下降,查缓存规则
Nginx 5xx 率> 1%应用层故障
MySQL 慢查询> 10 条/分钟慢 SQL 增多
MySQL 主从延迟> 10s读一致性风险
Kafka 消费积压> 10000 条Worker 处理不过来
表单提交失败率> 5%留言链路异常

七、上线后可能出现的状况与应对 ​

类别征兆处置
性能类文章详情页打开慢命中率低→查 CDN 回源率;回源高→延长缓存 TTL、热点页预热
性能类MySQL CPU 高看慢查询,后台列表/全文检索拖库→加索引或迁 ES,读走从库
容量类磁盘上涨快多为日志/图片,图片迁 OSS,日志切分 + 定期清理
容量类OSS 流量超预算检查是否被外链盗图,开 Referer 防盗链 + 带宽告警
故障类Nginx 一台挂SLB 自动摘流,剩余一台顶住;尽快拉起替换
故障类MySQL 主库挂切换从库为主(见 高可用蓝图),应用连接串切 VIP
故障类Redis 挂旁路缓存失效,直查 MySQL,靠 Nginx 限流兜底
故障类Kafka 挂发布/留言暂停(表单先写本地文件补偿),不影响线上读
活动流量发布会文章被刷屏CDN 扛,提前预热该 URL,必要时临时扩容回源
数据类留言丢失查 Kafka 积压与 Worker 消费失败重试,死信表人工补
数据类主从延迟监控 seconds_behind_master,延迟大时读回主库,排查大事务
数据类误删文章用 binlog/每日备份恢复到时间点,静态页重新发布
性能类谷歌/百度蜘蛛抓取过频压垮源站对蜘蛛 UA 单独限流或限速,sitemap 控制抓取频率,重要页面保持长缓存
故障类HTTPS 证书过期全站打不开证书过期监控提前 30 天告警,自动续期(acme.sh),备一份手动续期脚本
故障类CDN 厂商故障大面积回源失败切换备用 CDN 厂商 DNS 解析,或临时回源直出静态页
容量类留言/垃圾数据暴涨占满库垃圾留言定期清理,Kafka 队列积压告警,Worker 并发临时调大
活动流量被恶意刷表单留资触发限流阈值,临时开更强验证码,IP 黑名单
数据类静态页与后台内容不一致触发全量重新发布任务,对比 CDN 上 HTML 与 DB 内容,强制刷新
故障类从库延迟导致访客看到旧文章发布后延迟敏感请求读主,或等待复制追平再切流
性能类后台编辑器卡顿后台管理端不走 CDN,检查后台接口慢查询,独立扩容
容量类文章库历史归档3 年前文章迁冷备库,线上只留近 2 年热数据
故障类留言 Worker 宕机丢通知消息未落死信表,Worker 重启后从 Kafka 位点重消费

7.1 演进路线 ​

流量再涨 10 倍时:详情页全静态化推 CDN,源站只留后台写接口;MySQL 读多写少可加 ES 做全文检索;CMS 容器化上 K8s,按 CPU 自动扩缩容(见 K8s 架构)。


相关阅读:架构方法论 · 容量估算 · 高可用蓝图 · MySQL · Redis · Nginx · SLO