系统架构设计:C/S vs B/S、核心组件与高可用思路

好,咱们进入第二章。架构设计这事儿,说白了就是定骨架。骨架歪了,后面填多少肉都别扭。我在做补丁分发系统之前,踩过不少架构的坑,今天把这些经验掰开了讲给你听。

2.1 C/S 架构 vs B/S 架构,怎么选?

先解决一个根本问题:你的控制台,到底用客户端还是浏览器?

我见过不少团队一上来就拍脑袋选 B/S,理由是“现在都流行 Web”。但你想想看,补丁分发这个场景,控制台操作人员就那么几个,又不是给成千上万人用的。选型不能只看流行,得看场景。

对比维度 C/S 架构 B/S 架构
部署方式 需安装客户端 浏览器直接访问
实时推送能力 强(长连接原生支持) 弱(需 WebSocket 或轮询)
跨平台 需为每个平台单独开发 天然跨平台
升级维护 客户端需手动或自动升级 服务端更新即生效
离线操作 支持本地缓存和离线审批 依赖网络
安全性 可做双向证书绑定 依赖 HTTPS + 会话管理

我的建议:控制台用 B/S,Agent 用 C/S。混合架构才是正解。

为什么?操作人员需要灵活访问,浏览器最方便。而 Agent 需要常驻后台、实时通信,C/S 的长连接优势无可替代。

我曾经在一个项目中强行全上 B/S,结果 Agent 的心跳检测全靠 HTTP 轮询,服务器压力大不说,补丁下发还有十几秒的延迟。后来改成 Agent 走 TCP 长连接,延迟降到毫秒级。嗯,这个教训挺深刻的。

2.2 核心组件拆解

一个完整的补丁分发系统,离不开四个核心组件。我习惯把它们比作人的四肢:

  • Agent —— 手和脚,负责执行
  • Server —— 躯干,负责调度
  • 数据库 —— 大脑,负责记忆
  • Web 控制台 —— 眼睛,负责展示

2.2.1 Agent(客户端代理)

Agent 是部署在每台目标机器上的小进程。它的职责很纯粹:

  1. 心跳上报:每隔 30-60 秒告诉 Server “我还活着”
  2. 补丁下载:从 Server 或文件仓库拉取补丁包
  3. 补丁执行:调用系统命令或脚本安装补丁
  4. 结果回传:安装成功或失败,必须原路返回

避坑指南:Agent 一定要做断点续传。我曾经遇到一个场景,50MB 的补丁包下载到 80% 网络断了,Agent 直接重头开始下,气得运维同事直拍桌子。后来加了断点续传,体验好太多了。

2.2.2 Server(服务端)

Server 是整个系统的调度中心。它要处理的事情不少:

  • 接收 Agent 的心跳和状态
  • 管理补丁任务的下发和暂停
  • 控制并发数,防止网络打满
  • 提供 API 给 Web 控制台调用

我个人习惯把 Server 拆成两层:API 层和调度层。API 层负责和 Web 控制台交互,调度层负责和 Agent 通信。这样拆的好处是,哪天想换前端框架,API 层不用动;想升级通信协议,调度层单独改就行。

2.2.3 数据库

数据库存什么?说白了就三类数据:

数据类别 内容示例 存储建议
资产信息 主机名、IP、操作系统、Agent 版本 MySQL / PostgreSQL
补丁元数据 补丁名称、版本、依赖、发布时间 MySQL / PostgreSQL
任务与日志 下发记录、执行状态、错误日志 Elasticsearch / 时序数据库

注意:不要把任务日志存在关系型数据库里。我见过有人把几百万条执行记录塞进 MySQL,结果查询一次补丁历史要等 30 秒。日志类数据,用 ES 或时序库,查询快得多。

2.2.4 Web 控制台

Web 控制台是运维人员的操作界面。功能上,我建议至少包含:

  • 仪表盘:总览补丁覆盖率、成功率
  • 补丁管理:上传、审核、下架
  • 任务下发:选择目标、设置策略、一键执行
  • 报表导出:按部门、按时间导出补丁安装情况

技术栈上,我个人偏好 Vue 或 React,后端 API 用 RESTful 或 gRPC。别搞太复杂,运维工具追求的是稳定和效率,不是花哨的动画。

2.3 高可用设计思路

系统搭好了,万一 Server 挂了怎么办?Agent 连不上怎么办?高可用不是锦上添花,是保命用的。

2.3.1 Server 高可用

Server 无状态化是关键。把 Session 扔到 Redis 里,把任务状态存到数据库,Server 本身只做计算和转发。这样前面挂个负载均衡,后面部署 2 台或 3 台 Server,任何一台挂了,流量自动切走。

核心思路:Server 不存任何本地状态。重启等于新生,所有状态从数据库和 Redis 恢复。

2.3.2 Agent 高可用

Agent 的高可用,体现在“断连自愈”。

我曾经遇到过 Server 机房断电,Agent 连不上 Server 就开始疯狂重连,把备份机房的网络都打满了。后来我改了策略:

  1. Agent 配置多个 Server 地址,主备切换
  2. 重连间隔指数退避:1s → 2s → 4s → 8s …… 最大 5 分钟
  3. 断连期间,本地缓存待执行的补丁任务,恢复后继续

2.3.3 数据库高可用

数据库这块,我推荐主从 + 自动故障转移。MySQL 用 MHA 或 Orchestrator,PostgreSQL 用 Patroni。读多写少的场景,可以加一个只读从库分担查询压力。

小技巧:补丁包本身不要放数据库,太大了。用对象存储(MinIO 或 S3),数据库只存路径。这样数据库挂了,补丁包还在,恢复后重新索引就行。

2.4 架构总览图

说了这么多,画张图帮你串起来。下面这张 SVG 展示了系统的核心架构和通信关系:

自动化补丁分发系统架构总览 Web 控制台 负载均衡 (Nginx) Server 主 Server 备 Server 备 MySQL 主 MySQL 从 MinIO 对象存储 Agent 集群 Agent 集群 Agent 集群 说明:Web 控制台通过负载均衡访问 Server 集群,Server 读写数据库和对象存储,Agent 与 Server 保持长连接

从图上你能看到,整个系统是分层解耦的。每一层都可以独立扩展,任何单点故障都不会导致系统瘫痪。这就是高可用的核心思想——没有单点,自动切换。

2.5 本章小结

架构设计没有银弹,但有一些基本原则可以遵循:

  • 控制台用 B/S,Agent 用 C/S,各取所长
  • 四个核心组件各司其职,不要混在一起
  • 高可用靠的是冗余和自动切换,不是靠祈祷