第3章:分层架构演进:为什么需要分层、经典三层架构、好处与挑战、实际项目中的分层实践
3.1 为什么我们需要分层?
先聊个我亲身经历的事。几年前我接手过一个交易系统,代码全写在一个大文件里。数据库查询、业务逻辑、网络通信全混在一起。你猜怎么着?每次改个订单状态,都得把整个流程捋一遍。改完一个bug,至少冒出两个新bug。
为什么会这样?说白了,就是没有分层。
分层架构的核心思想很简单:把不同职责的代码拆开。就像盖楼,你不能把地基、承重墙、水电管线全糊在一起。每一层只关心自己的事,层与层之间通过明确的接口通信。
我个人习惯把分层比作「三权分立」。接入层管「谁来敲门」,逻辑层管「怎么处理」,数据层管「东西放哪」。各司其职,互不干扰。
核心原则:每一层只对下层有依赖,上层不关心下层的实现细节。
3.2 经典三层架构
交易系统里最经典的分层,就是这三层:
| 层级 | 职责 | 常见组件 |
|---|---|---|
| 接入层 | 协议解析、会话管理、流量控制 | Gateway、Nginx、WebSocket Server |
| 逻辑层 | 业务编排、风控校验、订单处理 | Order Service、Risk Engine、Matcher |
| 数据层 | 持久化、缓存、数据一致性 | MySQL、Redis、Kafka |
下面这张图,是我在项目中常用的分层结构。你看一眼就明白了:
3.3 分层带来的好处
我在项目中体会最深的有这几点:
- 可维护性大幅提升——改接入层的协议,逻辑层完全不用动。我记得有一次把HTTP改成WebSocket,只改了接入层一个模块,逻辑层一行代码没碰。
- 团队协作更顺畅——前端团队管接入层,后端团队管逻辑层,DBA团队管数据层。各干各的,互不踩脚。
- 扩展性变强——想加个新的风控规则?在逻辑层加个模块就行。想换缓存方案?只改数据层。
- 测试更容易——每层都可以单独写单元测试。我习惯给逻辑层写mock测试,把数据层mock掉,专注测业务逻辑。
小技巧:分层之后,建议每层都定义清晰的接口契约。用protobuf或者OpenAPI规范,这样层与层之间就像插拔式组件,换起来特别方便。
3.4 分层带来的挑战
当然,分层也不是银弹。你想想看,它也有麻烦的地方:
- 性能损耗——每层之间都有序列化、网络开销。我见过一个系统,三层之间来回传对象,一次请求光序列化就占了30%的耗时。
- 调试困难——问题跨层的时候,你得一层一层排查。我曾经花了一整天,才发现是接入层把时间戳截断了,导致逻辑层计算错误。
- 过度设计——小项目硬套三层架构,反而增加复杂度。我建议:业务逻辑少于50个接口的项目,别急着分层。
避坑指南:我曾经在一个项目里,把逻辑层又拆了五层。结果呢?改一个需求要改四个文件。记住:分层不是越多越好,够用就行。
3.5 实际项目中的分层实践
说了这么多理论,来点实际的。我在一个日交易量过亿的系统中,是这样落地的:
接入层实践:
- 用Nginx做反向代理和限流
- 自定义Gateway处理协议转换
- 每个连接分配一个Session ID,用于追踪
逻辑层实践:
- 拆成多个微服务:Order Service、Risk Service、Settlement Service
- 服务之间通过gRPC通信
- 每个服务内部再分三层:Controller、Service、Repository
数据层实践:
- MySQL存核心账户数据
- Redis做热点缓存
- Kafka做异步消息和日志
嗯,这里要注意:数据层不要直接暴露给接入层。我见过有人图省事,让接入层直接查数据库。结果呢?接入层一个慢查询,把整个数据库拖垮了。
最后分享一个我踩过的坑。有一次,逻辑层需要调用数据层的一个存储过程。存储过程里有个bug,导致数据不一致。排查的时候,逻辑层说「我传的参数没问题」,数据层说「我执行的逻辑没问题」。最后发现是存储过程里有个隐式类型转换。从那以后,我要求所有跨层调用都必须显式声明类型。
分层架构,说白了就是「分而治之」的思想。它不完美,但确实是交易系统最稳妥的起点。你想想看,没有分层,那些千万级的订单量,根本没法维护。