京东三级列表页持续架构优化—Golang+Lua(OpenResty)最佳实践
分类列表入口
分类列表入口,可以通过京东首页首屏左侧导航进入,是用户购买商品的几大入口之一。
分类列表,展示各个分类的商品,有综合排序、价格排序、销量排序、上架时间排序、图书还有出版时间排序。可以按照品牌、价格和各种扩展属性筛选出想要的商品。下图以空调列表为例。
分类列表特点
分类多,全站大概几千个分类;
商品多,每个分类商品多,有的分类达上千万的商品;
需求多样化,不同分类需求不一样,例如大家电、图书需求各不一样;
请求量大,实时性要求高。
旧架构
旧架构,前端是用nodejs做模板渲染,后端服务是调用搜索接口。旧架构缺点:
响应时间比较长;
因为是搜索返回的数据,数据二次加工不方便。
升级新架构
* 新架构设计目标
分布式,数据可以做多个分片,服务各层可以做到水平扩容;
高可用,双机房双活部署;
响应迅速;
数据闭环,线上服务主要数据不依赖于外部API;
运维便捷,方便切换集群,方便分类管理配置;
数据提升,通过优化排序算法,提升GMV、订单转化率、客单价等。
* 新架构
新架构功能模块如上图所示:
页面渲染:采用OpenResty(Nginx+Lua)来作模板渲染,方便页面逻辑的调整;
业务处理:采用golang,所有的筛选、过滤逻辑都是在这一层处理的;
数据异构:页面渲染需要相关的数据、过滤筛选需要的数据,都是通过异构过来的;
消息处理:通过接入MQ消息,可以实时处理商品上下架、库存更新、价格修改等消息;
质量分计算:通过大数据平台计算商品质量分,为综合排序提供依据;
配置管理中心:负责后台调度、分类配置等。
新架构线上流程如下图所示
新架构离线数据流如下图所示
其中:
数据集市,使用的是京东的大数据平台;
JSS,是京东自研分布式文件存储系统;
JIMDB,是京东自研KV存储系统,可当分布式Redis使用。
详解各个模块
* 质量分计算
由于每个分类的商品非常多,个别分类达千万量级的SKU,而用户浏览的SKU有限,我们需要将用户最可能买商品排在前面;为每个分类的所有sku进行质量分计算,涉及到几十个指标(包括销量、评价、浏览、转化率等);根据质量分的高低进行排序;由于涉及数据量很大,所有计算都在大数据平台完成;将计算结果推送到JSS。
由于还有一些特殊规则,例如品牌穿插、店铺穿插、特殊排序等,这些规则的实现是通过worker实现,读取jss,并进行特殊规则处理。将处理后的数据推送到MYSQL。
* 异构服务
异构服务主要是异构过滤和展示需要的商品数据;调用外部各个接口,形成一张商品宽表。如下图所示:
* 业务处理子系统
上图展示了列表各种筛选逻辑,排序逻辑。
业务处理子系统提供前端所需要的所有过滤筛选接口,以及展示数据。该系统采用golang开发,所有筛选数据都存在内存中,提高检索速度;展示的数据都放在jimdb中,目的减少占用内存大小,缩短golang的GC时间。下图展示了内存中存储的数据。
* 消息处理系统
该系统接收处理相关消息(商品变更,上下架,价格变更,库存变更),并实时更新到线上,如下图所示:
* 页面展示子系统
页面展示子系统,采用Nginx+Lua实现,负责模板的渲染,如下图所示。
为了提高页面的渲染速度,有一部分页面采用异步渲染,例如:页面小图聚合的可以让js渲染小图;超过5个的扩展属性,让js异步渲染。页面需要的价格数据、库存数据、广告数据,采用异步加载;保证这些数据的实时性。
页面渲染优化:
HTML文档精简,越简单渲染越快,性能越好;例如:页面小图聚合的可以让js渲染小图;超过5个的扩展属性,让js 异步渲染;
懒加载数据,例如:滚屏加载图片和页尾;
资源加载排序,对每种资源定优先级,对必需的资源优先加载,而低优先级的请求保存在队列中延时加载或等必需资源加载完再加载。例如:搜索推荐热词、顶部三个热卖商品接口、价格优先加载。对于库存、促销信息、广告词、预售商品、店铺信息等,延后加载; 对于点击流,广告统计数据则延时两秒再加载;
页面更多优化参考:《京东三级列表页持续架构优化—前端优化实践》。
Golang+Lua(OpenResty)的应用
* Golang–遇到的坑
JSON的序列化性能低下:Golang内置的encoding/json、encoding/gob,采用ffjson;
GC问题:减少内存对象。减少对象申请,两个作用:减少内存使用,减少内存碎片;
字符串拼接:尽量使用byte数组,不要用String,由于String会创建新对象;
Go占用OS内存释放慢:执行:debug.freeOSMemory();
Goroutine闪退:goroutine闪退,导致应用进程闪退,异常捕获;
并发处理map:必须加读写锁(sync.RWMutex)。
* 选择Lua(OpenResty)
Lua:轻量级、协程、嵌入式、开发效率高;
OpenResty:OpenResty将Nginx核心、LuaJIT、许多有用的Lua库和Nginx第三方模块打包在一起的web应用开发框架。
** 模板渲染
使用的模板引擎https://github.com/bungle/lua-resty-template。Nginx配置如下所示。
模板如下所示。
** 缓存
缓存:
为后端服务异常提供托底数据;
当流量太大时,可以开启缓存,减少后端服务压力。
缓存流程:
解析url,对url做hash,得到相应的key,从后端服务获取数据,如果数据完整,则渲染模版,将对应的数据放入对应的缓存,并将key放入keycache,并设置缓存时间;
页面缓存是永不过期的,当key过期时,主动替换掉;
为什么分为两类缓存:firstpage cache只缓存每个分类首页的数据,这样可以缓存全部分类的首页,保证所有分类都有托底数据。Otherpage cache 缓存除首页以外页面,这样保证热点数据都在缓存中。如果超过容量,通过lru淘汰;
为什么每类缓存多个分片:因为lua_shared_dict存在自旋锁,单片读写压力大时,会有一定的瓶颈,因此采用多个分片,每个分片大小设置,根据具体缓存数据来定;
Firstpage和otherpage 是缓存在每台nginx服务器上,缓存的内容有限;
Redis缓存,可以集中缓存,能够缓存更多的数据;
** 异常处理
异常处理分为两层托底,保证每层报错,均可对异常进行处理,无5xx等错误,提高用户体验,第一层托底,展示各个分类首页的缓存;第二层托底,跳转京东首页。
Lua执行问题,通过nginx配置error_page,进入异常处理。接口响应问题,通过ngx.exec内部跳转,进入异常处理。
注:error_page默认只匹配一次,匹配多次需配置recursive_error_pageson;
ngx.exec为内部跳转,类似于流水线,数据流动方向单一,无额外http请求。
新版性能
* 页面渲染性能
页面响应时间:模板渲染+业务筛选接口(go),平均在30ms左右,tp99在80ms以内,提高6倍以上;页面渲染(NGINX+LUA)TPS,在并发100时,16核单机在3500笔/秒,提高10倍左右。
* 业务筛选接口(GO)性能
业务筛选接口(GO):平均在10ms以内,tp99在50ms左右,响应时间提高6倍以上。
来源:http://mp.weixin.qq.com/s?__biz=MzIwODA4NjMwNA==&mid=2652898074&idx=1&sn=d9770ca7b5f5707b041cb1568d8a19a4&chksm=8cdcd755bbab5e43d52d938644e0b754545c84d718eaafe2330ea2f6778c0b416bc5836ad2b3&mpshare=1&scene=23&srcid=0728kGwKgw3uhOJxIm3Z1m5x#rd
京东三级列表页持续架构优化—Golang+Lua(OpenResty)最佳实践相关推荐
- 京东三级列表页持续架构优化—前端优化实践
在持续开发一个核心系统过程中,除了满足业务需求外,还应该考虑系统未来的架构,追求极致的系统的可用性.高性能和稳定性.这个过程是一个长期积累和重构的过程. 每个应用都要满足自己特定的需求,因为商业条件. ...
- 京东三级列表页持续架构优化
本文作者,王向维,京东商城三级列表页架构师.工作期间,完成了京东三级列表页由Node.js版本到Nginx+Lua版本的变迁,并针对三级列表页前端即服务器端做了大量的优化工作. 京东三级列表页 三级列 ...
- 京东前端:三级列表页持续架构优化
为什么80%的码农都做不了架构师?>>> 王向维,京东商城三级列表页架构师.工作期间,完成了京东三级列表页由Node.js版本到Nginx+Lua版本的变迁,并针对三级列表页前 ...
- android自定义视频列表,Android仿京东天猫列表页播视频看这一篇就足够了
阅读本文解决什么问题? 解决android 滑动列表页自动播视频中的一些技术难点.助力更好的实现类似需求.不涉及到播放器的具体编解码技术,因为各家用的播放器可能都不一样(其实是我不会~) 何时播视频最 ...
- dedecms 栏目列表页链接如何优化
这篇文章主要介绍了dedecms 栏目列表页链接如何优化,具有一定借鉴价值,需要的朋友可以参考下.希望大家阅读完这篇文章后大有收获.下面让小编带着大家一起了解一下. dedecms 栏目列表页链接怎 ...
- 新手站长说说之织梦DedeCMS列表页标题SEO优化
织梦DedeCMS列表页标题SEO优化 织梦无忧 织梦技巧 摘要: 织梦DedeCMS栏目列表的标题是重复的,在谷歌站长工具,就会有相关的提示:重复的标题标记,说明这个对搜索引擎是很不友好的.当然,这 ...
- ySQL性能优化的21个最佳实践 和 mysql使用索引
MySQL性能优化的21个最佳实践 和 mysql使用索引 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我 ...
- 搜索引擎优化网页设计:最佳实践
作为一名网页设计师.网页的设计是我们一个最直观的辨认.我们如今的生活依赖于网络,依赖于这个高速让我们互知和沟通的工 具.它早已不不过一个静态的页面,而是一个有思想有文化无国界的一个内容涵盖量丰富的还有 ...
- App 后台架构设计方案 设计思想与最佳实践
CSDN 2016博客之星评选结果公布 [系列直播]零基础学习微信小程序! "我的2016"主题征文活动 博客的神秘功能 App 后台架构设计方案 ...
最新文章
- JAVA Roman to Integer 罗马数转换为int型方法
- Hooks中的useState
- RDS还原数据库时报错:ERROR 1227 (42000) at line 78664
- SQL 数据库操作类
- Google开源项目风格指南-Python(C++)风格指南
- 电影数据集TMDB数据分析练习
- 不到100行代码制作各种证件照
- TCP之Delay ACK在Linux和Windows上实现的异同-Linux的自适应ACK
- NYOJ-14-会议安排问题
- 采集今日头条数据 python 爬虫 API接口
- 大数据分析技术有哪些
- 在cmd中怎么进入mysql?
- p2p传输实时视频流
- 【无标题】VisualC++逆序存放
- adress标签的使用
- Hadoop多个文件单词计数
- 【Android -- 写作工具】Markdown 图片
- 临时起搏器测试----概念梳理
- Java JDK 动态代理实现和代码分析
- 186、项目超过255个摄像机怎么分配IP地址
热门文章
- VMware虚拟机启动后出现黑屏,不能显示界面,无论安装的是ubuntu、kali还是centos
- Linux服务器开发之:stat(),fstat(),lstat()详细介绍+案例演示
- typedef,结构体,共用体,联合体
- JavaGUI中的JComboBox的处理
- Android中Activity和task,活动亲和力,启动模式,活动状态以及生命周期,激活钝化
- 数据库工程开发秘籍之TSQL 存储过程user stored procedure的概念与案例实战
- 窗口分析函数_1_生成不重复排名序号
- 二、在VMware中搭建PHP集成环境(lamp/lnmp/lanmp)
- Wintel物联网平台-Windows IoT新手入门指南
- Kruskal Prim模板