前后端分离模式研究

一、前言

         对目前的web来说,前后端分离已经变得越来越流行了,越来越多的企业/网站都开始往这个方向靠拢。前后端分离概念在今天其实并不新鲜,自以MVC模型为主的开发模式流行之初,前后端分离思想就被提出来了,但是经历了几十年的发展,前后端分离并没有得到实质的进步和应用。得益于前后端框架的丰富和发展以及接口文档自动化技术的出现,前后端分离于最近几年在很多的实践中得到了越来越好的应用和推崇。那么,什么是前后端分离呢?为什么要选择前后端分离呢?前后端分离对实际开发有什么好处呢?

二、背景

         在以前传统的网站或者系统开发中,前端的工作一般只是切图,简单的将UI设计师提供的原型图实现成静态的HTML页面。而具体的页面交互逻辑,如页面与数据的交互工作等,可能都是由后台开发人员来实现,或者是前端紧紧的耦合后台。比如以前的基于MVC架构的淘宝Web,架构决定了前端只能依赖后台,这种模式是前端写好静态demo,后端翻译成VM模板,同时后台还实现C层的逻辑。

    更有甚者,部门公司后台人员直接兼顾前端工作,一边实现API接口,一边开发页面。这导致后台的开发压力大大增加。前后端工作分配不均。不仅仅开发效率慢,而且代码维护困难。而前后端分离,则可以很好的解决前后端分工不均的问题。将更多的页面交互逻辑分配给前端来处理,而后端则可以专注于其本职工作,比如提供API接口,进行权限控制以及进行运算等工作。而前端开发人员则可以利用nodejs等来搭建自己的本地服务器,直接在本地开发,然后通过一些插件来将API请求转发到后台,这样就可以模拟线上的场景,并且与后台解耦。前端可以独立完成与用户交互的整个过程,这样前后端开发都可以同时开工,不互相依赖,开发效率更快,而且分工比较均衡。

三、前后端分离技术

1、MVC模型

         MVC是一种经典的设计模式,全名为Model-View-Controller,即模型-视图-控制器。MVC模式早在上个世纪70年代就诞生了,直到今天它依然存在,可见生命力相当之强。MVC模式最早应用于Smalltalk语言中,最后在其它许多开发语言中都得到了很好的应用。随着包括Struts、Spring MVC、SpringBoot在内的MVC框架的出现,MVC模式真正落地并得到极大进展,MVC模式使得开发更加高效、代码耦合度尽量减小、应用程序各部分的职责更加清晰。

    在MVC模型中,其中模型是用于封装数据的载体。例如,在Java中一般通过一个简单的POJO(Plain Ordinary Java Object)来表示,其本质是一个普通的java Bean,包含一系列的成员变量及其getter/setter方法。对于视图而言,它更加偏重于展现,也就是说,视图决定了界面到底展示成什么样子。在Java中可通过JSP来充当视图,或者通过纯HTML的方式进行展现,而后者才是目前的主流。模型和视图需要通过控制器来进行粘合,例如,用户发送一个HTTP请求,此时该请求首先会进入控制器,然后控制器去获取数据并将其封装为模型,最后将模型传递到视图中进行展现。综上所述,MVC的交互过程如下图3-1-1所示:

图 3-1-1

         MVC模式尽管很强大,但是仍然有以下三点不足:

         1、每次请求必须经过“控制器->模型->视图”这个流程,用户才能看到最终的展现的界面,这个过程似乎有些复杂;

         2、实际上视图是依赖于模型的,换句话说,如果没有模型,视图也无法呈现出最终的效果,解耦不够彻底;

         3、渲染视图的过程是在服务端来完成的,最终呈现给浏览器的是带有模型的视图页面,性能无法得到很好的保证。

2、Ajax技术

         既然MVC模式并不完善,那就推动了人们的研究和改进,随着历史的发展和技术的改进,2004 年 Gmail 像风一样的女子来到人间,很快 2005 年 Ajax 正式提出,加上 CDN 开始大量用于静态资源存储,于是出现了JavaScript王者归来的SPA(Single Page Application 单页面应用)时代。

Ajax的出现,使得数据的展现过程更加直接,并且提供了更好的用户体验。在这种模式下,前后端的分工也逐渐清晰,前后端的关键协作点是 Ajax 接口。引入Ajxa后,MVC模式就变成了用户从浏览器发送AJAX请求,然后服务端接受该请求并返回JSON数据返回给浏览器,最后在浏览器中进行界面渲染。改进后的MVC模式如下图3-2-1所示:

图 3-2-1

         根据这种模式,也就是说我们输入的是AJAX请求,输出的是JSON数据。如果将浏览器这一端视为前端,而服务器那一端视为后端的话,可以将以上改进后的MVC模式简化为以下模式,如下图3-2-2所示:

图 3-2-2

    通过这种简化后我们可以明显的看出前后端分离的雏形。但是我们这样简化是否可行?如果这样简化是否有相应的技术进行支撑?幸运的是,历史给出了一个完美的答案:REST。

3、REST架构

         REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。Fielding是一个非常重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。所以,他的这篇论文一经发表,就引起了关注,并且立即对互联网开发产生了深远的影响。他这样介绍论文的写作目的:

“本文研究计算机科学两大前沿—-软件和网络—-的交叉点。长期以来,软件研究主要关注软件设计的分类、设计方法的演化,很少客观地评估不同的设计选择对系统行为的影响。而相反地,网络研究主要关注系统之间通信行为的细节、如何改进特定通信机制的表现,常常忽视了一个事实,那就是改变应用程序的互动风格比改变互动协议,对整体表现有更大的影响。我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。”

    Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。即如果一个架构符合REST原则,就称它为RESTful架构。

REST本质上是使用URL来访问资源的一种方式。REST中指出的“表现层”就是“资源”。所谓“资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源标识符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。

网络上的“资源”是一种信息实体,它可以有多种外在表现形式。如文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。

         当客户访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。这四种类型,正好与CRUD(Create-Retrieve-Update-Delete,增删改查)四种操作相对应,这正是REST与CRUD的异曲同工之妙!

    有了Fielding博士提出的REST框架体系的支撑,那么我们将MVC模型简化为前后端分离就有了理论依据。采用REST分格的架构可以使得前端关注界面展现,后端关注业务逻辑,分工明确,职责清晰。那么,如何使用REST架构将应用程序进行前后端分离呢?

4、前后端分离技术体系

    有了REST基础理论,这极大促进了前后端分离各种技术的发展。为了更好的处理传输数据,为了给用户提供更好的使用体验。前后端分离出现了以REST+Json为架构风格的大方向。其实现思想如下图3-4-1所示:

图 3-4-1

    为了实现理想的前后端分离模式,目前总体来讲需要依据四大原则:

    1、前端静态化。前端有且仅有静态内容,再明确些,只有HTML/CSS/JS。其内容来自于完全静态的资源而不需要任何后台技术进行动态化组装。前端内容的运行环境和引擎完全基于浏览器本身。

    2、后端数据化。后端可以用任何语言,技术和平台实现,但它们必须遵循一个原则:只提供数据信息,不提供任何影响界面表现有关的内容。换言之,他们提供的数据信息可以用于任何其他客户端(如移动端程序、公众号、PC等)。

    3、平台无关化。前端3大技术本身就是平台无关的,而后台部分的本质是实现合适的RESTful接口和交互Json数据,就这两者而言,任何技术和平台都可以实现。

    4、前后端架构分离。前端架构完全基于HTML/CSS的发展和JS框架的演变,与我们耳熟能详的后台语言(如Java,C++等)完全无关。

由于前台是纯静态内容,大型构架方面可以考虑向CDN方向发展。后端构架几乎可以基于任何语言和平台来实现。大型构架方面, RESTful Api可以考虑负载均衡。而数据,业务实现等可以考虑数据库优化和分布式,也能更加符合无状态的微服务的要求。

    遵循这四大原则,可以更好的实现前后端分离。根据四大原则和REST+json的规则,一个项目的技术架构图应该是如下图3-4-2所示:

图3-4-2

    根据架构图说明如下:

1、前端请求(可以是pc端,app,小程序,公众号)到node前端服务器,然后通过nginx转发进入 controller层,该层对外提供restful接口。

2、然后将业务的处理发往service层。

3、service层再对数据进行落地处理。

在实际项目中,技术框架应该不会有很大偏差。根据项目场景和硬件条件,允许适当取舍和变化。

    在以上架构中,前端一般可以使用vue等技术实现页面交互逻辑,使用ajax与node服务器交互,一般的node服务的请求通过nginx转发至后台服务器,后台服务器只提供RESTful接口。Redis的使用可以是管理session,同时redis的作用还包括用户基础数据缓存,数据信息缓存等,这些都可以大大减轻数据库的访问压力,从而可以提升整个服务的响应速度和用户体验。

除此之外,为了适应企业日益增长的数据业务,往往后期会采用分布式部署,而采用redis,前后端分离模式也可以很轻松的平滑到分布式。为了解决数据量的级数增长,进行分布式部署,基本上是对前后端分离架构的横向扩展。一个简单的分布式网络架构如图3-4-3所示:

图 3-4-3

    图中的web层即对应着Controller,service层和数据库,中间使用了目前比较流行的Kafka,在分布式架构中解决分布式中数据一致性等问题。

    当然,实际中分布式往往是比较复杂的,还包括服务注册与调用,分布式事务幂等性,请求链路追踪,消息总线等。

四、接口安全技术

    在前后端分离模式中,由于前后端服务分开,结构分开,实现了高度的松耦合。那么接口(API)就成了联系前后端的关键桥梁,前端和后端变成了非必要绑定,两者可以自由组合实现任何复杂的业务。凡是使用了前后端分离模式的项目,理论上来说,都可以自由的组合,这也为系统间不同业务,不同数据的打通提供了便利和方向。传统的系统间接口交互将会在前后端分离模式下变得如此简单。

    无论传统的MVC架构的开发模式,还是前后端分离模式,业务接口往往都是天然暴漏的。这就导致了接口的安全性问题。在传统的MVC模式下,由于前后端高度耦合,接口的暴漏性可能往往得不到开发者的重视,而忽略了对接口安全性的设计。目前流行的前后端分离模式,首当其冲的就是接口的安全性。由于前后端的剥离,接口成了唯一的交互渠道,所以在前后端分离模式之初,最紧迫的任务就是解决接口的安全性。

    当然,现在有成熟的关于前后端分离接口安全性的设计方案,这也促进了前后端分离的发展趋势,使得越来越多的公司和个人选择该模式。那么,我们有哪些方法来保证接口数据的安全性呢?

    1、通信使用https。

    2、请求签名,防止参数被篡改。

    3、身份确认机制,每次请求都要验证是否合法。

    4、对所有请求和响应都进行加解密操作。

    5、APP中使用ssl pinning防止抓包操作。

    6、其他安全设计方案。

    很显然,方案有很多种,当项目中做的越多,也意味着安全性也更高。如果在数据的传输中加密,前端需要做两件事:

    1、统一处理数据的响应,在渲染到页面之前进行解密操作。

    2、当有POST请求的数据发出时,统一加密。

    前端加密可以一定层度提高接口的安全性,但是前端服务的不安全性,不可靠性可能会导致加密的key泄露。而服务端的安全性,可靠性较高。为了提高安全性,那就只能借助后端提供一种动态的加密key的方式。加密算法有对称加密和非对称加密,AES是对称加密,RSA是非对称加密。之所以用AES加密数据是因为效率高,RSA运行速度慢,可以用于签名操作。我们可以用这两种算法互补,来保证安全性,用RSA来加密传输AES的秘钥,用AES来加密数据,两者相互结合,优势互补。

    1、客户端启动,发送请求到服务端,服务端用RSA算法生成一对公钥和私钥,我们简称为pubkey1,prikey1,将公钥pubkey1返回给客户端。

    2、客户端拿到服务端返回的公钥pubkey1后,自己用RSA算法生成一对公钥和私钥,我们简称为pubkey2,prikey2,并将公钥pubkey2通过公钥pubkey1加密,加密之后传输给服务端。

    3、此时服务端收到客户端传输的密文,用私钥prikey1进行解密,因为数据是用公钥pubkey1加密的,通过解密就可以得到客户端生成的公钥pubkey2。

    4、然后后端生成对称加密,也就是我们的AES,相对于我们配置中的那个16位长度的加密key,生成了这个key之后就用公钥pubkey2进行加密,返回给客户端,因为只有客户端有pubkey2对应的私钥prikey2,只有客户端才能解密,客户端得到数据之后,用prikey2进行解密操作,得到AES的加密key,最后就用加密key进行数据传输的加密,至此整个流程结束。

   

五、总结

    前后端分离模式正成为越来越多公司的选择,在项目开发中前后端开发人员可以独立开发、独立运行、独立调试,他们之间桥梁就是API接口。通常,一个页面的加载或者表单的提交,都有数据在客户端和服务器端之间传输,而swagger技术可以让后台开发人员在写接口的同时自动生成API接口页面。有了API接口页面,前端开发人员就可以基于API页面的模型完成页面样式和页面交互。而后台开发人员如果修改了接口,也能及时的反映到前端,避免了沟通不及时导致的接口问题。正是基于node前端服务器,nginx负载均衡,springboot快速敏捷开发架构,swagger等api文档自动生成技术的出现,前后端分离也具有了很好的落地性。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值