您的位置:首页 > 运维架构 > 网站架构

京东架构师讲解京东是如何优化列表页的

2016-07-15 12:00 381 查看
三级列表页是什么

列表页是京东商城的三大核心系统之一。京东三级列表页是用户选取商品类型后,展示同类商品的页面,具体如下图表示:



如何进入三级列表页

用户在首页左侧的导航中(如下图所示)、全部商品分类列表页或者顶部面包屑导航中,选择到商品的最小类别后,就可以到达三级列表页



三级列表页的作用

该页面根据用户选择的商品类目进行检索,将结果以列表展现在页面上。是用户快速的找到自己需要的产品,提高用户购买转化率。

三级列表页的业务特点

涉及到多维度多因子质量分综合排序,排序质量的效果直接关系到转化率,客单价,进而影响到GMV,实质上是数据挖掘和机器学习技术在海量数据上的应用。

在不同三级类目下,通过复杂不确定的查询条件、属性区域和列表查询结构的实时联动,以及跟区域相关的库存、京东配送、货到付款等复杂业务逻辑下,坐到高并发实时计算。

优化原因

三级列表页的页面周围依赖的内部系统太多,要做到异步化展示,阻塞可降级。

在持续开发一个核心系统过程中,除了满足业务需求外,还应该考虑系统未来的架构,追求极致的系统的可用性、高性能和稳定性。这个过程是一个长期积累和重构的过程,京东三级列表页的优化工作,就是这个过程的一部分。

优化前的状况

优化前的三级列表页有一下特点:

1.基于搜索实现。

2.全量数据,搜索结构不理想。

3.接口相应时间长,影响了用户体验。

4.没法针对数据做二次优化。

5.转化率相对较低。

基于以上原因,需要对三级列表页做出改变,也就是对老版本进行重构。

重构版本目的

通过优化,希望达到以下目的:

1.非全量数据,线下异步根据数据模型进行筛选部分最优数据。

2.要求实时过滤计算,接口响应时间要快,保证用户体验。

3.数据进行优化,提高转换率,提高GMV。

4.实现前端降级和异步模块出错上报。

优化原则

每个应用都要满足自己特定的需求,因为其商业条件、应用场景、用户期望,以及功能复杂性各不相同。尽管如此,如果应用必须对用户作出响应,那我们就必须从用户角度来考虑可感知的处理时间这个常量。事实上,虽然生活节奏越来越快(至少我们感觉如此),但人类的感知和反应时间则一直都没有变过:

下面这个表格展示了Web性能社区总结的经验法则:必须在250ms渲染页面,或者至少提供视觉反馈,才能保证用户不走开。如果想让人感觉很快,就必须在几百ms内相应用户操作。超过1s,用户的预期流程就会中断,心思就会向其他任务转移,而超过10s,除非你有反馈,否则用户基本上就会终止任务!



此次的优化工作遵循一下四个原则:

1.首屏优先:精简和瘦身页面,首屏优先展示出来;

2.惰性交互:需用户交互的部分惰性加载;

3.惰性执行:能不执行的先别执行,惰性执行;

4.惰性滚屏:滚动惰性加载。

主要优化工作

(1)首屏优先

为了保证首屏优先展示,HTML文档进行了适当精简。

目的:尽快渲染出页面并达到可交互的状态。

方法:

1.如果非必须,尽量只生成首屏需要的HTML数据。

2.优先获取资源,提前解析。如首屏需要的CSS和JS;如果不考虑维护成本,可以把首屏需要的CSS和JS放到文档中。

3.发现和优化安排网络资源,尽早分派请求并取得页面。

4.文档精简后,服务端生成程序耗时短,性能才回好。

如下图所示,列表页的头、面包屑、品牌区、属性筛选区、60个商品主图数据,这些是服务端模版渲染输出;而剩余部分是在前端js惰性加载或生成。



(2)惰性交互

惰性交互,即对需用户交互的部分进行惰性加载。

对于三级列表品牌区,服务端只渲染18个品牌,用户在点更多时,AJAX异步加载其他的。对于整个属性是筛选区服务端只渲染5行,其他行用户在点更多时,js从文档嵌入资源中取得数据,并渲染成HTML。这样做可以保证服务端计算量少,提升服务端性能,较少数据传输。

如下图:点“更多”时才加载更多的品牌,因为有些三级类目有许多品牌,如果不采用这种方式,整个页面渲染非常慢。



(3)惰性执行

能不执行的先别执行,惰性执行。

上图是三级列表页最重要的商品区(商品主图+N个关联商品小图),每个商品的区域都是完全一样的;如果在服务端拼装整个商品区域的话,尤其涉及到小图部分,会有非常多的重复HTML元素。



我们把体验和减少页面内容进行了折中处理:服务端渲染输出商品主图部分;小图部分通过Json数据嵌入到页面,然后通过js惰性执行渲染。这样可以很好地对页面进行瘦身。而且小图资源是页面嵌入的,非异步加载;没有网络请求。因此,用户基本感知不到异步带来的渲染闪动问题。

(4)惰性滚屏

三级列表页的60个商品区域的图片和页尾都是当用户向下滚动页面时,才去加载当前屏幕中的图片和模块。这样可以节省服务器带宽和压力,提升页面整体渲染时间。

细节优化工作

在实际优化过程中,还涉及到非常多的优化细节。

讲一些JS/CSS资源直接嵌入页面

把资源嵌入闻到那股可以减少请求的次数。比如页面需要的JS、CSS数据。如下图所需:



上图中的那些JS对象,是后端渲染输出的,因此不适合放入单独的JS文件,直接在页面中嵌入输出会更好些。slaveWareList是小图的列表对象。如果放在服务端渲染输出的话,首先需要进行一些循环拼装页面;另外会使页面体积变得非常大。

权衡之后决定放到前端JS渲染输出。这样也带来了一些好处:

1.减轻服务端压力,提升渲染模版性能和减少服务端执行时间;

2.服务端不用生成HTML,文档减少上百个DIV,减少页面大小和网络开销。

3.提前放到HTML中,不用异步调用。

4.用户基本感知不到渲染过程。

对引入的资源排定优先次序

根据自己系统的业务,对每种资源定优先级:对必需的资源有限加载。而低优先级的请求保存在队列中延时加载或等待必须资源加载完成再加载;如:搜索推荐热词、顶部三个热卖商品接口、60个主商品的图片、价格有限加载。而对于库存、促销信息、广告词、预售商品、店铺信息等。延后加载。对于点击流,广告统计数据则延时两秒再加载。

应用JS缓存来存储公有属性和商品信息属性

三级列表页中的每个商品都是一个对象。存放在一个Map中,通过AJAX接口异步填充和维护商品的属性。用于后续用户交互用。同时维护成本也会降低;即页面中的每个商品数据放入一个Map中,如果没有则异步加载;如果没有则异步加载;如果有直接使用;即这些数据是公共数据。



AJAX接口最优调用

页面往往依赖很多的异步接口,因此要对异步接口进行压测,找出接口的最优调用方式。如京东三级列表页依赖价格、库存、广告词、店铺信息等异步调用接口。而页面有时候会出现多达300多个商品,如果用一个get请求把这些sku做参数,性能非常慢,那么就采取分组分批调用。如页面商品在300个时,价格接口分六组,第一组30个,第二组30个,第三组60个,第四组60个,第五组100个,第六组100个。

DNS预解析

对可能的域名进行提前解析,避免将来HTTP请求时的DNS延迟。如对价格、库存、图片、单品页等服务预解析。



减少HTTP重定向

HTTP重定向极费时间,特别是不同域名之间的重定向,更加费时;这里面既有额外的DNS查询、TCP握手,还有其他延迟。最佳的重定向次数为零。比如三级列表页以前是http://list.jd.com/9987-653-655.html,而现在是http://list.jd.com/list.html?cat=9987,653,655;在过渡期间可以重定向,但是过渡完成后就没必要重定向了。

使用CDN(内容分发网络)

把数据放到离用户地理位置更近的地方,可以显著减少每次TCP链接的网络延迟,增大吞吐量。比如京东三级列表页、商品详情页、公告JS、CSS

传输压缩过的内容(Gzip压缩)

传输前应该压缩应用资源,把要传输的字节减至最少;确保每种要传输的资源采用最好的压缩手段。所有文本资源都应该使用Gzip压缩,然后再在客户端和服务端间传输。一般来说,Gzip可以减少60%~80%的文件大小,也是一个相对简单(只要在服务端上配置一个选项),但优化效果较好的举措。(对于压缩级别,经过不同服务器的多次压测,建议Nginx设置为1-4)

去掉不必要的资源

任何请求都不如没有请求快,把一些非必须的或者可异步的,或者可延迟的尽量延迟请求。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  京东商城 优化