京东列表页性能优化实践

京东列表页是什么

   京东列表页是商品属性高度聚合的关键词或索引组成的目录树,从京东首页下拉菜单里可以直接进入。

列表页承载网站大部分流量和订单的入口。列表页目前有通用版、全球购、特产管、凤凰、四免一等许多套模板。各套模板的元数据结构是一样的,只是展示方式不一样。目前列表页很多需求都在模板上处理,因此我们需要一种架构能快速响应和优雅的解决这些需求问题
http://list.jd.com/list.html?cat=1315,1342,1349

京东列表页性能优化实践_第1张图片
 
列表页涉及的服务

列表页HTML页面渲染

价格服务

促销服务

库存状态和配送至服务

广告词服务

预售和店铺信息

推荐商品

热卖商品

快报

脚印等等

架构


京东列表页性能优化实践_第2张图片
 
京东列表页性能优化实践_第3张图片
 

性能数据

11当天访问量亿,双11当天服务器端响应时间<80ms。此处我们用的是第1000次中第99次排名的时间。 (页面200-300KB,逻辑复杂,渲染元素多)


京东列表页性能优化实践_第4张图片

 

列表页流量特点

数据离散

热点少

各种爬虫、比价软件抓取。

架构特点

能迅速响瞬变的需求,和各种变态需求;

支持各种垂直化页面改版;

页面模块化;

开关可控制模块功能;

一分钟降级;

AB测试;

高性能、水平扩容;

多机房多活、异地多活;

静态化;

各种异常和兜底数据;

 

防爬虫和恶意刷列表页;

 

业务优化思想

使用Nginx+Lua技术获取数据并渲染模板输出

页面逻辑分散到各个阶段

数据结构优化

算法优化

页面html瘦身

 

Js等前端优化

Nginx+lua的优势

Lua是一个可以嵌入到Nginx配置文件中的动态脚本语言。

Nginx的看家本领就是速度,Lua的拿手好戏亦是速度,这两者的结合在速度上无疑有基因上的优势。应对高并发nginx更有出色的表现。

Lua简单易懂,适合快速开发。

Lua模板渲染性能不错支持随时变更模板需求。

Nginx秒级重启,重启不丢失本地缓存数据。

 

模板引擎:lua-resty-template

 

https://github.com/bungle/lua-resty-template

 

数据结构优化

Luago直接是http调用,返回的数据是json串,需要反序列化。

反序列化非常消耗cpu

对象》数组》字符串

变量用0,1代替字符串

 

数据层级最好不要超过三层

算法优化

模板输出变量严重消耗性能。一个变量,在模板上只输出一次。多余的不输出。

for循环用for i=1,#evParamsArr do end 方式。

数组table t={}t[#t+1]=“”;取代table.insert(t,””);

对于需要遍历的数据结构尽量用key-value,不要用数组。

lua-resty-http模块中keepalive默认是true。调用的服务不支持的话,要改源码为false

Lua中类型转换,提前把类型转换好,然后再参与运算。

字符串拼接用数组先存起来,最后concat

 

不用嵌套循环模板中不要重复输出同一个变量,并且输出前要转成str类型

提升速度的优化方向

负载均衡:DNS+CDN减少DNS查找,每一次主机名解析都需要一次网络往返,从而增加请求的延迟时间,同时还会阻塞后续请求。

减少页面连接数 和并行处理请求和响应:减少浏览器http并发连接,合并js,合并css,合并图标。请求和响应的排队都会导致延迟,无论是客户端还是服务器端

减少页面大小:带宽有限,gzip压缩

页面静态化:同一时间内,查下相同分类的结果页面都是一样。

前端缓存:应该缓存应用资源,从而避免每次请求都发送相同的内容。

前端页面模板数据结构和后端数据结构优化

 

异步化、非实时变化数据,可以异步请求

前端js分担一部分模板非必须的逻辑处理(考虑seo)。如ajax、瀑布流、bigpipe等。

后端服务尽量不调用其他系统接口。如果调用,可用定时任务把数据缓存起来,然后自己取。

重用TCP连接:尽可能使用持久连接,以消除TCP 握手和慢启动延迟;

减少HTTP重定向:HTTP 重定向极费时间,特别是不同域名之间的重定向,更加费时;这里面既有额外的DNS 查询、TCP 握手,还有其他延迟。最佳的重定向次数为零。

消除不必要的请求字节:如cookie太大

 

用其他三级域名做异步调用。

降级开关前置

开关前置

1Init_by_lua_file初始化开关数据

2、共享字典存储开关

 

3、提供API进行开关切换

开关控制

     秒级切换开关

    功能切换开关

    第三方服务降级开关

 

    异常、超时等自动降级

 

JS相关优化

1、异步方法先后执行顺序要控制。

2、对于非必须的业务,做成wait2000毫秒。

3、对于点击流做成页面加载完再调用wl.js

4、考虑各个接口性能,分批调用。

5、回调函数的优化,不要全局find,把需要的元素缓存到全局变量中,从缓存中查找比全局查找快。

6js面向对象编程,不要因为某个方法报错影响后面的js功能执行。同时维护成本降低。

7、需要缓存的数据,尽量缓存起来,减少调用次数。

 

8、埋点的onclick不要写在html里。动态绑定。

 

 

 

 

缓存架构

1缓存的存在一是提高访问速度和高并发,二是上游服务器挂了,还有缓存数据给用户展示,相当于兜底了,虽然内容旧一点,但是不会形成事故,影响用户体验和无法浏览商品

 

2这里的缓存还可以理解为一个小型cdn服务器功能。为后端应用挡流量

 

3台应用服务器都有自己的缓存HttpLuaModule模块shared dict),缓存中放当前时段内最热的数据。如果缓存不命中,go服务取。reload不丢失)

 

 

4、当出现异常时,从本地缓存取,如果没有从Redis缓存取(独立全量的缓存,请看下图)


京东列表页性能优化实践_第5张图片
 

读取分布式Redis缓存

服务异常读取。

 

异步收集数据,定时执行写缓存。

 

使用本地Twemproxy进行分片

 

减少redis连接

 

1 缓存的内容是什么

  缓存的是调用上游服务器,lua渲染模板后的html数据(页面在200Kb左右)。

 

2缓存中取数据的时间多少
京东列表页性能优化实践_第6张图片
 

 


京东列表页性能优化实践_第7张图片

2Key值是什么

Key值是对用户访问的url进行过滤和排序后md5值。(url中多余的非白名单参数丢弃)

3缓存失效时间设置

缓存的失效时间在上图key缓存存入时指定,这个时间在配置文件中,可随时调整。

4缓存的数据不设置过期时间

上图第一页缓存和其他页缓存存入时,不指定失效时间。通过nginx的共享缓存自己来管理,LRU策略淘汰冷数据。(Least recently used. 可以理解为, 最少使用的被淘汰。)

5第一页和其他页缓存为什么是10

Nginxshared_dict缓存读取是有锁的,如果放在一片上,读时间会长,高并发下,容易形成排队严重的瓶颈。

6为什么第一页和其他页缓存分开

因为服务器的内存是有限的,第一页是每个三级分类的默认页,从首页菜单直接进入的页面。这块缓存不能被丢弃,所以单独分配了存储空间,这个空间合理计算好,不能用完。同时,如果后端接口有问题、数据解析有问题、各种异常等,都需要用这块数据做最后的兜底。

7如何区分第一页和其他页

根据自己的业务,通过判断url上的参数值来确定。

8开关控制

 

整个缓存模块有五个开关来控制,总开关、第一页写开关、第一页读开关、其他页写开关、其他页读开关。

10500501502503504error timeout等异常处理

        对上面后台服务运行时错误,在nginx做了一层递归跳转逻辑。跳转时,加了一个header值,标记是服务器错误,直接在程序中判断static=1返回共享字典缓存或redis缓存数据

11缓存命中率问题

        由于列表页用户筛选的属性千变万化,第一页缓存命中100%,但是其他页缓存命中只有12%,所以要引入redis来全量存数据。提高命中率Redis缓存是一个写异步的work,异常时读取

12缓存cdn技术结合使用

     对于上cdn,是程序根据不同的分类来设置header头的。Cdn回源时,命中缓存后,取缓存的flag值,来决定是否写header头。对于cdn异常回源,会根据If-Modified-Since和缓存生成时间比较,直接返回304.

 

13缓存失效风暴

防爬虫

日志分析(统计ipUAreferer

通过cookiejs去写keyvalue值在html和图片)

Referer非法

UA黑名单

IP黑名单

 

拦截95%

 

工具

1Oprofile

     http://www.cnblogs.com/bangerlee/archive/2012/08/30/2659435.html

2apache性能测试工具ab

 

3 apache性能测试工具 Jmeter

 

4nginx-systemstap-tools栈调用的火焰图

一个性能检测和调试跟踪的工具,最开始是为了调试内核被做出来的,后来添加了用户态跟踪的功能。

  https://github.com/openresty/nginx-systemtap-toolkit

 

5stap++nginx性能调优)

  https://github.com/openresty/stapxx

6nginx-gdb-utilsnginx调试)

 

  https://github.com/openresty/nginx-gdb-utils

 

作者:

王向维

 

 

 


 

 

 

 

你可能感兴趣的:(高并发,高可用架构,上亿请求,百万并发,毫秒级响应)