从京东主页里寻找技术的真相

一、编程语言的探究

业内人士都知道,京东网的服务端最开始是用.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时,页面只显示给用户重要的活动和商品信息,节省了用户大量流量,缺点是产品汪汪汪。。。美术。。。程序。。。