第4章:整体架构分层——拆开KMS的五层蛋糕

说到知识管理系统的架构,我见过很多团队一上来就堆功能,结果半年后发现改不动、测不了、扩展无门。说白了,一个能撑住组织级体量的KMS,必须先把层分清楚。

这一章我们就聊透这五层:展示层、业务层、服务层、数据层、基础设施层。每层该放什么、不该放什么,我踩过的坑会一并交代。

核心观点:层与层之间只能通过接口通信,不能跳层直接操作数据。这条红线一破,架构就变质了。

4.1 展示层——用户看到的那个“面子”

展示层就是用户能摸到的所有界面。门户、搜索框、个人工作台、移动端H5,都算。

但这里有个常见的错——把业务逻辑也塞进前端。我在一个项目中就遇到过:前端直接写死了“文档审批流程”的判断条件,导致后端改了策略后前端还得跟着发版。这叫什么?这是把架构建在了沙滩上。

展示层该干的事:

  • 渲染UI组件,响应交互事件
  • 调用业务层的API,把数据展示出来
  • 做简单的格式验证(比如字段是否为空)
  • 缓存一些用户偏好(如布局、主题)

嗯,这里要注意:展示层不应该直接访问数据库。哪怕只是读一条“分类名称”,也得走业务层。我自己的习惯是,在前端项目里单独建一个 services/ 目录,专门放API调用,绝不掺杂SQL或业务计算。

4.2 业务层——真正有“脑子”的地方

业务层是KMS的大脑。权限判断、知识审核流程、标签自动推荐、文档版本管理……这些都得在这里完成。

为什么不在服务层做?服务层偏技术通用,而业务层关注的是组织特有的规则。比如一个合同知识库,审批链可能是“员工→主管→法务→归档”;换了另一个团队,可能只需要“员工→归档”。这种变化就该封装在业务层。

我曾经接手过一个系统,业务逻辑散落在服务层和展示层,光梳理“一个知识发布到底经过哪些校验”就花了两周。后来我们强制要求:所有业务规则必须写在 business/ 模块,并且用单元测试覆盖。从那以后,改动再也不怕炸到别的地方了。

层 典型职责 反例(我在项目中见过)
展示层 界面渲染、交互反馈 前端直接拼接SQL
业务层 组织策略、审批流、业务校验 业务规则写在存储过程里
服务层 通用技术能力、消息推送、文件处理 服务层硬编码业务字段
数据层 数据CRUD、索引、事务 数据层做业务计算
基础设施层 网络、存储、容器、监控 业务代码直接操作容器API

4.3 服务层——通用的“工具箱”

服务层放的是跟具体业务无关的技术能力。比如全文检索引擎(Elasticsearch)、文件转码(Office预览)、消息通知(邮件/钉钉/企微)、日志收集。

你想想看,如果每个业务模块都自己写一套“发送钉钉通知”的逻辑,是不是很蠢?所以服务层要做的是把这类能力抽象成 API,业务层只管调。

但请注意:服务层不能理解业务。比如一个“知识发布成功”的消息,服务层只负责投递,至于哪些人该收到、用什么模板渲染,那是业务层的事。我在项目里看到过服务层里写死了“部门经理”的收件逻辑,结果换了个部门结构就崩了。避坑指南:服务层所有入参和出参都应该是通用类型,业务字段用 Map 或 JSON 透传,别做解析。

我的经验:服务层尽量设计成无状态。部署时水平扩展,扛住搜索和通知的高并发。有状态的东西(比如用户会话)交给基础设施层的 Redis 集群。

4.4 数据层——最老实的“仓库管理员”

数据层只管三件事:存、读、查。索引优化、分库分表、事务隔离,都是这里的事。

很多时候架构出问题,就是因为数据层兼任了“业务计算”角色——用存储过程写复杂的报表逻辑,用触发器做状态流转。你猜后果是什么?数据库 CPU 跑满,迁移时没人敢动。

我个人的习惯是:数据层只提供简单的 CRUD 和最基本的过滤(按 ID、按时间范围)。任何需要 JOIN 三张表以上的复杂查询,都往服务层或业务层的搜索引擎走。为什么?因为数据库是扩展性最差的组件,别把压力堆在那里。

数据层的典型组件:

  1. 关系数据库(MySQL/PostgreSQL)——存知识条目、用户、权限
  2. 对象存储(MinIO/S3)——存文档原文、图片、附件
  3. 缓存(Redis)——存热点知识、会话数据
  4. 搜索引擎(Elasticsearch)——存倒排索引,支撑全文检索

4.5 基础设施层——地基和“水电煤”

这一层最容易被忽略,直到某个凌晨服务器宕了、磁盘满了、证书过期了,你才会发现它有多重要。

基础设施层包括:容器编排(K8s)、Service Mesh、API 网关、监控告警(Prometheus + Grafana)、日志管道(ELK)、CI/CD 流水线、DNS 和 CDN。

我记得有一次,团队花了两天排查“KMS 偶尔变慢”的问题,最后发现是同一台宿主机上另一个任务的 IO 打满了。从那以后,我们给每个 K8s Pod 都加了资源限制(requests/limits),并且把知识存储的磁盘挂载成独立的 SSD。

警告:基础设施层配置必须纳入版本管理,不能用“上线前去服务器上改一下”。我曾经见过生产环境的 Nginx 配置没有备份,扩容时只能靠人肉回忆。这种坑,踩一次就够。

4.6 五层架构的核心逻辑

光记住这五层还不够,关键要理解它们之间的依赖方向:展示层依赖业务层,业务层依赖服务层,服务层依赖数据层,数据层依赖基础设施层。反过来,下层不能依赖上层。这个单向依赖原则,是架构可维护性的命根子。

下面这张图你可以存下来,提醒团队的所有人:

KMS 五层架构核心依赖关系 展示层 门户 · 搜索框 · 移动端 H5 业务层 权限 · 审批流 · 标签推荐 服务层 全文检索 · 消息通知 · 文件转码 数据层 MySQL · Redis · ES · MinIO 基础设施层 K8s · 监控 · DNS · CDN 依赖方向 (上层依赖下层)

4.7 层间通信的黄金法则

光分层不行,还得定规矩。我一般会在项目初期就写下这些约定:

  • 展示层 → 业务层:只通过 REST 或 gRPC 调用,不得携带 SQL。
  • 业务层 → 服务层:通过 SDK 或内部 API,需要签名和超时熔断。
  • 服务层 → 数据层:通过 ORM 或 Repository 模式,禁止裸写 JDBC。
  • 数据层 → 基础设施层:通过配置中心获取连接串,不得硬编码。
一个实操技巧:在代码仓库里用 分层架构checklist.md 记录这些规则。每次 Code Review 时对着 check,违反的退回。坚持一个月,团队就养成习惯了。

4.8 避坑总结——我亲手踩过的三个雷

  1. 展示层直接调数据层。 某次为了“缩短搜索响应时间”,前端直接连了 Elasticsearch 的查询端口。后来权限泄露,内部知识被人爬了一天才发现。——现在我的原则:任何写在前端的数据库地址都是安全漏洞。
  2. 业务层和服务层混在一起。 有个版本把“知识发布”的业务校验和“文件转码”的服务逻辑写在一个模块里。结果转码服务升级,业务层也受影响一起重启。——拆干净,每个模块有独立的部署单元。
  3. 基础设施层没有声明式配置。 上面提过的 Nginx 配置未版本管理,导致扩容时手忙脚乱。现在所有基础设施定义(Dockerfile、Helm Chart、Prometheus Rule)都跟代码走同一个仓库。

好了,这五层框架就是你搭建或改造KMS的骨架。记住:架构的目的是让未来的人(包括三个月后的你自己)能快速定位问题、放心改动。下一层怎么落地?第5章我们会讲具体的技术选型和组件取舍。不过别着急,先把这几层的边界刻在脑子里。