我们已经准备好了,你呢?

2024我们与您携手共赢,为您的企业形象保驾护航!

接手淘宝首页不久,就遇到了年度改版,那时候还运行在PHP环境中。这里要注意的是,淘宝首页所有的代码完全由前端控制,前端不直接和数据库交互。它的数据源分为两部分。

数据源

首先是操作填写的数据,前端用来挖坑、留坑给操作获取填写的数据,如(伪代码):

js include php_js include php_js include php

上述代码会生成一个PHP模板,以及与info字段对应的表单坑,这个过程我们称之为“挖坑”。

js include php_js include php_js include php

当操作人员填满这些槽位之后,就会生成这个PHP模板对应的数据,最终渲染出来的是一个完整的HTML片段(实时渲染)。

这是旧版本系统中子模块的构建方式,我描述的很简单,但作为一个平台,需要考虑的东西很多,比如数据顺序控制、定时发布、回滚机制、过滤机制、筛选机制、数据同步、数据更新、版本控制、权限控制、对其他系统的引用等等。

第二是后端或者个性化平台提供的数据。不同的业务有不同的诉求,有的业务有自己的后端,要求使用自己业务生产的数据;有的业务希望用户看到不同的内容,期望接入算法;有的业务直接跟卖家打交道,期望使用招商数据;有的业务期望使用运营从数据池中筛选出来的数据……总之,淘宝首页需要对接各种系统,接口很多,动态数据源的集成后面会提到。

而且这些系统对应的域名都是不一样的,所以JSONP格式自然就成为了首选。但是对于一些特殊的系统,比如广告,它们的渲染并不是简单的JSONP请求,还可能干预整个广告渲染的流程,比如加载它们的JS,把渲染的控制权交给它们。

页面架构

上面介绍了数据的来源和子模块的结构,那么整个页面是怎么构建的呢?模块构建分为两种,一种是可视化构建,运营或者前端把开发好的模块(或者从模块库中选择的模块)拖拽到容器中,就形成了一个页面。

js include php_js include php_js include php

当然,上图只是一个模型,作为一个系统,还有很多问题需要考虑,比如页面布局、多端适配、模块临时隐藏、位置调整、皮肤选择、模块复制等等。

您也可以使用以下源代码来构建(伪代码):

js include php_js include php_js include php

通过模块id导入模块,并添加一些类似的标签来控制渲染节奏和数据入口。源码构建和模块构建的区别在于前者更容易控制模块的结构和模块的渲染顺序。

动态数据源

首页面对大量的接口和平台,对接几十个业务方。接口是一个很大的问题。由于后端系统的差异,数据源的格式基本没办法统一。一旦运营人员想换一个自己认为更舒服或者数据更好的系统,前后端很可能要沟通、对接好几次。于是就出现了下面的画面:

js include php_js include php_js include php

平台具备接入数据源的能力,也就是说我们挖的坑不仅可以让操作填数据,还可以直接从各种数据源导入数据。当然这里需要一个数据字段映射转换。后端提供的接口如下:

前端同意的接口形式为:

那么系统必须为这个映射提供一个绑定策略:

绑定后,数据可以同步输出,也可以异步输出,这是平台提供的能力,这个方案基本解决了后端系统/界面变更的问题,减少了前后端的沟通成本。

不过需要注意的是,虽然页面上的接口都是通过平台统一整理的,但是这也意味着对该页面的所有请求都会先流经平台,然后再分发到各个后端,对平台的抗压能力要求非常高。

2. 从 PHP 过渡到 Node

淘宝首页每天的请求量,不是十几二十台服务器能够应付的,需要一个服务集群来支撑。

js include php_js include php_js include php

每个CDN节点都具备PHP渲染能力,当一个页面发布时,我们会把该页面的所有模块和数据同步到所有CDN节点,这是最基本的模式,看上去还不错,但是经过一段时间的运维,很多安全和性能问题逐渐显现出来。

性能问题。每个PHP页面包含多个子模块,子模块之间还可能引用其他子模块。PHP操作耗时较长,每次引用都是一次磁盘IO。如果一个渲染节点运行几千个类似淘宝首页的PHP页面,并发量高的情况下,其效率可想而知。

//@邦彦同学补充道:PHP 运行确实会耗资源,但是预热加载执行过程之后直接缓存字节码,不存在频繁的磁盘 IO。PHP cdn 性能差主要有两点问题:1、PHP 版本太老,5.4 和 7 性能相差好几倍以上;2、fast-cgi 模式在高并发场景下相比 node 并无优势。

推送机制问题。文件同步(图中的 sync 动作)是一个比较恶心的机制。首先时间无法控制,一个文件同步到所有节点最快也要几秒到一两分钟以上。另外同步过程可能会失败,健康检测的成本也相当高。当发布比较紧张,需要同步的文件较多时,容易造成队列堆积,加剧同步体验不佳。

实时性要求强的问题。文件在推送前可能会经过一些前端系统,发布环节越长,上线生效时间越慢,最慢也要五分钟左右才能生效。这样的延迟对于实时性要求高的需求(比如秒杀)是完全不可接受的。

当然,还有很多其他的问题,比如运维成本增加、安全风险增大、高级PHP人才储备不足等等,所以,PHP渲染容器的命运是被干掉的。

下图换个玩法,服务集群是Cache CDN,只具备静态文件处理能力,没有PHP/Node渲染能力,因此处理效率高,性能好,抗压能力强,当承受不住的时候,可以花钱买服务,扩容Cache集群。

js include php_js include php_js include php

当用户访问的时候,Nginx 会走 Cache CDN,如果命中缓存,就直接返回,如果没有命中,就返回到源服务器,源服务器是一个有模块渲染能力的 Node 服务,它可以做很多事情:

它的优点还有很多,这里就不一一列举了。这种模式还增加了一层容灾,源服务器会定期将数据推送到与缓存位于同一机房的备份服务器,一旦源服务器出现故障,可以自动恢复到备份数据。

模式的改变不仅带来了运维上的突破,也大大降低了CDN在受到攻击时的安全风险,还省去了同步所需的各种检测机制,每年可以节省上百万元的成本,优势还是比较明显的。

3. Node,一种不同的模型

在上面的 PHP 模块中,我们只讲了 HTML 和数据,细心的读者应该注意到了,并没有讲到 CSS、JS 等静态资源。那么页面是如何渲染出来的呢?

在老版本的PHP页面中,我们直接引入一个CSS和一个JS。淘宝采用git版本迭代发布,这些静态资源直接放在一个git仓库中。即:

js include php_js include php_js include php

每次发布git文件后,修改PHP版本号,再发布PHP代码。当然也做了相关优化,比如发布git时自动更新版本号。

新版本平台的页面渲染模式与PHP模式有所不同。

一个模块的CSS/JS和模板放在一起,页面其他模块的CSS/JS和静态资源相互独立,目的是为了让单个模块能够完整运行,更利于模块复用。

模块的挖掘也已经从模板中分离出来,数据格式以JSON定义。

js include php_js include php_js include php

构建平台将这个JSON解析成图1中的坑位,然后编写一个模块的渲染程序,将index.xtpl和坑位数据组装起来。

模块之间相互隔离,这样会有一定的冗余,但是模块解耦带来的好处远大于这种冗余,其实我们通过一个仓库来管理单个模块,页面渲染比较简单, Node容器会把所有的index.xtpl合并成一个page.xtpl,为了减少页面请求,css和js也会合并成一个文件,如上图mod2.css,mod3.css。

页面会感知任何模块的更新,下次进入系统时会提示您是否需要升级模块和页面。

二维码
扫一扫在手机端查看

本文链接:https://by928.com/4973.html     转载请注明出处和本文链接!请遵守 《网站协议》
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。

项目经理在线

我们已经准备好了,你呢?

2020我们与您携手共赢,为您的企业形象保驾护航!

在线客服
联系方式

热线电话

13761152229

上班时间

周一到周五

公司电话

二维码
微信
线