URL到底应该有多长?我为什么要提这个问题呢?有许多优化指南里都写着:要尽量减小COOKIE、缩短URL,以及尽可能地使用GET请求等等,以便优化WEB页面的请求和装载。但是,这种所谓“尽可能”、“尽量”只是定性的描述,定量的来看,要缩短到多少个字节才算少呢?
就以我们某次首页的改版中,通过http analyzers我看到几个有趣的.js文件的URL,是这样的:
[xhtml]view plaincopy注意最后一条。嗯,不要惊讶,的确是这样长的URL,确切的长度是443bytes。但这是长了呢?还是不算长呢?
要知道以IE为例,可以处理的URL长度为2048 bytes,也就是说,反正~~无论如何,IE是能处理的。其实,一般浏览器也没问题,所以,“正确性”是没问题。所以,接下来我们要说的是效率。
一、TCP/IP协议中的包头问题
在TCP/IP网络中,底层协议是一回事,应用层协议又是一回事。所以作为应用层协议的HTTP,自身可以传输多大的内容,以及如何传输(例如HTTP包一般以48K为界限,超过48K时会出现应用层的分包,即所谓的multipart)这些都是由应用层来约定的。而在底层协议中,链路层与传输层对“传多大的包”有各自的约定。简单的说,传输层约定了IP数据包的MSS(最大分段尺寸),链路层约定了MTU(最大传输单元)。如果一个IP数据包的大小超过MTU(即MSS+TCP报头+IP报头>MTU),则在链路层会将IP数据包拆成多个信息包传输。
MSS与不同的传输环境相关,有两个推荐值。一般来说, - 目标地址非本地地址(与源地址在不同一个网段)时,MSS默认值通常是536;否则, - MSS默认值通常为1460。 MTU与网络环境相关,也有两个推荐值。一般来说, - 串口为576字节; - 以太网为1500字节。
MTU/MSS的两种推荐值中都有40个字节的差异,即是(TCP报头+IP报头)的一般值,该值以120 bytes为上限(20+20字节的IP/TCP头部;40+40字节IP/TCP可选头部)。所以在复杂的网络环境中,应用层的网络协议可用的单个数据包的大小,最佳值应小于536-80=456字节,尽量限制在1460-80 = 1380字节以内。这样的限制,是综合考虑传输层与链路层协议的结果。不过一些常见的建议中,也会用536/1460这两个值,与这里的讨论没有太本质的差异。我只是强调,如果我们要一个“足够优化的请求”,那么极限值应该是多少?
二、HTTP协议中的包头问题
那么,现在来到HTTP这个应用层协议。一个HTTP请求由头部与数据区构成,对于HTTP GET请求来说,可以只有头部而没有数据区,原因是HTTP头部的内容如下(头部需要以2个连续回车换行结束):
[xhtml]view plaincopy这里的GET (...)可以跟着一个完整的GET请求的URL,而GET请求的参数也都放在这个URL上,因此可以不需要有单独的数据区。在上述的这个HTTP请求中,某些特定的客户端可能会多几个或少几个http head field,但通常字段都会比较短。我们仅以这个例子来说明,那么这个“缺省的(不完整的)HTTP头”用掉了多少字节呢?
答案是184字节。不过还需要强调,Referer与当前正在浏览的网址直接相关,例如当前正在浏览的页面是500字节长的URL,那么当前网页上的超链接点击时Referer字段都会填上这个500字节的URL,网页中过长的URL会使得点击超链接时消耗更多的传输,这里也是一例了。
那么不讨论Referer字段的影响,仅以上述为例,我们能用的最佳值,就只剩下了456-184=272字节了。这272字节会有三个地方使用,就是上面标为(...)的三个地方:GET、User-Agent和Cookie。User-Agent这个字段与浏览器相关,不同的浏览器以及该浏览器处理不同的操作系统环境时,都会出现不同。在JS以及服务器上的统计软件中,也常常使用这个字段来判断浏览器环境,例如OS、版本等。这个字段的值有时候会比较长,以我当前的机器为例,该值为: --------- Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; QQWubi 108; EmbeddedWB 14.52 from:http://www.bsalsa.com/EmbeddedWB 14.52; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 1.1.4322; .NET CLR 3.5.21022; .NET4.0C; .NET4.0E) --------- 占用了274字节。也就是说,事实上理想环境下的使用456字节就已经不够用了。按此前讨论的,我们可以退而求其次: - 使用536字节的边界值,即不考虑80字节的tcp/ip可选头部。
此外,需要强调的是User-Agent长度的可变性,例如上面的“EmbeddedWB……”等64字节在一般的电脑中可能就没有,这是一个第三方组件。同样的,也可能因为其它的浏览器环境(例如傲游)导致这个字段更长。基于这个事实,我仍以本例中的这一特殊情况来做分析。
以536字节为例,我们事实上还有78字节可用,因此在这里我们将优化的第一等级设为:70字节。建议公司可以根据服务器端收集的数据取一个平衡值。
三、COOKIE耗用可以降到0
现在,Cookie是消耗最大的地方,以我当前的机器为例,该值有几种情况(对于不同的协议与域,是不一样的):
(1) 对于首页http://www.alipay.net/,值有49字节: ali_apache_id=12.1.11.70.1275978936200.5; lastpg=
(2) 对于http://*.alipay.net/,值有171字节: ali_apache_id=12.1.11.70.1275978936200.5; ali_apache_sid=12.1.46.46.128998714836.4|1289988948; ALIPAYJsessionID=bYWcn4Wq0Z5FBCoHzfpn2f1XxDAmBepay; ali_apache_tracktmp=uid=
(3) 对于https://static.alipay.net/,值有307字节: cna=AKaaAhYBhU0BAeMdAHlnHNcd; ali_apache_id=169.17.198.19.1272623861747.7; payMethod=directPay; _tb_order=38016166656317; defaultBank=ICBC; __utma=22931947.260433774.1277279158.1277279158.1282287558.2; __utmz=22931947.1282287558.2.2.utmcsr=life.alipay.net|utmccn=(referral)|utmcmd=referral|utmcct=/index.php
(4) 对于http(s)://img.alipay.net/,值有379字节: apay_id=159588238.127262386236866.128979461890689.1289969142342368.137; cna=AKaaAhYBhU0BAeMdAHlnHNcd; ali_apache_id=169.17.198.19.1272623861747.7; payMethod=directPay; _tb_order=38016166656317; defaultBank=ICBC; __utma=22931947.260433774.1277279158.1277279158.1282287558.2; __utmz=22931947.1282287558.2.2.utmcsr=life.alipay.net|utmccn=(referral)|utmcmd=referral|utmcct=/index.php
(5) 其它情况。
为什么在2、3、4情况下出现了cookie使用的暴增呢?事实上,3、4两种情况虽然略有差异,但产生问题的根源与情况2是完全一致的。所以后文仅以情况2为例。跟踪其http request过程可知: - 请求首页时,服务器端返回了四个set-cookie应答。
这四个应答(http response head)如下: --------
Set-Cookie:ali_apache_sid=10.2.46.46.128998714836.4|1289988948; path=/; domain=.alipay.net Set-Cookie:JSESSIONID=A8CE523AEA03E2C990D6796D6BAEC81E; Path=/ Set-Cookie:ALIPAYJSESSIONID=bYWcn4Wq0Z5FBCoHzfpn2f1XxDAmBepay; Domain=.alipay.net; Path=/ Set-Cookie:ali_apache_tracktmp=uid=; Domain=.alipay.net; Path=/
--------
所以在此后的所有http请求中,都将使用如前例(3)中的171字节的cookie。但是,显然的,至少有以下几种情况这些cookie是无意义的: - 如果访问的是重定向页面,包括返回Status Code:302的重定向,以及html页面中使用http-meta的重定向; - 如果访问的页面是被缓存的,例如返回Status Code:304的“Not Modified”; - 如果访问的页面是静态的、无需识别cookie的,例如static.alipay.net中的.img、.js和.CSS文件等。
显然,我们在img、static中的图片或其它静态资源是可以被缓存的,而且无论是缓存还是第一次存取,cookie值都完全没有意义。对于静态页面(.html)来说,如果我们不是要通过http server来统计分析静态页面的访问情况,那么这些cookie也是不需要的。所以,对于这些资源、内容,我们应该强调的使这些cookie不被发送,或尽量少的使用(对于部分的.html静态页,我们可能仅仅需要用于分析用户访问链的session id)。
优化cookie的方式很简单:将这些静态资源部署在不以.alipay.net为domain的服务器/组里,或使用其它的独立域名。这种情况下,对于特定的——当然也是最大量的一部分——资源,COOKIE耗用可以降到0。
四、缩短url
总算来到我们的正题:URL可以有多长?通过前面的分析,我们仍然还有70字书可以用,即使在特定条件下,我们需要给一些页面访问留下track数据(例如session),那么我们仍然有40~50个字节可以用。不过,仅此而已,我们离本文最开始提到的443 bytes仍然有相当相当长的距离。
但我们真的需要这么长的URL吗?
答案是不需要,我们完全可以缩短URL。例如前面的例子,我们原始的URL的get部分是:
[xhtml]view plaincopy新闻热点
疑难解答