从‘大泥球’到‘乐高积木’:一个后端工程师眼中的架构演进史

张开发
2026/6/6 19:32:43 15 分钟阅读

分享文章

从‘大泥球’到‘乐高积木’:一个后端工程师眼中的架构演进史
从“大泥球”到“乐高积木”一位架构师的十年演进手记第一次推开那扇贴着核心系统标签的机房大门时扑面而来的是一股混合着灰尘与热风的陈旧气息。眼前那台嗡嗡作响的IBM小型机里跑着我们公司价值数十亿交易的核心系统——一个超过200万行代码的庞然大物。我的导师老张拍了拍我的肩膀说欢迎来到大泥球乐园这里的每一行代码都像意大利面一样纠缠不清。那是2013年我职业生涯的起点也是我与架构演进这场漫长马拉松的起点。1. 石器时代单体架构的生存法则在移动互联网爆发的前夜我们像中世纪工匠般精心雕琢着单体应用。所有的业务逻辑——从用户登录到订单结算都被塞进同一个WAR包里。Spring Struts Hibernate的三件套是当时的标准配置而分层架构是我们最后的尊严。典型单体架构的技术栈组合┌───────────────────────┐ │ Presentation │ ← Struts2/JSP ├───────────────────────┤ │ Business │ ← Spring IOC/AOP ├───────────────────────┤ │ Persistence │ ← Hibernate/JDBC ├───────────────────────┤ │ Database │ ← Oracle/MySQL └───────────────────────┘这种架构在早期给我们带来了惊人的开发效率本地调试时F5刷新就能看到修改效果一个war包扔进Tomcat就能完成部署事务管理简单到加个Transactional注解就行但随着业务量每年300%的增长这个完美系统开始显露出狰狞面目大泥球架构的典型症状编译噩梦全量编译需要25分钟工程师们发明了咖啡编译法——按下编译键后正好够冲杯咖啡部署恐惧每次上线都像拆弹某个业务线的BUG可能导致整个系统瘫痪技术债陷阱没人敢动十年前的老代码就像不敢碰考古现场的脆弱文物最难忘的是2015年双十一前夜促销活动的一个小修改导致整个支付模块崩溃。我们十几个工程师挤在会议室里在满是汗味的空气中通宵回滚版本。那一刻我明白了要么改变架构要么准备随时带着睡袋上班。2. 青铜时代垂直拆分的阵痛第一次架构演进像一场外科手术。我们按照业务域将系统拆分为用户中心商品服务订单引擎支付网关垂直架构 vs 单体架构对比维度单体架构垂直架构部署单元单个应用多个独立应用数据库共享数据库分库但同实例技术栈必须统一可差异化发布风险全有或全无局部影响团队协作高度耦合按业务线分工这个阶段我们收获的不仅是架构上的解耦更重要的是团队协作模式的转变。每个小团队开始对自己的服务负责出现了最早的你动我接口试试的微服务前兆文化。但新的问题很快浮现数据孤岛用户信息要在三个系统间同步最终我们发明了最终一致性的委婉说法来掩盖数据不同步调用混乱服务间直接HTTP调用形成了蜘蛛网般的依赖关系工具缺失没有统一监控故障排查就像在迷宫里摸黑找人记得当时为了排查一个订单状态不同步的问题我不得不同时分析四个系统的日志。最终发现是商品服务用了GET请求修改库存而nginx有缓存策略。这次事件后我们制定了第一条架构原则写操作必须用POST。3. 铁器时代SOA与ESB的荣光2017年引入ESB企业服务总线是我们向规范化迈出的重要一步。IBM Integration Bus成为我们的中枢神经系统所有服务调用都必须通过这条高速公路。ESB时代的典型调用流程[客户端] → [ESB] → [服务A] → [ESB] → [服务B] ↑ ↓ 协议转换 数据转换这个架构带来了显著优势统一监控所有流量都经过ESB调用链路一目了然协议转换老系统用SOAP新系统用RESTESB完美适配安全管控在ESB层统一做权限校验和流量控制但代价是性能的显著下降。某次大促时ESB集群成为瓶颈CPU飙升至98%。我们连夜紧急开发了ESB旁路机制允许部分关键服务直连——这实际上已经预示了ESB架构的黄昏。架构师笔记任何集中式组件都可能成为单点故障源越是核心的中间件越需要逃生方案这个阶段最大的收获是服务契约意识的建立。我们制定了严格的接口规范版本号必须显式声明字段变更需要兼容三个版本接口文档与代码同步更新这些规范后来成为我们微服务化的基石。4. 蒸汽时代微服务的狂飙与反思2018年Spring Cloud的成熟让我们终于迈入微服务时代。第一批上线的用户服务只有8000行代码部署时间从原来的15分钟缩短到45秒这种对比带来的震撼无以言表。微服务技术栈选型// 服务注册与发现 EnableEurekaServer public class RegistryCenter {} // 声明式REST客户端 FeignClient(name inventory-service) public interface InventoryClient { PostMapping(/stock/deduct) ResultBoolean deductStock(RequestBody StockDTO dto); } // 熔断保护 Slf4j public class PaymentFallback implements PaymentClient { Override public ResultString createPayment(PaymentDTO dto) { log.warn(Payment service unavailable); return Result.timeout(); } }微服务化过程中我们踩过的典型坑分布式事务尝试实现Saga模式时补偿操作比主流程还复杂链路追踪没有统一traceId时跨服务排查问题如同大海捞针配置管理某次Nacos配置错误导致半数服务不可用接口兼容修改接口时漏掉某个移动端版本引发大量用户投诉微服务拆分原则演进时期拆分依据典型问题1.0阶段按业务功能服务粒度不均匀2.0阶段按变更频率依赖关系复杂3.0阶段DDD限界上下文领域模型理解成本高当前团队拓扑结构需要组织架构调整配合最深刻的教训来自一次错误的拆分我们把商品搜索和商品管理拆分成两个服务结果两者都需要完整的商品数据模型导致大量重复代码。后来采用共享内核模式才解决这个问题。5. 电气时代ServiceMesh的曙光当服务数量突破50个时我们发现Spring Cloud的Java生态限制越来越明显。2021年引入Istio服务网格将服务治理能力下沉到基础设施层就像给城市装上了智能交通系统。ServiceMesh带来的变革多语言支持# Python服务无需任何SDK即可接入 from requests import get resp get(http://inventory-service/stock?sku123)可视化治理# 通过istioctl实现流量管理 istioctl set-route -n orderservice /checkout v2 -w 10%无侵入可观测性[2023-01-01T12:00:00Z] OUTBOUND 200 12ms POST /api/orders ├─ [product-service] 200 8ms GET /products/123 └─ [inventory-service] 200 5ms POST /stock/deduct但ServiceMesh并非银弹。初期我们低估了sidecar带来的资源开销——每个Pod增加0.5核CPU和512MB内存需求直接导致集群成本上升30%。经过半年调优才将额外开销控制在15%以内。6. 未来中台化与Serverless的思考现在的架构已经演变为混合形态核心交易采用微服务ServiceMesh创新业务尝试Serverless数据分析走Flink实时计算架构选择决策树是否需要快速迭代? → 是 → 是否需要强一致性? → 是 → 微服务 ↓ 否 → Serverless ↓ 否 → 是否是遗留系统? → 是 → 服务网格 ↓ 否 → 单体架构站在十年这个节点回望架构演进从来不是单纯的技术决策。每次变革都伴随着研发流程的重构从瀑布到敏捷到DevOps组织架构的调整从职能团队到特性团队工程师思维的转变从实施者到产品owner那些深夜的故障复盘、凌晨的发布窗口、争吵的技术方案最终都沉淀为团队的技术基因。或许正如康威定律所言设计系统的架构受制于产生这些设计的组织的沟通结构。

更多文章