本文系转载,原作者,普元,敖显奇
在 web 应用开发过程中,业界对前后端的分界线似乎一直都没有确定的概念,不过大多数人以浏览器作为前后端的分界线。将浏览器中为用户进行页面展示的部分称为前端,而将运行于服务器,为前端提供业务逻辑和数据准备的所有代码统称为后端。
虽然前后端分离在数年前就已经开始受到关注,但很多人对它却是只闻其声,未见其形,所以对它产生了一些误解,误以为前后段分离只是一种 Web 应用的开发模式,只要在 Web 应用的开发期进行了前后端开发工作的分工就是前后端分离。
其实并非如此, 准确的说,前后端分离并不只是开发模式,而是 Web 应用的一种架构模式
。在开发期,前后端工程师可以通过约定好交互接口,实现并行开发;在运行期,前后端分离模式需要对 Web 应用进行分离部署,前后端之间使用 HTTP 请求进行交互。然而作为应用的架构模式,前后端分离并不是通过这样一句话就能一概而谈的,我们可以从交互形式、代码组织方式、开发模式三个方面对前后端分离进行认识。
1、交互形式
在前后端分离架构中,后端只需要负责按照约定的数据格式向前端提供可调用的 API 服务即可。前后端之间通过 HTTP 请求进行交互,前端获取到数据后,进行页面的装配和渲染。
2、代码组织方式
在传统架构模式中,前后端代码存放于同一个代码库中,甚至是同一工程目录下。页面中还夹杂着后端代码。前后端工程师进行开发时,都必须把整个项目导入到开发工具中。
而前后端分离模式在代码组织形式上有以下两种:
半分离
前后端共用一个代码库,但是代码分别存放在两个工程中。后端不关心或很少关心前端元素的输出情况,前端不能独立进行开发和测试,项目中缺乏前后端交互的测试用例。
分离
前后端代码库分离,前端代码中有可以进行 Mock 测试(通过构造虚拟测试对象以简化测试环境的方法)的伪后端,能支持前端的独立开发和测试。而后端代码中除了功能实现外,还有着详细的测试用例,以保证 API 的可用性,降低集成风险。
3、开发模式
传统的 MVC 架构开发,没有进行前后端分离,前端工程师负责编写 html,完成前端页面设计,然后给后端工程师员套界面,使用模板技术将前端代码转换成 JSP 页面,同时内嵌 java 代码。应用运行期,将全部代码进行打包,部署到同一服务器上,或者进行简单的动静态分离部署。
此时,应用的开发流程如下图所示。
在前后端分离架构中,前端工程师只需要编写 HTML、js、CSS 等前端资源,然后通过 HTTP 请求调用后端提供的服务即可。除了开发期的分离,在运行期前后端资源也会进行分离部署。
前后端分离之后,开发流程将如下图所示。
通过上面的两幅流程图,不难发现,在开发模式上,前后段分离不仅仅只是工程师的分工开发,更重要的意义在于实现了前后端的并行开发,和简化了开发流程。
重新认识前后端分离之后,想必大家心里都会有疑问,前后端分离模式与之前的 Web 应用架构相比可谓是大相径庭,我们为什么要进行前后端分离呢?正如莎士比亚在《哈姆雷特》中的经典名句一样,分还是不分,这是个问题。
从目前应用软件的发展趋势来看,一方面,用户越来越注重软件的体验感,随着互联网的蓬勃发展,应用开始走向多终端化;另一方面,大型应用的架构模式正纷纷向着云化、微服务化发展。
虽然过去的应用架构暂时还能支撑起当下应用的开发,但是各种弊端已经开始浮出水面,几年前能带来开发便捷优势的前后端代码混合模式,在当下已经成为了拖慢我们前进步伐的泥沼,让我们屡屡吃痛。我们之所以开始尝试前后端分离,是为了能在未来获得更好的发展,期望通过前后端分离架构,来为我们带来以下 4 个方面的提升。
为孵化优质产品打造精益团队
正如康威定律所述,产品是组织沟通结构的缩影,软件开发团队想要孵化出优质的产品,必须先打造一个精益的开发团队。开发团队的组织划分是如何影响产品的孵化呢,我们通过下面的示例来进行说明。
如果开发团队是按照业务边界进行划分的,开发出来的产品将可能会是微服务的架构。
如果开发团队分为前端团队、后台服务团队和 DBA 团队,产品将会成长为下面的架构。
应用不断迭代,功能日趋完善,开发团队也随之壮大。虽然现在有些人比较推崇全栈工程师,一位全栈工程师就能支持前后端的所有开发。但是试想一下,如果在开发团队中前后端开发分隔不清,职责边界模糊不明,代码均由相同的工程师完成,长此以往前后端代码的耦合程度可想而知。
通过将开发团队前后端分离化,让前后端工程师只需要专注于前端或后端的开发工作,使得前后端工程师分别自治,培养其独特的技术特性,然后构建出一个全栈式的精益开发团队。这样的开发团队能够快速应对需求的变更以及市场的复杂多变,打造出架构清晰、前后端并重的优质产品。
提升开发效率
传统开发模式中,前后端开发强依赖。需要前端工程师先完成静态页面的 Demo,后端工程师才能将页面 Demo 翻译成 VM 模板,如果前端页面出现变动,又会需要前后端工程师再走一次开发流程,如此一来开发效率将会变得很低。
前后端分离以后,可以实现前后端代码的解耦,只要前后端沟通约定好应用所需接口以及接口参数,便可以开始并行开发,无需等待对方的开发工作结束。与此同时,即使需求发生变更,只要接口与数据格式不变,后端开发人员就不需要修改代码,只要前端进行变动即可。如此一来整个应用的开发效率必然会有质的提升。
完美应对复杂多变的前端需求
Web 应用的用户体验关注度与日俱增,使得应用的前端界面需要有华丽酷炫的外观,简单易用的操作,变化多样的界面设计和个性化的自定义展示。这使得前端开始变重,逻辑复杂程度加大,渲染效果多样化加剧。
移动终端的大范围普及,让应用向着多终端化发展,这就要求前端页面需要对不同终端的显示都能进行配适。
传统开发模式中,前后端工程师开发职责不明确,面对复杂多变的前端需求,开发团队势必会变得捉襟见肘、不堪重负。
如果开发团队能完成前后端分离的转型,打造优秀的前后端团队,开发独立化,让开发人员做到专注专精,开发能力必然会有所提升,能够完美应对各种复杂多变的前端需求。
增强代码可维护性
前后端分离后,应用的代码不再是前后端混合,只有在运行期才会有调用依赖关系。应用代码将会变得整洁清晰,不论是代码阅读还是代码维护都会比以前轻松。
然而任何一项技术都不是银弹,前后端分离也是如此。虽然前后端分离架构能带来众多优势,但终究得建立在开发团队适合的基础之上。我们暂且以前端页面的渲染效果与逻辑复杂程度把 Web 应用大致分为轻前端、重前端、前后均衡三种类型,然后加上现在热门的微服务架构应用,一起探讨一下什么样的 Web 应用适合进行前后端分离。
轻前端
页面布局简单,颜色、字体类型较少
对前端界面的渲染效果没有高要求,无动画效果
只有少量、简单的业务逻辑
只需要在不同终端上布局能适应
对于这样对前端渲染要求不高,业务逻辑简单的轻前端应用来说,因为涉及到的前端技术并不复杂,所以没必要追求前后端分离。将前后端代码放到一起,反而更方便进行开发,但是在开发过程中需要做到关注点分离(Separate
Concern)。
重前端
页面布局复杂,使用了多种颜色和字体
需要有较高的页面渲染效果,有大量动画
前端页面中包含有复杂业务逻辑
需要在不同终端和浏览器上保证布局适应和渲染效果
对于重前端应用,建议采用前后端分离架构,如果开发团队中前端工程师不足,需要尽早完善前端团队的建设,确保前后端并重。
前后均衡
页面布局适中,使用的颜色和字体种类不多
页面中使用了少许动画效果
业务逻辑较为简单,可下沉到后端实现
只需要在不同终端上布局能适应
对于前后端均衡应用,建议综合团队的人员结构和未来发展方向进行考虑。如果在团队中前端工程师的占比不高,后续也没有继续发展前端的计划,那么就不建议过于追求前后端分离。如果对未来有更高期望,即使在前端工程师占比不高的情况下,依然建议团队尝试前后端分离转型,开始着手培养合适的前端工程师。如果团队中已经有了相当规模的前端工程师,建议立即转向前后端分离,并且尽早做到前后端代码分离,为前端提供一个可以进行开发调试的伪后端。
微服务架构应用
微服务架构应用由大量微服务提供者构成,共同为用户提供服务。在微服务架构中,很多微服务提供者都是基于 SpringBoot 实现的,通过 API
Getway(API 网关)进行微服务的整合,然后在一个统一的前端门户上为用户提供所需服务。
微服务基于 SpringBoot 开发,要达到快速交付的目的,并且每个微服务的粒度都比较小,这必然需要微服务的前后端由不同的工程师分别实现,然后相互之间使用 Restful 进行通讯。如果还是沿用之前的开发模式,将会增大微服务架构应用的构建难度。而前后段分离模式正是解决这一难题的良药。
前后端开发分离之后,应用在部署时也需要进行前后端分离。在进行前后端分离方案选择的时候,需要结合项目的需求情况和用户群体来考虑。目前业内较为常用的前后端分离部署方案有如下几种。
1、Nginx+Server
将前端资源部署在 Nginx 上,后端服务部署在常规的服务器。当浏览器发起访问请求的时候,如果请求的是页面资源,Nginx 直接把资源返回到前端;如果请求是调用后端服务,则经过 Nginx 转发到后端服务器,完成响应后经 Nginx 返回到浏览器。
这个方案比较简单,易于实现,而且能达到前后端解耦的目的。
但是对于页面量比较大,需要有良好 SEO 的应用来说,此方案缺点也较为明显。因为 Nginx 只是向浏览器返回页面静态资源,而国内的搜索引擎爬虫只会抓取静态数据,不会解析页面中的 js,这使得应用得不到良好的搜索引擎支持。同时因为 Nginx 不会进行页面的组装渲染,需要把静态页面返回到浏览器,然后完成渲染工作,这加重了浏览器的渲染负担。
2、Node+Server
这是淘宝所使用的前后端分离模式,在浏览器与后端服务器之间增加一个了 Node Server 作为中间层,将前端资源部署到 Node Server 中。Node
Server 中还包含了一层 Model Proxy,负责与服务端进行通信。
浏览器发出的请求都被 Node Server 接收,然后通过 Model Proxy 调用后端服务器提供的服务。Node
Server 得到后端服务器反馈,接着在 Node Server 中完成页面的组装渲染,把最终页面返回给浏览器。
如此一来不仅达到了前后端解耦的目的,还解决了浏览器渲染负担过重的问题,为 SEO 提供了比较好的支持。
但在这样的模式中,浏览器所有发出的请求都需要经过 Node
Server 进行中转,然后才能到达后端服务器。在实际的应用中,并不是所有的请求都需要页面渲染,只要在页面上直接调用后端服务器提供的服务即可。所以这个模式必然会对请求性能有所消耗
3、Nginx+Node+Server
为了能解决方案 2 中请求性能损失的问题,我们可以考虑在其基础之上增加 Nginx。浏览器发起的请求经过 Nginx 进行分发,URL 请求统一分发到 Node
Server,在 Node Server 中进行页面组装渲染;API 请求则直接发送到后端服务器,完成响应。
目前在已经有一个名为 Goku 的 Go 语言框架提供了这样的前后端分离解决方案。
通过对三种前后端分离方案的对比可以看出:
如果是企业级应用,不需要考虑对 SEO 的支持,浏览器渲染也可以忽略不计,Nginx+Server 的模式无疑是最好的选择,实施成本相对来说比较低;
如果是互联网应用,需要有良好的 SEO 支持,页面渲染工作量大,那应该选择 Nginx+Node+Server 的方案,各个方面都能得到比较好的兼顾。
前后端分离并非仅仅只是前后端开发的分工,而是在开发期进行代码存放分离、前后端开发职责分离,前后端能够独立进行开发测试;在运行期进行应用部署分离,前后端之间通过 HTTP 请求进行通讯。前后端分离的开发模式与传统模式相比,能为我们提升开发效率、增强代码可维护性,让我们有规划地打造一个前后端并重的精益开发团队,更好地应对越来越复杂多变的 Web 应用开发需求。
传统的前后端混合开发模式,虽然久经考验,到现在依然还是能支撑起应用的开发。但是放眼未来,应用的云化、微服务化势不可挡。同社会分工精细化一样,前后端开发的精细化也是必然趋势。技术在持续进步,架构在不断演进,只有紧跟发展的脚步,不断调整项目管理方式,软件开发模式,才能在互联网浪潮中把握机会,乘风破浪。
前后端分离,是为了让彼此更好。
来源: https://juejin.im/entry/5a33290ef265da431876c832