首先,页面的加载速度跟HTTP连接方式是息息相关的。HTTP 1.0是Browser和Server三次握手建立连接发送数据包。HTTP 1.1对这种情况有了改进,在HTTP 1.1中有Persistent Connection的概念,Server端不会马上关闭连接,这样可以减少连接数,但是维护连接需要消耗服务器资源。
在HTTP请求方面,IE和Firefox也有比较大的差另。IE7对ajax请求,是发送两次tcp包。第一个是HTTP Header,第二个是xml data。两次tcp发包之间,Server一个ACK确认后才发xml data。 IE7上发送ajax请求会继续使用浏览器已经建立的tcp链接,而 IE6发送ajax请求会重新建立新的TCP链接(三次握手)。Firefox中xml和HTTP Header的最后一个TCP包是一起发出去没有延迟的。
再次页面加载速度受浏览器的并发Pipeling影响;HTTP协议1.1版本中对浏览器并发请求连接数的2个限制。也就是说如果遵循HTTP 1.1协议,默认状态下,每个主机名只允许同时执行2次请求。当并发请求数大于2个的时候,其它的会处于等待状态,这种情况会影响图片的加载和ajax请求。那么事实真的是这样吗;如果是这样,那又如何优化这种情况呢?
我本机装的是IE8,打开注册表[HKEY_CURRRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings],这里可以看到MaxConnectionsPerServer和MaxConnectionsPer1_0Server都是10;而IE6、IE7都是2。而Firefox 3.6.12中,network.http.max-connections是30、network.http.max-persistent-connections-per-server是6。这两个浏览器都没有遵循HTTP 1.1协议规定的2个。
想要快速的知道你的浏览器支持多少个并发请求,可以访问这个页面:http://developer.oncecode.com/comet/ 进行测试。默认情况下,IE6/IE7是2个,IE8应该是10个,Firefox 3.6.12和Chrome都是6个。
我们分析新浪微博,发现新浪使用了tp[1-4].sinaimg.cn不同的域名,从tp1到tp4的图片都是相同的。将图片随机分布到这四个域名来加载,就可以加快图片的加载速度。这样的方式还有一个好处,因为sinaimg.cn不同于sina.com.cn,sina.com.cn下的cookie就不会带到域服务器,也可可以一定程度上加快响应速度。
上面的方式解决了图片的加载,但是ajax是不可跨域的,也就是说在相同域名下依然受浏览器请求数的限制。一种做法是在页面中对实现ajax的Priority Queue,优先级高的请求先执行。但这种情况依然不能解决并发请求的限制,只是对页面的ajax请求顺序做了优化。
“赵劼”同学在《挣脱浏览器的束缚(6) – AJAX也跨域名》中解决了这个问题,通过iframe实现一个proxy,利用这种方式来突破浏览器并发Pipeling的限制。其实真的没有做不到,只有想不到。
虽然可以通过iframe嵌入proxy页面可以突破浏览器并发Pipeling的限制,但是在IE中,增加iframe页面并不能增加线程,window中所有 iframe 的 window 的内部的 Javascript 都是不并行的。如果一个 iframe.src 赋值后,Javascript 所在的线程应该会通知另一个线程(简称通讯线程)去向服务器发 HTTP 请求。通讯线程从服务器端接收了一个完整的 HTTP 包后,将把这个数据包交给负责显示的线程(中间环节可能有一个线程负责解析 html),显示线程(或解析线程)边显示边运行页面中的 Javascript,并不停的绘制屏幕。而在这个 HTTP 数据包处理过程中,并不会处理其他 iframe 的 window 的 setInterval 之类的事件。处理完一件事情后,才会在内部的 timer / timeout 队列中选择一个到期的开始运行。
也就是说,在IE的一个窗口或者Firefox的一个Tab内,Javascript是单线程运行的。如果要实现单个页面iframe中Javascript的同步必须使用setInterval。
还有一个很棒的参考资源:《Yahoo!关于网站优化的35条建议》。
在线浏览器并发测试工具:http://site-perf.com/