前端实战 | 基于京东架构的前端部署方案

点击「京东金融技术说」可快速关注

「摘要」从实践出发,探索前端部署方案。记录思考和尝试的全过程,为京东技术体系下的前端部署增加一个方向。踩着前辈走过的路,勇敢往前再走一步。

始于阿瑞斯

17年11月中旬接到任务,需要做一个红包系统,承接所有财富的红包发放需求。我将之命名为阿瑞斯(Asset Red Envelope System)。因项目的界面交互较复杂,而时间又紧张,如果使用传统的web技术jsp+jquery的方式开发,需要大量的javascript代码来搞定交互和数据校验等问题,开发进度很难赶得上;同时也希望借机提升前端的技术架构。所以,最终决定,前后端分离,且使用vue + vue-router + vuex来做前端的开发。

项目如期开发完成,但在这时遇到一个问题:如何部署?虽然之前有预案,但在实际操作中还是遇到很多问题,期间不得不更换方案,以适应京东大架构下的CD(持续部署)方案。在成功上线后回头来看,发现这一路踩了不少坑,所以想将这些心得写下来分享给后来者,希望能有所借鉴。

架构&跨域

系统架构在前后端分离后,前端成为独立的项目,独立开发,独立部署。通过ajax调用后端接口来获取数据。简易架构示意图:

 

这是个典型的前后端分离的架构。如图中所示,前后端服务是分别部署的,域名不一样。前后端数据交互是靠ajax进行交互。ajax运行在浏览器,而根据浏览器的同源策略,ajax不允许跨域访问,也就是说上图的ajax是会被浏览器阻止的,无法实现调用,这时就必须跨域。浏览器同源策略:

要解决ajax跨域问题,有5种方式,如下:

一、Jsonp

  • 原理:利用<script>标签的一个hack,浏览器允许<script>标签加载不同源的javascript。服务端配合返回类似callback({}) 这样的数据,页面拿到数据后会将数据做为javascript执行,调用页面实现的callback()方法。

  • 优点:这种方式实现简单,前后端改动都不大,是一种可取的方式。

  • 缺点:jsonp只能使用get不能使用post,这是它的原理所决定的。

二、Cros

  • 原理:cros是一个W3C标准,即跨域资源共享(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

  • 优点:支持所有类型的http请求。

  • 缺点:实现比较复杂,需要区分简单请求和非简单请求,使用不同的http head;需要服务端支持cros。

三、Websocket

  • 原理:websocket是html5中的一种持久化通信协议。本身就没有跨域的限制。

  • 优点:通信几乎没有什么限制,而且速度很快。

  • 缺点:需要在支持的浏览器下运行;需要单独实现基于websock的通信,实现会比较复杂,需要考虑多窗口、状态等等问题。一般的简单数据交互场景并不是特别适合websocket。

四、Flash

  • 原理:flash通过远程沙箱可以加载远程文件,flash会根据远程服务器的资源策略文件crossdomain.xml的配置来读取跨域的资源。

  • 优点:没有请求限制。

  • 缺点:实现复杂;需要服务端配合;有安全性问题;flash已经快要被淘汰,很多浏览器已经不支持,特别是移动端。

五、服务器Proxy

  • 原理:跨域是浏览器的限制,服务器间的请求并没有跨域问题。页面请求同源服务器,同源服务器将请求代理到非同源服务器。

  • 优点:由于请求是后端处理的,前端不再需要关心跨域问题。不需要改任何代码,没有任何限制。

  • 缺点:需要做个代理服务器。

整理思路后,实现的方案如下:

预想中的理想部署方案

中间层的proxy如何实现呢?它需要有:可以做http容器、可以和后端做服务器间的调用,要满足这两个特性,我们最熟悉的非node莫属了。而且在前后端分离的情况下,中间加一个node层能解决很多其他问题:比如纯前端渲染不利于seo的问题、前端router的短板、安全性、前端限流等。

因此最理想的方案就是:实现基于node 的 CI、CD(持续部署),实现代码下载、编译、打包、发布、启动node服务、服务监控,全流程的一键化。但是京东部署平台目前还尚未支持node,怎么办呢?后来发现部署平台支持发布静态文件,node不支持,可以曲线救国呀。

京东部署平台的static服务应该是这样的:利用nginx作为http容器将静态的页面发布成http服务。nginx除了作为http容器,还有其他功能,比如反向代理。Nginx可以在config文件中配置proxy_pass,并请求反向代理。利用nginx的这一特性,将环境稍作修改,就完全解决了上面问题。

测试环境的尝试


接下来以测试环境(使用jekins做的CI)作为练手,进行了搭建。虽然jekins支撑nodeJs的插件,能将nodeJs直接集成进来,实现一键部署,但是出于生产环境的考虑,这里就没有考虑这种方式。

申请了测试环境权限,登录到了测试环境的服务器。先修改nginx的配置文件,将nginx作为http的服务器,同时配置proxy_pass实现反向代理,将ajax请求代理到后端服务器。过程如下:

之所以创建vhost目录并且创建a.com.conf配置文件,是因为考虑到可能会有一台服务器部署多个前端项目,有多个域名的问题,便于管理。当然也可以直接修改conf/nginx.conf文件,在文件最后添加server。a.com.conf里写入如下配置:

保存后退出。再到nginx/config/下找到nginx.conf 进行编辑:

注释掉默认的server,将刚才创建的vhost目录下的所有配置include进来。很简单,nginx的配置就完成了,再接下来就是将静态文件上传到git了:

执行npm 命令,生成生产文件,再修改vue-cli 默认的.gitignore 文件,将其中的dist删掉:

将代码上传到git,这时dist也会被上传。

最后,在jenkins上新建一个项目,并对其进行配置,只需要两步:从git下载代码到jenkins服务器;并将dist目录剥离出来,上传到前端应用服务器。Jenkins配置如下:

Application-worker


改造完成后,试验环境完美通过,如果按照正常的剧情发展,故事到这里就结束了,接下来就是照猫画虎搬到生产环境即可。但作为一个跌宕起伏的故事剧本,到这里只是开始…我找到了pe,希望pe能帮忙把生产环境的nginx也按照上述配置修改一下。这时pe说了一个不幸的消息,线上的nginx配置不能修改,修改这个文件简单,但是后续维护很难,过了半年如果没人关注这些修改,一旦要扩容或者维护,就会出问题。确实是这样,不能因为项目给运维增加非标准化的风险。所以,这套基于静态文件部署方案就此腰斩,只能另想它法。后来又想了两个方案:

  • 用个java的web项目包装一下静态文件,把项目做成了后端的,用java做代理,但是这样就变成了老的架构,前后端分离的意义不就荡然无存了。

  • 全项目改造,全部用jsonp处理跨域。但是这个也不理想,项目已经开发完成,这个时候改造工作量比较大,而且只能用get也会有问题。

就在不知如何抉择时,pe告诉我一个好消息,京东部署平台有一种application-worker模式,允许执行自己的shell脚本,而且有人已经基于这个部署过node。这个消息给了项目新的希望,我立刻找到了当初部署过node的前辈@沈度先,在他写的文档基础上,做了一些调整和改造,最终在生产环境成功部署了完全标准化、自动化,没有运维风险的方案。大家可以参考本文,也可以参考@沈度先发布在cf上的文章。

首先,需要将node环境在生产环境上运行起来,这是最关键的一步。步骤如下:

一、在生产服务器安装node环境。这一步需要pe大力支持,pe会帮你搞定一切,你只需要告诉pe node的版本号就行了。

二、在生产环境安装pm2。pm2是linux下的一个进程管理器,能帮助我们管理node进程。它有两个作用:维持node进程,守护和管理node进程。

  • 维持node进程,在开发环境,我们都是执行node app.js 来启动node,但这种方式是不能用于生产的,当请求链接一断,node进程就会被杀掉。可能有人会说可以用nohup,没错,nohup确实可以,但是它缺少了第二个功能,管理。

  • 管理node进程,我们需要做自动化的流程,那就需要对node进行进行管理,能启动、停止、重启node,并且最好是能有监控,方便我们查找线上问题。能做到这两点的,除了pm2还有forever等。但是forever虽然支持也监控,但需要在linux下执行命令,没有图形化界面。个人建议选择pm2。

三、编写启动和停止脚本。接下来就是编写启动和停止脚本。京东部署平台部署时会自动调用启动脚本和停止脚本。

  • 启动脚本:启动脚本需要做两件事:判断node进程是否已经启动,如果没有启动,则将之启动。利用pm2命令“pm2 list”来检查是否有正常运行的node进程。

  • 停止脚本:

总 结

项目一波三折最终成功的上线运行了,虽然比较曲折但是也积累了一些经验。同时本文介绍的是纯客户端渲染的项目的部署方案,如果是服务端渲染SSR(server-side-render)的项目,部署上还会有所区别。

  • 测试环境可以作为纯静态文件部署,以nginx做代理实现跨域。

  • 生产环境需要利用application_worker模式,在生产服务器安装node和pm2,编写启动、停止脚本。利用shell脚本控制项目的启停。这种模式下node即作为http服务器,也作为代理服务器。

  • 部署方案不止一种,只要能很好的解决问题就是好方案,大家有更好的方案欢迎一起探讨。

  • 停止脚本还有待优化,pm2 stop all 并不可靠,有时会发生执行sop命令后,用pm2 list 查看进程,node进程还在,状态变为error,导致启停失败。可以使用kill 命令辅助,在pm2失效时,杀死进程,重启。


京东金融技术说

   ▼▼▼     

原创·实用·技术·专业

不只一技之长

我有N技在手

你看,我写,共成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值