# 单体架构介绍

单体架构（Monolithic Architecture）是一种将所有功能打包在一个容器中运行的设计风格，一个实例中集成了一个系统的所有功能。通过负载均衡软件/设备实现多实例调用。

![单体架构示例](https://raw.githubusercontent.com/gudaoxuri/Microservices-Architecture/master/resources/images/monolithic-architecture.png)

上图为典型的单体架构示例，这种架构下我们多用Tomcat、JBoss或Weblogic做为服务容器，一个系统部署多个实例，负载均衡多通过随机或IP Hash等规则将终端请求路由到不同的实例。

在互联网早期，这种架构非常流行，时至今日单体架构以其开发、调试、部署简单的特性在一些特定场景下任然有着无可比拟的优势。

但我们从目前中大型项目的业务形态、复杂度及响应速度等维度回看单体架构时可以发现它存在如下几个问题：

* **扩展性差** 很难梳理功能依赖清单，一个功能点的变更往往很难评估其影响模块进而无法有效地组织测试，测试与发布都会需要整体部署，非常耗时。笔者早期参与过多个单体架构，个别项目代码量上百万，四五十号人共同开发，一个版本的迭代最少一个季度，一次部署需要近半个小时，而这还不是最糟糕的，有些单体架构的系统部署启动就要一天的时间，这对崇尚小版本快迭代的互联网产品几乎是不可接受的
* **无法实现复杂业务** 一个容器中实现所功能，服务耦合性高，需要极为精巧的设计。大家都了解过GoF的设计模式，但为什么实际开发中很少直接接触？一方面框架为我们做了很多封装，设计模式已融入了框架的最佳实践或编码规范之中，另一方面SOA化、微服务化让每个模块的代码尽可能地简洁明了，大家更多的工作只聚焦于业务的代码实现，在单体架构中为了实现业务解耦可能会大量地使用装饰器、观察者、适配器等，这无形中又提升了开发的门槛，能否聚焦业务实现而非架构设计是衡量一种架构好差的重要标准，后续我们会看到在Serverless下极致的体现
* **技术升级困难** 牵一发而动全身，无法模块化地实现技术框架地升级。在项目生命周期内我们不可能不去升级依赖框架/类库的版本，更有甚者会重新选择基础框架，比如从早期的struts到struts2再到spring mvc、spring boot，每一次变更都会伤筋动骨，但我们又不得不做，项目要可持续，试想现在还有谁会用struts或struts2呢？温和的、可循序渐进的技术升级也是我们所期望的
* **开发效率低** 每个成员都需要有完整的环境依赖，开发环境的搭建成本高，协同开发时版本冲突频繁，一个有问题的提交可能会影响其他所有同事的开发调试。达到一定代码量后编译慢启动慢，一次调试启动可能都要5、6分钟
* **不利于安全管理** 所有开发人员都拥有全量代码，在安全管控上存在很大风险，尤其是对用大量外包人员或新招大量开发人员的团队。个别公司要求员工用虚拟桌面（一种集中存储、操作受限的虚拟环境）以避免代码外流，但这种开发体验差、受员工抵触，故普及度极低

> ⚠ 这些问题目前读者只要有一定印象即可，后续会结合实例进一步说明。
>
> ❓ 用辨证的思维看待技术
>
> 相信有部分读者从业不久，听说过微服务，想着用微服务改造现有的单体架构系统，但这之中却忽略了架构的适用性。 不要为架构而架构，以笔者的经验看单体架构在初创公司、中小型系统、产品试错等场景下开发的周期快、对开发人员的技能要求低而任然被广泛地采用。 本书的目的不是推销微服务，如果您看完本书从而打消微服务化改造那是笔者值得欣慰的一件事。
