一场由React引发的前后端分离架构的思考

4,238 阅读7分钟


内容来源:2017年7月22日,浪潮国际金融产品技术架构师丁周芳在“【济南】OSC源创会第65期”进行《一场由React引发的前后端分离架构的思考与实践》演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。

阅读字数:2715 | 7分钟阅读

嘉宾演讲视频及PPT回顾:suo.im/2A3F57

摘要

以React技术栈为主分享我们在大规模企业应用建设过程中遇到的问题,对前后端分离架构的思考,前后端分离的技术方案,前后端分离过程中的实践经验,前后端分离带来的效果与价值,以及目前存在的问题与未来可能的尝试。

应用的现状

我们的应用拥有接近100w的用户、3K+的QPS、5亿+的单表数据、万亿级别的资金流,但是同样也面临着诸多问题。

首先是颜值低,换肤受限、无法集成更好的前端框架和组件。然后是前后端的高度耦合使得无法快速的响应业务变化,维护成本也随着应用规模不断攀升,性能方面也受到限制,沟通成本提高。其次是无法跨终端,渲染和跳转强依赖于后端,业务逻辑分散。最后就是强状态性,应用中很多的数据是与用户的会话绑死的,由此造成没有水平伸缩的能力,智能化、自动化、服务化同样受限。

我们经过思考认为理想的状态应该是这样的,前端方面具备高颜值、个性化、多渠道、多终端的特质;而在后端上需要能做到微服务化、水平伸缩、高可用、自动化甚至智能化。

解决方案-前后端分离

定义

在之前的应用中后端是Java,前端是Browser(浏览器)。但是现在Node出现了,它被包含在大前端中用来替换原来的MVC部分,这样后端就可以脱离出来处理纯服务化的部分,前端也可以专注于纯前台的领域。

各自的职责

前端方面Browser负责数据的展现和收集、事件的响应和处理、DOM的操作、请求的发送和响应的处理。Node用来处理之前通过后端来实现的页面渲染、跳转和数据的传递等功能。而后端方面则专注于业务逻辑的封装、服务接口的提供以及序列化。

总体的方案

从总体上来看前端和后端基于服务化的方式进行交互,通过Json进行数据传递。前端做到组件化、后端实现模块化。

前端的选择

在尝试了很多方案后,我们选择了React+Redux,因为在React上有一定技术积累,同时国内也有很多的成功案例。但是由于Redux太灵活了,在接触了三周后我们选择了放弃,转而使用蚂蚁金服开源的基于React的一款展示框架AntD和基于Redux封装的Dva框架。

前端的技术架构

当有一个请求过来后,会通过Component或Route来展示界面。同时也会接收用户的点击事件,每一个点击事件都会由dispath来触发一个Action,这之后会产生两种结果。

一种是直接通过reducers函数改变状态state,使与前台关联的model发生变化,由此来改变前台页面。另一种是调用后台的服务,通过fetch进行后端服务的访问,后台服务返回的数据会由effects函数处理,处理后会交给reducers函数去改变状态state,进而触发前端的组件刷新和渲染。

最后还有一个subscriptions函数是进行前端拦截的,当拦截到一个URL请求之后仍然是触发一个Action,然后又会导致上面的两种变更。

后台的技术架构

后台的逻辑就相对复杂了,我们采用了分层的技术架构。最底层是基础设施,支持公有云、私有云当然还有本地服务器。然后技术平台层就是一般常见的架构,囊括一些系统权限、工作流、开发框架之类的。基于之上的是通用的服务层,里面有一些报表服务、打印服务,单据服务等。再向上就是业务模块的部分,包含账户管理、任务管理、自助中心等。最后顶层的就是接口服务层了,它是基于Web Service和Restful Service的。

除了上面的主体框架外,我们还有服务网关模块,主要是用来做流量控制、安全监控、负载均衡、服务降级与熔断等。另外就是安全运维模块,用来处理身份认证、访问控制、加密解密,审计日志,运维工具等等。

实践经验

前后台交互

目前绝大部分业务表单数据与后台的交互都是使用Fetch方式。另外由于一些遗留系统的问题仍然保留着AJAX方式,并对他进行了一些改进。而文件类的操作比如上传、下载,这些目前使用的是Form提交的方式。

跨域

我们原来是通过Jsonp来解决的,但是Jsonp的问题是只能支持get请求,参数会被暴露出去。出于安全性的考虑我们选择了目前主流的CORS方式,只在服务端处理跨域不涉及到客户端。

应有无状态

应用的强状态性是由于过度依赖会话造成的。会话的原理其实就是在Session中存储了一些数据,此时Session被当做缓存来使用;还有一个重要的职责是维护与客户端的联系,让后端可以判断是哪个客户端发送的请求。而现在我们采用Token来识别客户端,缓存的职责使用分布式cache来代替。

页面的跳转和参数传递

原先被放在后端通过forward或redirect的跳转、参数传递,现在被前端的Router代替,数据传递通过PayLoad进行。而如果需要依赖后端的一个状态才能进行跳转,那么只需要从后台获取一个消息,前端会根据这个消息来判断跳转的走向即可。

错误处理

我们的经验是后端统一异常错误捕获,然后进行分类,通过异常错误信息字典来统一向前台反馈错误信息。前台从后台得到错误的信息后,以此进行前端界面的提示和跳转到错误页面。

安全

通过Token来进行身份的验证,另外为防止Token一直有效,当前台主动登出时会注销Token;同时后台也会根据配置的回话过期时间来自动注销不活动的回话。消息的加解密,系统的访问控制,包括系统功能权限与数据权限也会有专门的服务。

质量的保证

原来的统一测试被分开了,前后端先分别独立mock数据进行单元测试,然后是联调测试,联调测试完后再根据测试用例进行冒烟测试。冒烟测试完成后开发人员的测试算是完了,后续就交由专业的测试人员来进行集成测试,UAT测试。

前后端分离的价值

敏捷、快速响应、提升效率,专业化的分工和协作、提升专业度和研发效率,结构清晰,降低维护成本,前后端各自独立扩展、自由水平伸缩。

未来可期

现在我们需要考虑下之后还有那些需要加强的地方,比如说服务网关、安全与运维特性的增强,公共组件的进一步提炼与封装,性能与体验的提升,框架开源等等。

今天的分享就到这里,谢谢大家!