场景
你正在开发一个服务器端的企业应用程序。它必须支持多种不同的客户端,包括桌面浏览器,移动浏览器和本地移动应用的。该应用程序还可能暴露于第三方消费的API。它也可能通过任何Web服务或一个消息代理其他应用程序的集成应用程序:处理通过执行业务逻辑请求(HTTP请求和消息); 访问数据库; 交换与其它系统的消息; 并返回一个HTML / JSON / XML响应。它有对应于应用的不同功能区的逻辑组件。问题
什么是应用程序的部署架构?要求
有一个应用的开发者团队新的团队成员必须迅速提高工作效率
该应用程序必须易于理解和修改
持续部署
必须以满足可扩展性和可用性要求运行在多台机器上的应用程序的多个副本
想利用新兴技术的优势(框架,编程语言等)
解决方案
建立一个单体架构的应用程序。例如:一个Java WAR文件。
一个单一的目录层次结构:Rails或者NodeJS
实例
让我们想象一下,你正在构建一个电子商务应用程序,有客户的订单,核实库存和可用信用等等。该应用程序由几个部分组成,包括StoreFrontUI,它实现了用户界面,带有用于检查信用,保持库存和运输订单一些后端服务。
该应用程序部署为一个单一的整体应用。例如,一个Java Web应用程序由一个web容器:如Tomcat运行单独WAR文件。Rails应用程序被部署在单个目录层次结构中,例如,乘客的Phusion部署在Tomcat的Apache / Nginx或JRuby上。您可以用负载均衡扩大规模的形式,运行多个应用实例,提高可用性。
这种场景的结果
首先,该解决方案有很多好处:开发简单 - 现有的开发工具和IDE的目标是支持的单一应用程序开发
部署简单 - 你只需要部署相应的运行时WAR文件(或目录结构)
简单的规模 - 您可以通过运行应用程序的多个副本扩展应用
然而,一旦应用程序变大和团队变大,这种方法有许多缺点:大型单体代码库吓跑新的团队成员,该应用程序可能很难理解和修改。其结果是,开发通常会减慢。此外,因为没有清晰的模块边缘界定,随着时间的推移,它可能很难明白如何正确地实施代码变更。质量随时间下降,这是一个向下的螺旋。
IDE负担过重 - 大型的代码库使得IDE变得缓慢,影响了开发者的效率。
Web容器负担过重 - 更大的应用程序需要更长的时间启动。也因此,这极大的消耗了开发效率,因为对于开发人员来说,他们不得不等待容器的启动。
持续部署困难 - 一个大的整体应用也是一个频繁部署的障碍。为了更新一个组件,你必须重新部署整个应用程序。这将中断后台任务,先忽略他们是否会因为变化,而产生新的问题。另外,组件更新失败,将影响其应用的正常启动。其结果是,随着更新,风险增加,阻碍了频繁的开发迭代。这通常是用户界面开发者的问题,因为他们通常需要快速迭代,并经常重新部署。
应用程序扩展困难 - 单体架构是,它可以在一个维中只有规模。在一方面,它可以通过运行应用程序的多个副本与增加交易量规模。有些云服务,甚至可以动态调整负载实例的数量。但在另一方面,这种架构不能扩展数据量的规模。应用实例的每个副本将访问数据,这使得缓存不太有效,并增加内存消耗和I / O的流量。另外,不同的应用程序组件具有不同的资源要求 - 一个可能是CPU,而另一个可能占用大量内存密集型。在单体架构中,我们不能独立地扩展每个组件
阻碍发展 - 一个整体的应用也是一个缩放发展的障碍。一旦应用程序需要形成一个专业团队规模,例如,我们可能希望有UI团队,财务团队,库存团队等。单体应用系统的麻烦是,它防止团队独立工作。该团队必须协调发展和调动,使得团队变更和发展变得异常困难
需要一个长期稳定的技术栈 - 单体应用,可能很难能够逐步采用更新的技术。例如,假设您选择的JVM。你有一些语言的选择界限,就算在Java中,你可以使用其他JVM语言:比如Groovy和Scala与java协同开发。但是,你没有选择非JVM语言的能力。另外,如果您的应用程序使用的平台框架,随后变得过时,那么它非常具有挑战性——将应用逐步迁移到新的和更好的框架。