后端分层
推荐依赖方向:
controller -> app/service -> domain -> infrastructure/mapper每层职责:
controller:接收参数、权限入口、统一返回app/service:编排用例、写审计、发事件domain:业务规则、状态约束infrastructure:数据库、Redis、外部 API、Outbox、任务
这个分层的重点不是“为了看起来像 DDD”,而是为了把三个最容易失控的东西拆开:
接口层协议处理
业务规则与编排
技术基础设施接入
只要这三件事混在一起,后面权限、审计、异步事件、事务边界就会越来越难维护。
不允许的做法
controller 直接操作 mapper
模块 A 直接改模块 B 的表
因为“赶时间”就绕过统一异常、审计、权限上下文
在多个模块里各自复制一套同类规则
system-service 的定位要特别看清
system-service 是平台控制面的核心服务,但它不是“什么都往里放”的大总管。它更像是平台内核,主要维护:
用户和组织主数据
角色、权限、菜单、权限快照
系统配置、字典、审计
平台级 AI 管理、在线会话、监控视图
如果一个能力具备独立数据生命周期、独立高频链路、独立扩容需求,就应该至少保持内部边界清晰,必要时进入独立服务评估,而不是继续无限吸收到 system-service。
当前关键模块边界
auth-service
负责:
登录、登出、刷新 token
登录保护、验证码、二次认证
Passkey、微信登录
不负责:
菜单树
角色权限分配
业务资源的数据范围判断
它负责证明“你是谁”,但不负责定义“你能做什么”。
system-service
负责平台控制面:
IAM、用户、角色、菜单、权限快照
系统配置、字典、审计
AI 管理、在线会话、系统监控
不应该无限吸收所有业务能力。
可以把它理解成平台控制面的 owner,而不是所有业务域的默认收容站。
file-service
负责:
上传、下载、预览
图片与文档安全校验
存储空间与 bucket 管理
它是文件 owner,其他模块需要文件对象时应通过它提供的契约接入。
文件一旦成为系统级资源,就很容易被很多地方共用。越是这种能力,越要明确 owner,不能把文件元数据散落在多个模块各管一份。
message-service
负责:
站内信
消息推送
消息 outbox 与实时投递
它的重点不仅是“发消息”,还包括消息状态、投递链路、重放与实时性保障。
plugin-service
负责:
插件包上传、安装、启停
插件运行时隔离
插件网关主流程
localization-service
虽然经常被忽略,但它本质上也是独立 owner 模块,负责:
语言定义
命名空间
词条与翻译内容
发布后的运行时语言包
owner 意识
在这个仓库里,“模块在不在一个进程里”不是重点,“谁是 owner”才是重点。
判断 owner 时优先看:
表是谁维护
生命周期由谁定义
权限由谁解释
异步事件由谁发出
允许的依赖方向到底意味着什么
推荐依赖方向:
controller -> app/service -> domain -> infrastructure/mapper对应到实际开发时,可以这样理解:
controller只负责入参、出参、权限入口和 HTTP 协议层细节app/service负责编排用例,比如“保存主对象 -> 写审计 -> 记录事件”domain负责规则,例如状态流转、字段约束、业务不变量infrastructure负责把这些规则落到数据库、Redis、外部服务、任务或文件系统上
这条依赖方向一旦被破坏,常见后果是:
控制器里开始堆事务和业务逻辑
规则散落在 mapper、util、定时任务里
事件和审计漏写
权限与数据边界越来越不清楚
新增能力放哪里
新增模块前先问自己三个问题:
这是平台控制面能力,还是独立业务域能力
它的数据和生命周期属于谁
它是否需要独立扩容、独立发布或独立事件链路
如果答案偏向独立业务域,就不要默认往 system-service 里塞。
什么时候应该评估“独立服务化”
满足以下任意两项时,就应该进入独立服务评估,而不是继续当成 system-service 的附属能力:
拥有独立表族和清晰生命周期
有自己的高频读写或异步处理链路
需要独立扩容
需要独立发布窗口
故障不应该拖垮平台控制面主链路
当前最值得持续关注的方向通常包括:
AI 相关能力
插件运行时
本地化发布
文件治理与处理链路