Elexvx
架构设计

系统总览

理解 Legendary Invention 当前的单体微服务形态、请求主链路和架构演进方向。

当前架构是什么

当前主线不是“完全拆开的多进程微服务”,而是:

  • 运行时采用单个后端入口 legendary-server
  • 代码仍保留模块化微服务边界
  • 所有外部请求统一从 /api 进入

这可以理解为“单体微服务”或“模块化单体的聚合运行形态”。

为什么这样设计

这样做的目标是同时得到两类收益:

  • 运行更简单:本地和生产默认只维护一个后端进程
  • 边界更清晰:认证、系统、文件、消息等模块仍能独立治理

它适合当前阶段的团队效率,也为未来重新拆分服务保留了演进空间。换句话说,系统不是因为“微服务失败了”才变成聚合运行,而是主动选择了一个更容易稳定交付、同时不牺牲边界治理的形态。

请求主链路

frontend -> /api -> api-proxy -> legendary-server -> module -> database/cache/outbox

在这个链路里:

  • 前端只关心 /api
  • api-proxy 负责统一代理和入口治理
  • legendary-server 负责实际承载业务模块

如果以后重新拆为物理微服务,前端这层调用路径仍然应该不变。变化只应该发生在代理层和后端部署拓扑里,而不是业务页面里。

主要模块

  • auth:登录、刷新 token、二次认证、Passkey、微信登录
  • system:用户、角色、菜单、配置、审计、AI、监控
  • file:上传下载、文件元数据、存储空间治理
  • message:站内消息、推送、归档
  • plugin:插件包与插件运行时
  • localization:语言、命名空间、词条、发布
  • job:后台任务与 outbox relay

模块之间应该怎么协作

当前仓库虽然聚合运行,但模块之间仍然要遵守边界。推荐的协作方式是:

  • 共享通用基础设施:通过 libs/common-*
  • 共享跨模块契约:通过 libs/legendary-api
  • 共享异步扩展点:通过 Outbox 事件
  • 共享用户、安全、租户、Trace 上下文:通过统一基础设施

不推荐的方式是:

  • 一个模块直接修改另一个模块的表
  • controller 绕过应用服务直接改别人数据
  • 为了一个页面需求临时复制一套权限逻辑
  • 前端根据猜测拼接后端内部地址

共享原则

  • 公共能力应放到 libs/*
  • 跨模块通信优先通过 libs/legendary-api 中的契约
  • 不要把模块边界因为“都在一个进程里”就随意打穿

现阶段最重要的几个 owner 维度

1. 数据 owner

一张表由谁定义、迁移、维护、解释,谁就是 owner。即使聚合运行,也不要跨模块直接把别人的表当成自己表来用。

2. 权限 owner

登录态、菜单显隐、按钮权限、数据范围不是一回事。认证、IAM、业务服务分别承担不同职责,不能混写。

3. 生命周期 owner

文件、消息、插件、知识库文档、角色授权这些对象的生命周期应由 owner 模块决定,其他模块只能通过契约或事件协作。

4. 事件 owner

异步事件必须由业务事实发生的 owner 模块发布,不要由外围模块“代发一个差不多的事件”。

对开发最有影响的架构结论

结论 1:新增功能先找 owner,再找目录

不要先问“这个代码放哪个包最顺手”,先问它属于谁、谁维护它、谁校验它、谁发布它的事件。

结论 2:前端统一走 /api

这不是风格问题,而是为了把未来部署变化隔离在代理层。

结论 3:单入口不代表统一大泥球

当前架构最怕的不是“模块太多”,而是“因为只剩一个进程,就开始无边界地共享实现”。那样后续无论维护还是拆分都会更难。

演进方向

未来如果需要拆回物理微服务,建议按模块 owner 顺序逐步拆分,例如:

  1. 先挑一个高边界清晰、高独立性的模块
  2. 补齐它的表归属、权限边界、事件边界和内部 API
  3. 再把运行入口从聚合进程中独立出去

也就是说,当前架构不是终点,但它已经是一个可长期运行的稳定形态。

推荐配套阅读

目录