C_Meng PSNA

Never wait for the storm to pass, just dance in the rain.

0%

什么是一体化架构(Monolithic Architecture)

背景

假设你在开发一个服务端应用。该应用必须支持各种各样的客户端,包括桌面浏览器、手机浏览器和本地手机应用。应用可能也需要公开部分API供第三方使用,还可能与其他应用通过web service或消息代理(message broker)相集成。应用执行业务逻辑来处理请求(HTTP请求或者消息);访问数据库;与其他系统交换消息;并返回HTML/JSON/XML类型的响应。

应用或是多层架构或是六角架构,并且包含多种类型的组件:

  • 表示组件(Presentation components) - 响应处理HTTP请求,并返回HTML或JSON/XML(对于web service API)
  • 业务逻辑(Business logic) - 应用的业务逻辑
  • 数据库访问逻辑(Database access logic) - 数据访问对象用于访问数据库
  • 应用集成逻辑(Application integration logic) - 消息层,如基于Spring的集成

这些逻辑组件分别响应应用中不同的功能模块。

问题

应用的部署架构是什么?

动机

  • 该应用由一个开发者团队在维护
  • 团队新成员必须快速上手
  • 应用应该易于理解和修改
  • 你想对应用进行持续集成
  • 你必须在多台机器上部署多份应用的拷贝,以满足可伸缩性和可用性的要求
  • 你想使用新技术(框架、编程语言等)

解决方案

使用一体化架构构建应用。如:

  • 单个Java WAR文件
  • 单个Rails或NodeJS目录结构

举例

我们假设你在构建一个电子商务应用,应用从客户接收订单,验证库存和可用额度,并派送订单。应用包含多个组件,包括StoreFrontUI,用来实现用户接口,以及一些后台服务,用于检测信用额度、维护库存和派送订单。

应用作为一体应用部署。例如,一个Java web应用运行在Tomcat之类web容器上,仅包含单个WAR文件;一个Rails应用使用Phusion Passenger部署在Apache/Nginx上,或者使用JRuby部署在Tomcat上,它们都仅包含单个目录结构。为了伸缩和提高可用性,你可以在一个负载均衡器下面运行该应用的多份实例。

结果

这个方案有一些好处:

  • 易于开发 - 当前开发工具和IDE的目标就是支持这种一体应用的开发
  • 易于部署 - 你只需要将WAR文件或目录结构放到合适的运行环境下
  • 易于伸缩 - 你只需要在负载均衡器下面运行应用的多份拷贝就可以伸缩

但是,一旦应用变大、团队增长,这种方法的缺点就愈加明显:

  • 巨大的一体代码库可能会吓到开发者,尤其是团队的新人。应用难于理解和修改。因此,开发速度通常会减缓。另外,由于没有模块硬边界,模块化也随时间而破坏。还有,因为难于理解如何实现变更,代码质量也随时间下降。这是个恶性循环!
  • 超载的IDE - 代码库越大,IDE越慢,开发者效率越低。
  • 超载的web容器 - 应用越大,容器启动时间越长。因此开发者大量的时间被浪费在等待容器启动上。这也会影响到部署。
  • 难于持续部署 - 对于频繁部署,巨大的一体应用也是个问题。为了更新一个组件,你必须重新部署整个应用。这还会中断后台任务(如Java应用的Quartz作业),不管变更是否影响到这些任务,此外还可能引发问题。未被更新的组件也可能因而不能正常启动。因此,鉴于重新部署的相关风险会增加,不鼓励频繁更新。这尤其对用户界面的开发者来说是个问题,因为他们通常需要快速迭代,频繁重新部署。
  • 难于伸缩应用 - 一体架构只能在一个维度伸缩。一方面,它可以通过运行多个拷贝来伸缩满足业务量的增加。某些云服务甚至可以动态地根据负载调整应用实例的数量。但是另一方面,该架构不能伸缩满足数据量的增加。每个应用实例都要访问全部数据,这使缓存低效,并且提升了内存占用和I/O流量。而且,不同的组件所需资源不同 - 有些可能是CPU密集型的,另一些可能是内存密集型的。一体架构下,我们不能独立伸缩各个组件。
  • 难于调整开发规模 - 一体应用对调整开发规模也是个障碍。一旦应用达到一定规模,将工程组织分成专注于特定功能模块的团队通常更有效。比如,我们可能需要UI团队,会计团队,库存团队等。一体应用的问题是它阻碍组织团队相互独立地工作。团队之间必须在开发进度和重新部署上进行协调。对团队来说也很难改变和更新产品。
  • 需要对一个技术栈长期投入 - 一体架构迫使你娶下开发初选择的技术栈(某些情况下,是那项技术的某个版本)。一体架构下,很难递增式地采用更新的技术。比如,想象下你选了JVM。除了Java你还可以选择其他使用JVM的语言,它们比如Groovy和Scala也可以与Java很好地进行互操作。但是一体架构下,非JVM语言写的组件就不行。而且,如果应用使用了后期过时的平台框架,将应用迁移到更新更好的框架上就很有挑战性。还有可能,为了采用新的平台框架,你要重写整个应用,这就太冒险了。

相关模式

微服务架构是解决一体化架构缺点的替代模式。

已知案例

著名的互联网服务,如Netflix, Amazon.com和eBay开始都使用一体架构。作者开发的大部分web应用也是一体架构的。

译自:
https://microservices.io/patterns/monolithic.html