- 文档
- 教程
- 后端
【免费下载链接】CodeGuide
:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、点赞、分享)!
本篇基于 《Netty+JavaFx 实战:仿桌面版微信聊天》专栏 中的服务端架构设计章节展开,讲解一个即时通信(IM)控制中心服务端的架构设计全过程:如何从业务目标出发提炼架构约束,在 MVC 与 DDD 两种模型之间做取舍,并把 DDD 四层结构(interfaces / application / domain / infrastructure)落地成真实工程骨架。读完本篇,你可以掌握一套"目标驱动"的服务端架构设计方法,以及 DDD 四层模型在 Netty 通信服务中的具体组织方式。
一、架构设计的核心理念:更适合才是更好的
"架构"这个词听起来高大上,但本质上并不神秘。哪怕是最初练习作业式的 CRUD,本身也是一种建构模式。架构设计的关键不在于堆砌先进概念,而在于找到与业务体量相匹配的模型:
- 一个只有几十人访问的小型工程,没有必要非得上分布式;
- 也不是硬要在十万并发的场景下直连数据库。
正如 服务端架构设计 一文开篇强调的:只有适合你业务的,才是更好的架构。
同时,一个架构模型的诞生远不止结构上的分层,还包括多种技术及相应内部业务模块的融合。例如:
- 服务基础使用 Spring 还是 SpringBoot;
- 需要 RPC 时选择 Dubbo;
- 缓存使用 Redis;
- 数据库分库分表用 MyCat;
- 文件系统使用 ES;
- 以及自己开发的一些中间件。
在 CodeGuide 仓库的 IM 实战专栏中,这套技术融合最终收敛为 JavaFx + Netty4.x + SpringBoot + Mysql 的组合,并以偏向 DDD 领域驱动设计的方式组织工程结构。下文以该专栏中"通信服务的控制中心服务端"为具体对象,拆解架构设计的目标与模型选择。
二、架构目标:设计之前先回答"为什么这样设计"
如何设计"适合当下需要"的架构?基本方法是先找到符合业务诉求的目标——每一个设计决策都要能回答"我们之所以这样设计是为什么"。针对 IM 通信服务端,2.1 服务端架构设计 提出了四条明确的架构目标:
- Web 管理面:服务端要有 web 页面来管理通信用户,以及对服务端本身进行控制和监控;
- 数据对象隔离性:数据库的对象类不能被外部污染、要有隔离性。例如,如果把数据库类暴露给外部当展示类使用,当需要新增一个"仅用于展示、数据库中并不存在"的字段时,数据库对象就已经被污染了;
- 通信协议抽离为独立 Jar 包:由于服务端与客户端都使用 Java 语言实现 Netty 通信,双方都要使用通信过程中的协议定义和解析,因此必须抽离这一层,对外提供 Jar 包;
- 分层职责清晰:接口、业务处理、底层服务、通信交互,要有明确的区分和实现,避免造成混乱难以维护。
这四条目标分别对应了后文架构模型中的具体分层:目标 1 落在接口的 web 管理面上,目标 2 落在领域层与基础设施层的隔离上,目标 3 落成独立的通信协议包(详见 2.2 通信协议包定义),目标 4 则由整体分层结构保证。
三、架构模型选型:MVC 与 DDD 的取舍
结合上述四条目标,需要在两种熟悉的架构模型中做出选择:一种是大多数 Java 开发者非常熟悉的MVC,另一种是DDD 领域驱动设计。
3.1 MVC 结构的局限:贫血模型与腐化风险
MVC 分层是一种典型的"贫血模型"设计,它把状态(PO/VO/Enum)和行为(Service 逻辑)分离到不同包中:domain 里写数据对象,service 里写功能逻辑。这种结构前期交付速度非常快,但缺少上下文约束,长期迭代后会出现 CodeGuide 架构重构专题 中总结的腐化问题:
- 贫血对象被众多 Service 交叉使用,Service 之间又相互调用;
- 对象、服务、组件的边界越来越模糊——"一条裤子被加肥加大,所有人都穿";
- 对应 IM 服务端的"数据对象隔离"目标(架构目标 2),MVC 结构没有天然的机制阻止数据库对象被上层直接引用,隔离只能靠开发自觉。
3.2 DDD 四层结构:各司其职的工程模型
从源码结构看,IM 专栏最终选定的 DDD 四层模型,其工程实现在 3.7 服务端控制台搭建 一文中给出了完整骨架:
itstack-naive-chat-server └── src ├── main │ ├── java │ │ └── org.itstack.naive.chat │ │ ├── application │ │ ├── domain │ │ ├── infrastructure │ │ ├── interfaces │ │ └── Application.java │ ├── resources │ │ ├── mybatis │ │ ├── spring │ │ └── application.yml │ └── webapp │ ├── chat │ ├── res │ ├── index.html │ └── res_layui.html └── test对照 MVC2DDD 架构重构 中讲解的 DDD 分层思想,这四层的职责可以这样理解:
| 分层 | 职责 | 对应 IM 服务端架构目标 |
|---|---|---|
| interfaces 接口层 | 提供接口实现、对外触发入口(HTTP/RPC/MQ/JOB 等触发器),是领域能力的触发器层 | 架构目标 1:web 管理面(Layui 页面 + 接口)与通信控制入口 |
| application 应用层 | 领域编排,对 domain 领域逻辑做封装组合处理;小项目可省略以降低成本 | 架构目标 4:接口与业务处理之间的编排边界 |
| domain 领域层 | 领域模型服务,核心模块;每个领域包内包含模型、仓储接口、领域服务三要素 | 架构目标 2:业务对象与持久化对象隔离,充血模型承载行为 |
| infrastructure 基础设施层 | 依赖 domain 定义的仓储接口做实现(依赖倒置),承载 MyBatis、Spring 配置、Netty 通信等底层能力 | 架构目标 3/4:通信交互与底层服务独立实现,不污染领域层 |
其中两个关键设计点值得展开:
- 依赖倒置:infrastructure 层依赖 domain 层而不是反过来。domain 层定义仓储接口,infrastructure 层的 DAO 去实现该接口。这样数据库对象(PO)只出现在基础设施层,领域层和业务层引用的是领域模型对象,架构目标 2 的"数据对象隔离"由此在结构上被强制保证;
- domain 是最大的模块:所有其他模块都围着 domain 转。领域内"模型 + 服务 + 仓储"自成闭环,就像把炸药包里的火药、引线、包布封装到一起使用。
3.3 与客户端架构的对称设计
服务端选定的分层思路在客户端侧同样贯彻。从 2.3 客户端架构设计 可以看到,客户端(工程 itstack-naive-chat-ui 对应的业务工程)采用了对称的分层:
- UI 层:使用 Maven 打包的 UI Jar 包,通过内部接口和事件操作 UI 展现、发起行为,强制 UI 与业务分离;
- 业务层:负责窗体中用户信息维护(好友、群组)以及对话信息收发,处理 UI 接口与事件;
- 协议包:即服务端抽离出的通信协议 Jar,中间穿插标识位区分登录、消息发送、添加好友等不同业务对象;
- 通信层:Netty 框架下的 Socket 通信,让开发聚焦业务;
- 运行环境:JDK 1.8 桌面环境。
服务端与客户端共享同一通信协议包,正是架构目标 3 的直接落地。
四、技术栈选型与配套设计
在分层结构确定后,IM 服务端的技术栈选型围绕"通信 + 管理 + 持久化"三条主线展开:
4.1 Netty:通信层的基础
Netty 是 JBOSS 提供的异步、事件驱动网络应用框架,被 Dubbo、RocketMQ 等大量企业级项目作为基础通信组件使用,能大幅简化 NIO 开发。IM 专栏在 2.2 通信协议包定义 中专门讨论了 Netty 的定位,并通过一系列案例(可对照 Netty 基础入门案例 阅读)掌握了字符串收发、对象传输、自定义编解码器处理半包粘包等内容后,才进入协议包设计。协议包的核心作用是:在数据帧中间穿插一位"标识帧",用来区分传输的是不同业务对象(登录、消息、好友等),这与 RPC 框架(如 Dubbo)对外提供接口描述 Jar 包的思路一致。
4.2 SpringBoot + MyBatis:管理面与持久化
从工程骨架看,resources/spring与resources/mybatis目录、application.yml配置表明服务端使用 SpringBoot 作为服务基础框架、MyBatis 作为 ORM 层,落在 infrastructure 层实现。库表设计在 2.4 数据库表结构设计 中完成,为体现核心功能,库表尽量简单、只保留核心业务字段,六个表分为三部分:
- 基础表:用户和群组的维护;
- 关联表:每个用户与好友、群组的关系;
- 行为表:用户与好友/群组产生的对话及聊天记录。
4.3 Layui:服务端控制台页面
为达成"web 页面管理通信用户及服务端控制监控"的架构目标 1,3.7 服务端控制台搭建 选用 Layui 作为后台页面框架(简单、干净、整洁、集成方式多样),页面结构放在webapp目录下(index.html、res_layui.html 等),用于查看 Netty 服务运行状态、用户在线列表和各维度通信信息。
五、总结:从目标到骨架的架构设计路径
回看 IM 服务端架构设计的完整路径,可以提炼出一条可复用的方法论:
- 先立目标:从业务诉求提炼出可检验的架构目标(管理面、对象隔离、协议抽离、职责清晰),而不是先画分层图;
- 再做选型:用目标去衡量 MVC 与 DDD——需要强制的数据对象隔离、需要清晰的接口/业务/底层/通信边界时,DDD 四层模型的结构性约束优于 MVC 的约定性约束;
- 后落骨架:把目标逐一对应到 interfaces / application / domain / infrastructure 的具体职责上,用依赖倒置保证基础设施层不污染领域层,用独立 Jar 包保证双端协议一致;
- 配套选型:Netty 承载通信、SpringBoot + MyBatis 承载管理与持久化、Layui 承载控制台页面,每项技术都只服务于一个架构目标。
这套"目标驱动 + 分层落地"的设计方式,也正是 CodeGuide 仓库中多个实战项目(IM、拼团、MCP 网关等)共同遵循的架构思路。
- 文档
- 教程
- 后端
【免费下载链接】CodeGuide
:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、点赞、分享)!
相关推荐
用 Netty 实践分布式 IM 即时通信系统:基于 JavaFx + SpringBoot + DDD 四层架构的仿微信桌面端全栈设计
用 Netty 实践分布式 IM 即时通信系统:基于 JavaFx + SpringBoot + DDD 四层架构的仿微信桌面端全栈设计 导读 本文以 Code
文档教程后端CodeGuide DDD落地实战:基于SpringBoot四层架构的领域驱动设计入门指南
CodeGuide DDD落地实战:基于SpringBoot四层架构的领域驱动设计入门指南 领域驱动设计(DDD)是一套把业务领域建模与软件架构设计相结合的指导
文档教程后端终极指南:CodeGuide架构设计中的DDD领域驱动设计落地实践
终极指南:CodeGuide架构设计中的DDD领域驱动设计落地实践 CodeGuide是GitHub加速计划中的重要项目,由小傅哥多年一线互联网Java开发经验
文档教程后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考