专栏首页腾讯NEXT学位双十一狂欢的背后和NODE.JS不得不说的故事

双十一狂欢的背后和NODE.JS不得不说的故事

覆盖业务

经过几年时间的改造和推进,到 17年双十一的时候,已经有大量的业务都有了 node 的身影,基本上天猫大部分的 web 页面都是通过 node 渲染出来:

  • 天猫首页、大部分天猫频道页、双十一会场以及所有天猫的活动页面都全部基于 node 应用提供服务。
  • 商品详情、店铺和搜索页等主流程链路上,以及天猫超市和天猫会员等业务线上的页面渲染。
  • 天猫页面搭建平台 web 层基于 node 进行开发,双十一期间在此平台上搭建了超过 1000+ 个双十一相关活动页面。

工作职责

在上述覆盖了 node 的业务中,node 在其中扮演了多种角色:

完整的 web 应用

天猫页面搭建平台即是一个由 node 负责整个 web 端包括业务逻辑和模板渲染等工作的应用。基于支付宝的 node web 框架 chair,通过 hsf 调用和淘宝共建的页面数据存储的接口,用 node 完成业务逻辑处理、页面渲染和前端接口。

轻量级的模板渲染容器

通过 node 整合前端的天猫组件规范 MUI,开发了一套专注于模板渲染的 node 容器(wormhole),通过这个 node 容器,前端可以专注于展现层的开发,统一前端的本地和线上的代码运行环境,也让后端摆脱了繁琐的套模板工作,专注于提供数据接口。同时这套容器基于天猫的模块化规范,横向打通了各个业务和应用之间的模块共享。

基于这个模板容器,完成了商品详情、店铺、搜索页以及超市等业务线上的前后端分离工作,大大提升了前端的开发效率,并有效降低了前后端沟通成本。

页面渲染服务

同样基于天猫前端的组件规范 MUI 和模板渲染的 node 容器,完成了一套模块化搭建页面的系统,同时开发并运维了一个用来渲染基于模块搭建的页面的服务,同时这个服务和阿里的 cache CDN 打通,在保证满足业务需求的前提下,降低消耗的计算资源。

基于这个服务,在双十一中提供了 900+ 活动页面的渲染,以及天猫首页和各个频道页的渲染工作,天猫的所有营销引流页面基本都由这个服务提供页面。

进入正题

上面讲了 node 做了什么,以及覆盖了那些业务,现在来看看,到底怎样用 node 解决实际的业务需求的。

拿这次双十一的会场页举例:

  1. 用户在不同的终端环境下访问 1111.tmall.com 这个网址,请求会直接来到 CDN 上。
  2. CDN 对用户的终端环境进行判断,并在内存中找到对应终端的缓存文件返回,若未命中缓存,则继续往下执行。
  3. CDN 将请求转发到 node 渲染服务,根据终端类型选择不同的页面响应(pc 页面,h5 页面, react-native 页面)。CDN 响应用户请求,并缓存页面。

在上述流程中,我们看到同一个 url 对应到后端其实是完全不同的页面输出内容,为了达到这个目的:

  1. 开发了一个 tengine-detector 组件,通过请求的 user-agent 以及约定的一些 cookie 信息,判断用户的终端类型。并部署到 CDN 上,让 CDN 拥有了终端判断的能力。
  2. 用户请求到 CDN 上之后,CDN 会根据用户的终端类型分类,设置一个请求头,例如: detector: pc 表明这个请求的终端设备是 PC 上的浏览器。
  3. 渲染服务获取到这个头之后,根据 url 和设备类型选择不同的页面返回。返回时设置 varydetector,保证 CDN 根据不同的设备类型缓存不同页面。

上面提到会根据终端类型对于同一个 url 返回不同的页面,而这些页面其实都是通过一个基于 node 开发的天猫页面搭建平台用模块搭建的。在这个平台上,超过 95% 的模块都拥有 pc 和无线两个版本,本次双十一所有用到的模块都有 react native 的版本。运营只需搭建 PC 上的页面,就会自动生成无线以及 react native 的页面。基于这套方案,通过 70+ 高质量的模块,让运营完成了超过 900+ 活动页面的搭建。

再深入一点,如何来完成这些页面或者是模块的呢?首先,让前端开发做什么?

  • 编写模板
  • 拿到数据(并处理),和模板进行结合
  • 拿到请求上下文,时间、环境等系统变量来确定不同的展现
  • 管理前端资源和依赖

在 xtemplate 模板引擎的基础上进行扩展,让前端通过编写 xtemplate 模板,在 context 中注入一些必需的页面上下文,扩展 xtemplate 的语法,支持引入前端资源。基于这套模板,可以在拿到数据后渲染得到完整的页面,基本满足了开发页面在功能上的所有需求。

但是页面中其实有非常多重复性的内容,完全可以把他们抽象成一个个的模块,让页面通过模块化的方式来基于模块搭建,在这个过程中需要解决几个问题。

  1. 模块版本和静态资源版本的管理:页面可能引用几十个模块,而这些模块依赖的静态资源有重复、有冲突,因此会通过一份统一的 seed 来进行依赖版本的管理,每一个模块在发布的时候都会打包好自身的依赖关系,而在将所有的模块组合成页面的时候,将所有模块的依赖表重新进行合并和去重,最终保证页面引用的模块和静态资源唯一。同时在模板中通过扩展引入了 FELoader(天猫的静态资源加载器),收集页面的所有静态资源,combo 后插入到页头(css)或者页尾(js)。
  2. 模块如何拿到相应的数据:对于模块而言,他并不需要知道被哪个页面引用了,所有的页面在引用模块的时候需要将模块所需的数据传递进去。而所有的模块开发者需要编写一份模块需要数据的 JSON Schema 描述,通过这份描述文件,搭建平台、投放系统以及其他使用这个模块的人都能够知道要为这个模块产生什么格式的数据。
  3. 配套的搭建平台和数据投放平台来让运营自由组合所有的模块生成页面,并为页面上的每一个模块进行数据投放。

解决完上述问题之后,将每一个页面都变成了以下几个部分:

  1. 一份页面的描述文件,声明了这个页面依赖的所有模块,以及渲染这些模块所需的数据的地址。
  2. 一系列相互独立的模块。
  3. 一份包含页面上所有模块需要的数据的数据文件。

最终,渲染服务会根据 URL 和请求的终端环境,找到对应的页面描述文件,请求相应的数据,合并所有的模板渲染成为 HTML 页面。

当完成了 web 页面的模块化搭建之后回头再看,是不是 react native(RN) 的页面也能够搭建呢?只需要所有的模块都有对应的 react native 版本,就可以像搭建 web 的 html 一样搭建渲染出 RN 需要的 js 了!所以本次双十一使用的所有模块都有 RN 版本,并有多个会场采用了 RN 进行搭建,取得了非常不错的效果,在接下来的双十二中,所有的会场都会支持 RN,而这一切对于搭建会场的运营来说都是完全透明的。

稳定性保障

对于 node 应用自身而言,首先要保证它有充足的测试,通过 mocha + istanbul ,尽可能让测试覆盖每一个功能点和边缘情况。

需要有完善的监控和报警。在阿里,已经有了内部的监控系统,对于 node 应用而言,只需要按照要求的格式打印的日志,或者通过自己编写日志采集脚本,就可以轻松的搞定监控和报警。

  • 错误日志监控:通过采集脚本采集上来并分类,并设置单机报警和阈值和集群报警的阈值,在异常出现时能够及时发现。
  • 系统状态监控:内存、CPU、load 等的监控,并设置报警阈值,当系统状态异常时能够及时发现。
  • 应用状态监控:QPS、响应时间以及所有的远程调用记录,时刻了解系统的负载和各个依赖节点的服务状态。

同时,对于 node 应用,可以使用 alinode ,他们可以提供更多 node 的日志和监控,并提供了在线的 profiler 和快照功能,方便排查线上异常和性能优化。

尽管可以对自身的代码做各种测试、各种监控,但是在一个复杂的系统中,各种上下游依赖非常复杂,网络情况也很复杂,这个时候为了保证稳定性,还有许多的工作要做。

没有单点

假设一个机房的光缆被挖断了,或者机房所在的城市大规模断电了,然后整个天猫的大部分页面都不能访问了,这明显不能接受,所以需要在多个城市的多个机房部署服务。如果存放模板文件或者数据文件的服务挂了怎么办?多个节点,主备读取,同时对所有的文件都加上磁盘文件容灾。对外提供服务的整条链路上的每一个依赖都不能够出现单点问题。

弱化依赖

在排除完单点问题之后,再来审视服务,是不是所有的依赖在挂掉后就无法正常服务了?是否对于每个依赖异常都有容灾的方案,弱化掉整条链路上的依赖。

预案自动化

对于每一个可能出现问题的环节,都需要有针对性的预案,如果这个预案需要人工去执行,就需要思考能否做到自动化。在 node 渲染服务中,可能有各个缓解出问题,链路上的所有预案都要能够自动切换:

  • CDN 回源到多个机房,当某个机房异常时能够通过健康检查自动剔除。
  • 当源站 load 过高时,服务自动切换到静态版本不做渲染。
  • 当模板或者数据的存储节点挂了,通过健康检查自动剔除。

总结

node 只是工具,在每一个具体的业务场景下都有最合适的使用方法,而随着业务的发展,node 能做的事情也在变化,期望它能在之后能在更多的场景下落地。


本文作者:掘金

本文分享自微信公众号 - 腾讯NEXT学位(NextDegree)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-11-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 学员投稿 | iframe 解决跨域

    ? 天气降温,大家注意保暖~~~ ? 因为学习了腾讯课堂NEXT学院的前端进阶课程,所以打算把课程内容都总结一遍。有些都是很普通很常见的知识,但是为了巩固自...

    腾讯NEXT学位
  • 干货|小程序性能优化的几点实践技巧

    “ 我们都知道,性能的好坏直接影响用户的体验。本文首先论述下如何评判一个小程序页面的性能情况,之后通过具体的案例重点讲解下几点实践技巧,最后再讲讲key值在渲...

    腾讯NEXT学位
  • IMWebConf 2018 圆满落幕,精彩内容回顾

    2018年10月14日,第七届IMWebConf前端大会在深圳科兴国际会议中心成功举办。今年大会现场参会人员近500人,线上直播参与人数累积近千人。 IMWe...

    腾讯NEXT学位
  • 腾讯云CentOS下nodejs的安装方法

    访问链接 https://nodejs.org/en/download/ 找到最新的文件。如图所示是最新的安装文件

    115621060
  • 微信小程序商城开发---真机测试有用!!!!

    第一部分(黑色框)是pages是整个里的页面,每添加页面一个页面,都要把路径写在这里:

    疯狂的技术宅
  • 微信小程序开发指引

    官方文档教程1:http://bcoder.cn/wxopen/ 官方文档教程2:http://bing.aliaii.com/wxopen/  本文档将带你一...

    用户1220053
  • 页面相似度检测,对SEO起到什么作用?

    我们知道百度蜘蛛对页面更新频率和页面原创度是情有独钟的,如希望网站快速获取排名这两点我们必须满足,而做SEO的我们都知道,长期的大量创造原创文章不但是及其辛苦也...

    蝙蝠侠IT
  • 在新窗口中打开页面?小心有坑!

    1. 背景 产品需求来啦:点击页面上某个东西,要在新窗口中打开一个页面,注意!要在新窗口中打开。你呵呵一笑,太简单了: 打开的页面地址是固定的?直接a标签加上t...

    IMWeb前端团队
  • 在新窗口中打开页面?小心有坑!

    产品需求来啦:点击页面上某个东西,要在新窗口中打开一个页面,注意!要在新窗口中打开。你呵呵一笑,太简单了:

    IMWeb前端团队
  • 前端和前端联调的各种姿势,了解一下

    背景:父页面index.html里面有一个iframe,iframe的src为子页面(另一个html的链接),下文都是基于此情况下进行

    lhyt

扫码关注云+社区

领取腾讯云代金券