再来讨论前后端分离的实践。

2014-11-25 11:17:21 +08:00
 thonatos
看过了“淘宝前后端分离实践”后,考虑在公司内部进行试验,更多的还是借鉴。

前后端分离的实现在SPA(Single-Page App)中应用较为广泛,如AngularJS,React 使用Ajax技术与后端通过RESTFul方式进行数据的请求与发送,

如我们的数据统计就是通过ng(AngularJS)的SPA项目,但它并不适用于我们主要项目(如SEO体验较差)。

考虑到之前曾讨论的未来可能会换到JAVA的后端服务的可能性,重新看了一遍淘宝UED的”淘宝前后端分离的思考与实践“的文章,下面两张图是我对他们结构的理解。

一)结构

1.经典的结构


2.前后端分离的结构


二)优势

1.后端实现业务逻辑和数据的查询计算,独立部署后端服务。(例如后端服务部署在8080端口)

2.前端路由,MVC,实现相对于后端的独立,自主控制视图层。(同样实现独立部署如部署在80端口)
# 这里的Model如上图所示,是与8080端口的后端进行交互

3.通过Server(Nginx模块)判断客户端请求类型,自助引导至不同的模块,仅需要一次判断,后续无需重复判断。

4.前端通过步骤3的预处理,可以在页面渲染前对例如css/images/js资源进行压缩处理,如置换渲染所需资源到所需的CDN(如icon/icon-mobile/icon@1x/icon@2x)

5.传统的SPA通常由于资源的处理时间问题(网络环境影响),在完成前可能出现”空白页“(等待阶段),这里可以参考BigPipe方式,持续输出。
# 虽然可以通过一些手段实现渲染完成前的一些预处理,但采用这里说到的方法,实现上更加优雅。

6.相对于传统,这样的分离更加明确各自的职责,后端职责更加明确,前端自由度更高,耦合度却有所降低。

三)疑问

看到知乎上关于这个问题的讨论,大体上阿里系的后端意见都挺大的样子,于此同时,很多人也在说增加了前后端的压力,尤其是要发展出一批nodejs工程师神马的;不过中肯的看法是要根据具体的情况来定,个人感觉在小型系统上,这样的模式是有优势的,实践起来也不是很困难,尤其是对内部的系统而言,问题不大,但是想到未来可能会放到对外的项目上,就产生很多疑问了,各位怎么看?


——————————(我是牛逼的分割线。)
参考:淘宝UED
地址: http://2014.jsconf.cn/slides/herman-taobaoweb/index.html#/
23905 次点击
所在节点    程序员
85 条回复
ZackYang
2014-11-25 18:19:08 +08:00
@thonatos 服务端客户端在不在一个网络完全没影响, 最佳实践应该是把客户端放CDN.
ZackYang
2014-11-25 18:20:22 +08:00
@thonatos 进入白屏的问题, 完全可以使用AMD解决, 按module加载, 不需要一开始加载所有的js.
thonatos
2014-11-25 19:07:31 +08:00
@boom11235

非常赞同你的看法,职责的分离以及前端自由度的提升是试验的动力之一(二),同时我也不认为让前端熟悉一部分后端的内容是压力,相反,更该是能力的提升,所谓全栈的说法不是很认同,做前端,又同时能对其他内容有所涉猎的能更好的发挥自己的价值,仅仅做demo,很好,但不是最好。
thonatos
2014-11-25 19:13:07 +08:00
@ZackYang

进入白屏这个问题,是我太偏激(见谅),这个,准确来说,应该是无解的……(试着将网速限制到足够低,必然还是会出现),即使采用Bigpipe的方式,也依然是不能解决的,这个话题略过吧,sorry
lygmqkl
2014-11-25 19:19:57 +08:00
@thonatos 不知道你说的通讯效率是什么? 我用的是php脚本来搭建后台,一次请求包含所有的信息,对应服务器返回需要的json 数据,不觉得效率上会有什么问题啊

PS: 服务器组成是 6台 web + 2 db
thonatos
2014-11-25 19:28:14 +08:00
@lygmqkl

我是指通过中间间(如nodejs)与后端逻辑服务器交互,对比直接传统的架构,总体的效率如何,指:耗时,稳定性(是否丢包等)。
lygmqkl
2014-11-25 20:07:15 +08:00
@thonatos 耗时 如果条件相同的情况下,应该是不相上下,甚至可能会多损耗5%在传输上,因为对比传统的session结构,request header里要包含的东西显然多了很多,但是这个损耗还回来的是,你可以同时有10台web服务器响应,100个用户的请求,每台服务器处理10个,而且随机选择服务器就可以,因为每一台服务器对相同的request header 返回是一样的。

稳定性应该是提升了的,当然是在请求量巨大的场景下。

请特别注意,在RESTful架构下,缓存更多的是做在客户端,即js代码里,一旦缓存了,请求都不会发送,只要设计的足够好,还是很强悍的。
otakustay
2014-11-25 20:54:44 +08:00
1. 阿里的前后端分离有它特殊的时代背景,比如前端想要的接口和后端想提供的对不上之类的
2. 你的第2张图里的后端是啥语言,如果不是NodeJS的话,左边那个NodeJS也没必要吧,和后端语言保持一致不是挺好的吗?这个NodeJS放在这的意义是啥
3. NodeJS不能算在前端里吧,这里的分界线很不明确?
hitsmaxft
2014-11-25 21:04:17 +08:00
前后端分离的最大驱动力是团队拆分.. 这不是笑话. 业务团队和ued团队不在一个队伍里, 带来的协作问题不是一点两点能讲完的..

前后端分离倒不是最核心的目的, 而是要分清楚 模型, 业务, 和模板的开发归属. 真正原因, 是在现有的协作分工模式下, 最大限度地解放生产力...
crossmaya
2014-11-25 21:16:38 +08:00
我不知道你这个php和java在这里做什么用,分离不就是统一业务系统吗,后端nginx已经把事情做完了,你这php和java在这里的意思是提供动态内容输出?还是只作为一个入口。。
thonatos
2014-11-25 21:23:55 +08:00
@lygmqkl

嗯嗯,知道了,谢谢,回头我实际试验一下,看看效果。
thonatos
2014-11-25 21:45:27 +08:00
@otakustay

1.应用分具体场景而定,阿里的模式也不全是因为“对不上”吧
2.这里主张的前后端分离,换言之是重新定义了前后端的范畴,和传统的前端定义有区别,显然也就需要其他来做后端了,语言一致只是相对而言,并非全部一致,比如多台服务器的时候,你也许能理解这样的好处。
3.仔细看图2,你应该大体能理解这里——前后端的概念。

@crossmaya
你不知道的原因在于你对这里所说的前后端理解上的偏差,前端不只是页面(css/html/js),前端应该是与用户交互的部分,换言之,ios/android的客户端(app),也可以理解为前端;后端是指逻辑和业务系统,比如说进行数据运算,比如说是持续的数据处理什么的。

仔细看图,应该能明白我这里的java和php只是泛指,也可以是c,也可以是go,或者python等等,他是指的整个项目的一个部分,显然动态内容的输出了,内容的输出交给nodejs来做的,可以是静态,也可以是动态,甚至说,可以是cdn。
thonatos
2014-11-25 21:53:43 +08:00
@hitsmaxft

嗯,团队合作的时候,分离的确很便利,比如说我当前的开发往往需要后端支持:

我们后端使用了redis,而我本地是不具有redis的,另外一些具体的配置,也不可能完全复制到本地,每次测试,往往需要我push,后端pull,测试反馈bug,重复上述步骤,很麻烦。

如果分离了,那么我负责页面(包含controller,view),model那边利用接口,可以轻松的实现现有的模式,只要后端保证model层的稳定即可,当然了,有人可能会说我们可以修改现在的模式,让我本地可以访问redis之类的,但那终归不是最好的解决方法,对吧?

扩展下,我的本地环境,其实就是充当了负载均衡控制的web服务器之一(web服务器是多台,例如5),同时业务服务器有2台,那么,web是独立的,他可以自主部署自主测试,业务那么不需要重复做”无用功“了。

这样才是真正的解放生产力么(⊙_⊙)?,前端学点简单的VC算什么难度~~~~对吧~
maxiujun
2014-11-25 22:09:41 +08:00
我在一家专门提供外汇交易平台解决方案的公司,最近一年都在用ember.js做类似的工作,效果不错,我觉得对于页面上复杂逻辑的实现,ember,angular 帮助非常大。同时后台用spring mvc 的rest借口也同样有我一个人完成,这样就可以平衡前和后端了。
thonatos
2014-11-25 22:14:50 +08:00
@maxiujun

嗯嗯,一个人做的话...确实是完全自主发挥了,我的主管大人直接发话了:
“统计哪里,就当你的试验田,随便你怎么搞~”

这样的分离也没有要完全放弃ember,angular的说法了,主要是如我附言那边写到的原因喽~
maxiujun
2014-11-25 22:23:49 +08:00
其实关键的问题就是前端和后端的界限在哪里,我们这的界限就在java的接口上,所以我们这么做也就好理解了。
另外,做了这么多实践,感觉,只要把前端的工具链(Grunt,bower 等)弄熟练,主题里面提到的“分离”就水到渠成了。
thonatos
2014-11-25 22:30:30 +08:00
@maxiujun

讨论再多,也只是为了提高生产力嘛~
最后做的东西即使一样多,但是中间环节的减少,在团队协作中,确实是巨大的提升。

(对于个人开发者来说...基本可以认为是一样的,至少过去我做东西,从来都不会考虑这个.)

前端和后端的界限,我认为是职能,或者说职责,减少无用功,这样定下的界限,更好一些。
exodia
2014-11-25 23:24:58 +08:00
好无聊,过来练习下写作和表达能力。

首先,我觉得不要扯性能方面的问题,性能对于绝大多数非首页场景都不会是瓶颈。真要追求极致性能,就像淘宝首页一样,写成静态 html好了。


解决前后端分离的问题,目前大概有以下几种方案:

1. 前端写后端模板

1)前端和后端的模板是不一致的,比如前端可能用 Hanldebars,后端 java 经常用velocity,php 用 smarty,都由前端一起维护。比较恶心的问题在于,公司大了,部门多了,业务线多起来了,可能技术选型都不一样,比如有的业务线用 php,有的用 java,还有的用 python,他们的模板引擎可能都不一致,一是碎片语言实在太多了,更严重的是阻碍组件的复用,比如淘宝的通用吊顶和吊尾以及登录框是可以全站复用的,但之前用 java 写的,如果有的业务线用 php 咋办?于是他们对这些组件进行前端组件的静态化处理,即这些组件变成了 html+css+js的片段给其他业务线去用,数据请求通过 ajax 去做;但这些组件的一个特点是,依赖后端的动态数据较少,比如吊顶只是简单的一个登录信息请求即可,不适合需要大规模的后端查询页面。

因为1)的问题,于是有了下面的 2)

2.1) 前后端统一模板,模板语言嘛,用不同的语言都写个引擎就好了嘛,比如后端 nodejs 用 jade,咱前端也用 jade,嫌慢,咱先编译好。这个我还没找到比较大型的案例,我自己做着玩玩的时候用过。

2.2)有人觉得每个语言都要为一个模板语法写一个引擎,维护成本也大,模板语法一更新,所有引擎都要更新,真是去你大爷的- -! 于是呢,linkedin的做法是前后端统一模板为dust(你猜对了,js的模板引擎), 后端在渲染模板的阶段,起个线程跑v8引擎,去做模板渲染。于是成功解决了web组件(前后端都有)复用的问题。


1方案的普及需要有好用的工具提供给前端做开发调试mock等,比如淘宝曾经出了个 vmarket,据说难用所以没然后了。然后,fis 也有针对这个专门做了工具,具体去 fis 主页看好了,最近我在试用他的 java 解决方案,感觉还是比较容易上手的。

2. 前端 mvc(webapp)

感觉不用太多介绍吧,这几年比较火的架构,模板在浏览器渲染(尼玛,你说后端返回渲染好的 html 字符串,艹,这还能叫前后端分离- -!!!!)。

很多人这个方案问题在于seo 和性能。就 seo 来说不是太大问题,比如我从组里同学那获知的用个 phantomjs 渲染出页面丢给 robot 就好了,以及 google 是有针对 ajax 页面做索引的。

再说说性能,linkein 不用前端 mvc 的一个很重要原因就是性能,不过人家是因为页面要兼容到 ie7,ie7没有原生的 JSON 提供,解析起来确实是巨慢无比,所以放弃了。我觉得吧,如果你的项目仅需要支持ie9+等现代浏览器,基本可以考虑采用这个方案试试,当然 seo 这块我也没涉及到,不好扯淡,有朋友去试了可以教教我~


2方案对前端的要求会比1更高些,大规模项目的路由设置,模块切分,mvc 的职责,代码规范,目录结构的组织,都需要有一定功底,否则会玩脱。

这个玩法比较多,框架也很多,angularjs,ext,然后是我们这的一系列组合: https://github.com/ecomfe/er
https://github.com/ecomfe/esui
https://github.com/ecomfe/oo
https://github.com/ecomfe/uioc

打广告就是爽,呵呵呵呵。


3. 加一层中间层

比较火的,淘宝中途岛,比较低调的, fis 的 yogurt。 线上案例,百度音乐移动版,淘宝的对外项目不是太清楚,麻烦知道的同学告知下,内部项目主要是之前的数据平台部门的一些产品:在云端等。

我曾经是这个方案的拥护者,在经历了北京velocity大会的 fis 和淘宝的前后端分离实践分享,前不久d2的支付宝前后端分离实践分享,以及最近自己在搞一个业务线前后端分离的实践后,我现在成为这个方案的反对者。至少我觉得这个方案不适合大多数场景。

我们看看这个方案想要解决的问题:

1) 前端依赖服务端开发环境
2)在服务端View层高度耦合
3)沟通成本高
4)职责不清晰

对于1),可以通过开发优秀的工具去解决,至少 fis 的 jello 还不错。
对于2),不明白这耦合在哪里?
对于3),阿里的场景是前端写html Demo,再丢给后端套,敢问有几个公司这样做?
对于4),我觉得和2)一样,说的太虚了。你要说职责清晰,学学腾讯把 html css 也分出去得了
- -。。


关于 ppt 中说前端 mvc的问题,限于篇幅和精力,我懒得吐槽- -!,@otakustay 可以来试试- -!

再看看这个方案会遇到的问题:

1)学习成本实质是最高的。

天真的以为仅仅是语言没有学习成本? 后端的各种技术,安全,日志,监控,并发,事务,分布式 session,数据库读写分离,确定一般的前端能搞定?阿里经历了多少年,java 发展了多少年才成就了现有这么成熟的体系。 bat 或许能用 nodejs 去玩玩,因为技术的服务化和平台化比较成熟,都会提供服务化的api来用, 比如分布式的 session 访问,你只需要去调接口,不用自己去用 nodejs 实现一套了,再说用户信息,订单信息也是提供接口给你,至于他们怎么做性能调优,安全处理,数据库设计你都不用管。 但是一般的公司能做到这么高度的服务化么?

2)现阶段绝大多数前端水平还跟不上

即便很多前端号称自己会 node,也只是停留在写工具层面。

在 velocity 上,淘宝的分享者(p7)说,他们请了后端的同学帮他们实现 nodejs 的 session 读取框架,我就跪了好嘛,整个淘宝 ued 都找不出一个前端能写这个,你确定有几个前端有这个技术能力去 hold 这种技术?
在阿里也就那些数据平台部的人在这方面比较牛逼了,但是别人一直都是以后端为主,前端为顺手写,起点和一般前端完全不同,现在最多就是挂个前端的 title 在上面。

3)想要解决的问题都可以有更快捷简单的方式去解决

对大多数场景来说,我更推荐1的解决方案,简单快捷,没有太多成本。比较成熟的公司想要做组件化的复用可以参考 linkedin 的方案。 中间层可能只是一个舍近求远的方案。


最后,中间层这个方案给我感觉最多会成为一个,由 nodejs 渲染的模板引擎方案。

当然,我个人倒是蛮希望这个方案能够将前端的总体水平提高一个档次,能够将前端工程师变为工程师。
HaEx
2014-11-26 00:20:24 +08:00
@exodia 就事实而言,最后的描述的三个问题中,有一个里面没一句话是对的,当然我也不知道您是从哪里打听到的;至于其它的,就不吐槽了...
exodia
2014-11-26 00:29:19 +08:00
@HaEx 我比较喜欢直接吐槽,这样我可以认识到我的问题,至于你说最后的三个问题,有一个不对,那么我猜你说的是第二个,这个我没有打听,因为这个是我在 velocity 上直接问的清羽,是他说的,至于他说的是不是事实,我只是转发。 数据平台部门在 node 牛逼,这句话我确信没啥问题,当然,可能现在没这个部门了就是,呵呵

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/149090

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX