刚刚经过“618购物节”的挑战,京东(此文简称JD)首次向大众公布了618的交易额,那就是1199亿元。什么?才1199亿,阿里系小伙伴肯定在后面偷笑,搞了18天的大促,还不如淘宝“双11”一天的销售额。不过没关系,这次强东哥非常满意,因为“618”这个日子,这个让全国网民们沸腾的节日,已经被京东写进历史,这足以证明强东哥这一年的强势回归是有多么重要。
在这背后,支撑着京东网稳定且高并发的服务着千万级买家购物过程的除了服务器和网络外,当然还有在办公室里默默加班的产品汪、运营喵、程序猿和市场鸡们。。。不然强东哥在办公楼里白白给你们造那么多员工宿舍干嘛。。。
玩笑归玩笑,我一转身,也默默的加入到了程序猿的行列,两行清泪。。。泪里都是对强东哥的崇拜之情:)
说了这么多,其实本文我想说的是京东网首页的事情。京东的网站这么多,产品业务线也这么多,技术架构和选型也是五花八门,任何人都不可能在一篇文章甚至一本书里说得清楚,所以,就只扒一扒首页。
一、编程语言的探究
业内人士都知道,京东网的服务端最开始是用.Net技术起家的,后来技术管理层的变动,引入了PHP、Java和Go。现阶段,Java已然成为京东里的当家花旦,大批的阿里系Java大牛们不断地投入到强东哥的“怀抱”。不过当公司的业务不断扩大的同时,老的业务依然能稳定运行,如果此时贸然把.Net技术全部换成Java,其实是存在非常大的风险的,所以,以和为贵。为了找出京东首页的背后的语言,我作了如下分析:
扩展名分析法
我分别在官网URL后面里添加了几大语言的扩展名进行尝试。
https://www.jd.com/index.htm
https://www.jd.com/index.html
https://www.jd.com/index.asp
https://www.jd.com/index.aspx
https://www.jd.com/index.php
https://www.jd.com/index.jsp
这几个地址居然都可以访问,且返回的页面是一模一样的!这说明什么,这说明Web服务器被做了手脚,有人故意把多种文件扩展名对应的MIME类型映射到了同一种后台语言上,且不说京东这么大的互联网平台,首页应该用纯静态的htm或者html页面才好,而我们应该更关心的是这背后的真正用意是什么?我随意点击了几个链接,发现打开的URL有的是php的页面,有的是aspx的页面,有些是html页面。为什么后缀不统一?考虑了一下,非常明了,为了防止死链接,不管京东以后怎么更改后台语言,只要路径不变,后缀随便变,链接都是有效的。
当然知道了用意之后,我们还是看不出它后面的语言是啥,就让我们继续看。
Web服务器类型分析法
从主页返回的头部信息(Header)中,我们看到了JDWS/2.0
。
字面意思,这是JD自己研发的Web服务器,实际上,应该是对Nginx或者阿里的Tengine做的修改版。从这个信息我们仍然不能猜出幕后的语言。
Cookie名称分析法
在Cookie列表里,没有发现任何ASP.NET_SessionId
项,说明主页肯定不是.Net后台,当然,也不可能是asp这么老的技术。
有排除也好,不过最终我们的目的还是没有达到,那就把悬念继续保留。
二、优化页面加载技术
首先JD主页采用了HTTPS协议,对于加载速度来说是个减分项,比起3次握手的HTTP来说,慢得不是一点两点。但是考虑JD此举是对广大用户负责,出于对用户数据的保护,此处给出省略号。。。
CDN加速
互联网发展至今,不管是大公司还是小公司,不管是自建还是租用,都会使用CDN技术。网站、游戏、视频直播等,CDN必是标配。而JD是属于财大气粗类型,有自己的CDN,从以下Coding便可以看出:
<link rel="dns-prefetch" href="//static.360buyimg.com" />
<link rel="dns-prefetch" href="//misc.360buyimg.com" />
<link rel="dns-prefetch" href="//img10.360buyimg.com" />
<link rel="dns-prefetch" href="//img11.360buyimg.com" />
<link rel="dns-prefetch" href="//img12.360buyimg.com" />
<link rel="dns-prefetch" href="//img13.360buyimg.com" />
<link rel="dns-prefetch" href="//img14.360buyimg.com" />
<link rel="dns-prefetch" href="//img30.360buyimg.com" />
<link rel="dns-prefetch" href="//f.3.cn" />
<link rel="dns-prefetch" href="//d.jd.com" />
<link rel="dns-prefetch" href="//ai.jd.com" />
<link rel="dns-prefetch" href="//ch.jd.com" />
ping一下上面的各个域名,便可发现藏在后面的www.jdcdn.com
和*.gslb.qianxun.com
是JD全站使用的CDN域名,都是自家研发。
限制浏览器对同一域名的并发请求数
不同的浏览器对同域名的最高并发请求数不太一样,在HTTP/1.1标准中,以4到6个为主,所以我们来看看JD的请求情况(不考虑异步加载的文件):
很明显,JD使用的域名并不多,虽然网页对大多数商品图片使用了异步加载的lazyload
技术,但是还是不能掩盖他360buyimg.com
域名被过度使用的真相。这里请问JD大拿们为什么要给360buyimg.com
加这么多二级域名,难道你们不知道二级或N级域名对于浏览器并发限制的优化是无效的么?
值得肯定的是,JD基本把所有的CSS样式代码全部打印在主页里,减少了不少请求数。
还有这一句:
<script src="//misc.360buyimg.com/??/jdf/lib/jquery-1.6.4.js,/jdf/2.0.0/ui/ui/1.0.0/ui.js,/mtd/pc/index/2.0.0/gb/lib.min.js,/mtd/pc/base/1.0.0/base.js,/mtd/pc/common/js/o2_ua.js,/mtd/pc/index/2.0.0/home/index.min.js,/mtd/pc/index/2.0.0/home/init.min.js"></script>
又是大阿里开发的Nginx模块nginx_concat_module
的功劳。此模块非常有用,可以把N个js、css或者html文件合并唯一,大大减少外部资源并发请求数。
压缩文本
省略Html里的外部引用和链接URL的协议头,方便网站同时使用HTTP、HTTPS两种协议。例子如下:
<a target="_blank" href="//miaosha.jd.com/">秒杀</a>
大部分的css和js已经被混淆压缩,但是仍有少部分css样式代码还是按原始代码的方式打印出来。最大的问题是,整个Html代码没有经过任何压缩,难道是为了让我研究得更方便?
压缩图片
JD将大部分的商品图片格式改成了webp
,文件的大小大幅度的减小。
三、数据采集
任何公司里都少不了对自己产品的各项功能获取的指标的需求,运维的APM系统,市场的流量来路统计系统,运营的用户画像系统等等,其系统的规模绝对不比面向用户而消耗的服务器少。这里我大概留意到了几个指标,下面说说。
页面打印时间
JD主页里,每打印完一个Html块后,就会获取一个当前用户时间,等到页面完全打印完后,页面会将所有这些时间数据一并发给APM接口,APM获取到每个块的显示完成时间后,便可以对每一个Html块的性能作一个评估和后期的优化。获取时间的代码段如下:
window['_REPORT_']['START'] = new Date();
window['_REPORT_']['CSS'] = new Date();
window['_REPORT_']['FS'] = new Date();
window['_REPORT_']['JS'] = new Date();
window['_REPORT_']['DOM'] = new Date();
标签点击事件
在Html里,看到太多的div
或a
里使用了clstag
这个自定义标签,如下:
<li clstag="h|keycount|2016|01e">...</li>
<a clstag="h|keycount|2016|11a">...</a>
<input clstag="h|keycount|2016|03a" />
明显是对页面中各个标签的点击事件的记录,且每一个标签由4个值组成,组合后的值是完全唯一的。下面是对clstag
中各个数据的用途分析:
- Section 1: 代表页面的id,这里
h
说明是主页 - Section 2: 代表统计事件,这里
keycount
属于点击事件 - Section 3: 代表页面中的模块id,主页里貌似都使用
2016
,应该代表主页的设计版本是2016年的 - Section 4: 代表模块内的元素id,每个模块里的不同元素区分,名字可以后台设置,但是同一模块里元素id不能重复
模块加载事件
JD专门使用//mercury.jd.com/log.gif
这个地址来记录页面中模块自动加载的事件。记录中包含用户浏览器信息、模块的信息等。信息太多,不能全部了解清楚,感兴趣的同学可以自行研究。
还有很多其他的数据也被提交到不同的后台BI系统,具体也可自行研究。
四、浏览器数据存储
现阶段,大部分用户数据最多还是存在Cookies里,一是对浏览器兼容最好,而且技术成熟,前后端都方便操作。但是在性能方面,由于每次页面请求,都会携带Cookies数据,所以也容易造成多余的数据传输,浪费带宽。而Cookies的另一个缺点,就是存储的数据量不大,如果要存储大量数据时,我们就要借助其他存储技术。
Cookies
里面存储了用户信息数据和大部分BI需要的统计数据,这里也无法作深究。
Local Storage
里面存储了非常多的用户请求返回数据,包含页面里显示的商品代码。这样的做法在于,如果你刷新页面或者下次访问首页,异步加载的Html会首先从Local Storage
里取,如果不存在,再到服务器上加载,起到了一个页面模块缓存的功能。
五、SEO优化
整站涉及到非常多的SEO,包含且不局限于以下几点:
- 使用大量二级域名替代功能模块路径。比如用
miaosha.jd.com
替换www.jd.com/miaosha
。多站点的好处很多,不外呼是可以分而治之,不同部门负责不同的功能点,还有就是不同站点的后台语言可以都不相同。 - 尽量减少URL路径的深度与长度。
//item.jd.com/1370329.html
一个根目录的地址就能查看到商品详情,方便搜索引擎对商品的搜索,提高搜索权重。还有一个优点就是Web服务器记录请求日志时,由于URL长度变短,日志文件也会比长URL的日志文件小很多,节省磁盘空间。 -
Keywords
和Description
必不可少。
六、设计相关
页面中大量使用了图标字体技术,可以根据不同浏览器加载不同的字体格式。这里第三次感谢阿里,Iconfont平台造福万千!
七、对移动触屏设备的支持
当我使用手机访问JD首页时,页面地址自动跳转到https://m.jd.com
,说明JD没有使用流行的响应式布局,而是分电脑版和触屏版(WAP)分别设计首页。好处是用户如果使用手机访问JD时,页面只显示给用户重要的活动和商品信息,节省了用户大量流量,缺点是产品汪汪汪。。。美术。。。程序。。。
研究的不是很深入,但是大可看出京东里大多数技术人都来自阿里且使用阿里的技术最多。另一方面可以反映出,京东对开源技术的贡献并不是非常上心,还是一个以业务为主的年轻小伙(毕竟我们强东哥还是非常年轻的)。等到他真正追赶上老大哥阿里的脚步时,说不定员工宿舍更多了:)
最后,在这提前祝贺强东哥,JD市值即将超过百度,即将产生新的互联网CP:JAT!!! 一个新的中国互联网时代到来了。