减少DNS查找能够缩短页面反应时间,但是所有网站资源都只用一个域名,从而把DNS查找减少到一个,也不是最好的办法。不仅仅因为减少的平行下载的可能,更因为Web Cache对带与不带cookie的请求和返回的处理不同。
我的网站域名是www.yining.org,有个页面(比如就这篇blog entry)带有一张图片,其src为:/img/camel.gif,那么它的URL就是:”http://www.yining.org/img/camel.gif”。如果这个页面设置了cookie(比如为了记录留言者的ID和网站地址等),cookie的作用域名自动为www.yining.org,那么每次访问该页的时候,因为URL的域名部是www.yining.org,那么浏览器都会带着cookie对该图片发起请求,即使一路上的web cache有www.yining.org/img/camel.gif的记录,也依然要到我的服务器(the origin server),而不是从中间的web cache返回 – 因为带cookie的请求都可能根据不同cookie的值而返回不同的response。
但是这对许多静态资源(图片, css, 和javascript)来说不是最理想的,因为不论cookie是什么,它们的response里都是同样的内容,对它们的请求没有必要每次都回到origin server。其次,因为不同web cache对带cookie的请求支持不同,即使有的cache能够缓存带cookie的response,但是1)不是大多数的cache都能做到这点,2)大多数的cache都缺省缓存不带cookie的response。因此最好的办法就是使用不同的域名把静态资源隔离开。虽然cookie的path属性也能做到这点,但是毕竟限制太多,不如使用专门的域名灵活。
所以应该尽量把所有静态的对象和动态页面的域名分开,更严谨地说,是把不需要读写客户端cookie的服务器资源与需要读写cookie的程序分开到不同的域名。比如我可以设置另一个域名static.yining.org,在引用该图片的<img>里的src属性改为”http://static.yining.org/img/camel.gif”,那么当访问首页的时候,浏览器就不会带着cookie(因为作用的域名现在不一样了),这样就能更好地利用web cache缓存和服务器的性能。我请教过一位曾经在NetAppliance(最大的web cache厂商)工作的同学,据他说根据经验,带和不带cookie之间的差别有可能是20%甚至更大。

雅虎的YSlow插件的规则之一:Rule 9 – Reduce DNS Lookups提到:
Reducing the number of unique hostnames has the potential to reduce the amount of parallel downloading that takes place in the page. Avoiding DNS lookups cuts response times, but reducing parallel downloads may increase response times. My guideline is to split these components across at least two but no more than four hostnames. This results in a good compromise between reducing DNS lookups and allowing a high degree of parallel downloads.
说说自己的理解:
首先,一个页面所需要访问的域名数量为n,那么就需要n次DNS查找,而DNS查找通常是blocking call,就是说在得到结果之后才能继续,所以越多的DNS查找,反应速度就越慢;
其次,并行下载(parallel downloading)由两个因素决定:到服务器的连接数量,以及每个连接内部的流水线请求数量。
一个页面里到服务器的连接数量由两个因素决定:
- 页面所需访问的域名数量,和
- 浏览器所允许的最多连接数
后者在Mozilla/Firefox中还由浏览器所允许最多连接数(network.http.max-connections,缺省为24),和每个服务器所允许的最大连接数(network.http.max-connections-per-server,缺省为8)决定。如果max-connection-per-server是m,那么一个需要访问n个不同域名的主机的页面,最多可以有n*m个连接 - 前提是n*m小于max-connections的值;
每个连接内部的流水线请求(pipelined requests)的数量也是浏览器的参数(Firefox上由network.http.pipelining来设置,缺省为4),前提是服务器支持persistent connection(比如在Apache设置KeepAlive为On)。之前的例子就不需要那么多的连接了(对服务器和浏览器来说,一个连接里多个流水线请求能够比多个并行连接更好些),假设pipelining的值为p,那么就可以只使用n*m/p个连接了。(BTW,对Firefox做优化的一些插件其实就是对上面的几个设置做调整)
所以减少页面内不同hostname的数量不一定会减少并行下载的数量,也要看所需要的请求(css, javascript, 图片等)的数量,因此YSlow的解释说是potentially。
Remy Sharp wrote a web service to look up HTML Entity Character. The service “allows you to quickly find the entity based on how it looks”. There is also an OpenSearch plugin and MacOS Dashboard widget. Kudos to Remy!
I figured a Firefox extension clone would be handy, and it wouldn’t be too difficult to make one, thus:

This extenion is simple: a GUI wraps and calls the Javascript code Remy wrote (with a little modifiication, basically renaming global variables to make them unique) and then displays the result. The code is licensed under Creative Commons by-sa 2.5, same as Remy’s code.
It should work on Firefox from version 1.5 and above (have tested on 3.0aPre7 too), also on Netscape Navigator and Flock, let me know if you have any problem using it.
To try out, go to the extension’s home page and click install (it’s currently hosted on my server, so you have to let Firefox allow download and install extension from my server).
I could have made the extension remotely invoke Remy’s web service, parse the return html and present the result, but it might not be a good option, because:
- I need it work while off-line (too much distraction online);
- HTML entities character set doesn’t change that often, what’s the last addition? € maybe?
- Overhead from network traffic and CPU cycles parsing html;
- Not really a reason though: I could later make use of the new Online and Offline Events and provide user the options;
Update (09/09/2008):
You should be able to have it run on Firefox 3.0.1 and above.
雅虎今天推出了YSlow插件(这名字不错:Why Slow? ),需要先装Firebug,YSlow其实是它的“插件”。YSlow从Firebug收集当前网页和该网页的访问信息后进行分析,如有必要则给出如何提高页面加载速度的建议,比如减少DNS查询,使用外部并压缩Javascript等。这些建议是根据13个提高网页速度的指导原则,其内容已经在Yahoo Developer Blog上系列连载了一段时间,最近更新速度快了很多几乎每天一篇(是为了配合YSlow的推出?)。除此外还有专门一本书:《High Performance Web Sites》,内容就是这个系列(多了一个关于Ajax的专题),应该有更深入的分析和解释(这本书是Rough Cut,所以有O’Reilly Safari帐号的可以先睹为快了)。
这个High Performance系列说明网站开发者(包括我自己)非常需要深入了解HTTP和HTML。对Java尤其尤其是J2EE程序员来说,不要只是build around the web, 而是build for the web。很多程序员(尤其是刚毕业的大学生)不在意HTTP的细节,从所谓的“企业级开发”的角度把HTTP请求仅仅当作作一种函数调用,导致能提高性能的所有HTTP的特性都被“抽象”掉了,也就不了解或者利用这些属性。比如,我常在面试的时候问:HTTP GET和POST的区别在哪里?大部分的回答只有参数大小和位置的不同。
YSlow上的指导原则里的内容还有些可以补充的(很多东西应该都放到那本书里去了吧),比如在High Performance Web Sites: Rule 13 – Configure ETags里,作者建议在Apache上把ETag关掉,实际上只需要告诉Apache不要用Inode信息生成ETag就可以。还有其他一些,回头写上来。这里,这里,和这里也有很多非常好的建议。
另外要注意的是,网页速度跟网站性能是不同的概念,网页在浏览器上加载得快,并不能保证网站的性能就好,虽然二者之间有密切的关联。
P.S. 关于网站的延展性(scalability)和速度(performance),O’Reilly已经出了两本,另一本是《Building Scalable Web Sites》,都是雅虎员工写的,在这要赞一下雅虎对Web开发社区的贡献。
昨晚下载了Apple最新的浏览器Safari的Windows版,试了一下,可能是习惯了Firefox,感觉一般,而且中文显示还有问题(也许是我没设置好)。但用是肯定会用的,因为现在不用专门找台Mac或者跑虚拟机来测试网页在Safari上的显示效果了,这算最大最直接的好处了,赞一下。
又搜索了解了一下,发现Safari:
-
像Firefox有扩展一样,有自己的plugin平台,PimpMySafar是专门收集和推广Safari plugins的网站;
-
像Firefox基于Gecko一样,基于开源的引擎Webkit,btw, Windows上也有个基于Webkit的开源的浏览器Swift(在中文显示上似乎比这Windows版的Safari还糟糕);
但是Safari有Firefox完全没有的优势:iPhone。据说iPhone上的开发将是Web application,而不是提供运行iPhone的MacOS的本地的SDK/API,如果真是这样(也许Jobs过几个月又会改主意),那么Apple的用意也很明白了:利用iPhone的Cool Factor(就像MacBook一样),吸引更多的开发者开发基于iPhone的Safari的plugin,让Safari成为一个平台(嘿,关于这方面针对Firefox我曾经写过类似的)。而这些plugins也会在MacOS和Windows上运行,从而建立起Mac之外Apple的更大的开发者社区和Safari生态圈,像曾经的微软一样,Embrace and Extend。
接下来会怎么样?
Safari的Plugin会像Firefox扩展一样甚至更容易开发么?会不会有软件能移植或者部分转换扩展到Plugin?Firefox的扩展界面是XUL,也就是XML,XML是可以(即使不容易)转换(通过XSLT)的……
业界的开放标准会因此得到推动么?iPhone肯定要存储地址簿和日历的,那么读取和存储页面上的Microformats比如hCard和hCalendar的plugin肯定会有的(如果不是已经集成在Safari之内)……
出版商如O’Reilly会出版Safari Hacks,Safari Cookbook,Safari For Firefox Developer,Manning出版Safari In Action?Apress出版Beginner/Professional Safari?;-)
当然,就算这个策略不成功,Apple也还有像微软提供Windows CEMobile的SDK一样提供iPhone SDK的选择。
如果不能在iPhone上开发,那花那么多钱买iPhone,跟作Apple的凯子有啥区别?:-P
UPDATE: 在O’Reilly Radar上看到这篇XULRunner for the iPhone,Marc Hedlund说:
I suspect that the real and right desire is to connect all of the capabilities of the iPhone to the Internet.
仅仅是Web页面是不能充分做到这点的,只有能够跟iPhone本地结合,才能做到这点,增加更多iPhone的价值,激发更多的想象力,这在Firefox上已经被扩展机制证明了。
So, people who make conferences: listen up. I think that there are lots of sysadmins and ops people who would go to a conference solely about web operations.
— John Allspaw
今年的网志年会已经开始筹备了,这一次,我们能不能做一个真正的有纯技术(开发,运行,维护等)话题和参加者的年会呢?
我个人想感兴趣的话题:
- 开发的平台,框架和工具,SCM的环境的选择;
- 网站性能优化;
- 技术团队的成长;
- 技术趋势(Atom, OpenID, REST, Microformats等)的演示;
- 好玩的新技术;
如果真的能够有完全让技术人员感兴趣和交流的演讲和讨论,相信年会的影响力和凝聚力会更大提高,而我也会争取让我们团队和认识的其他程序员一起去参加。
为了更方便阅读网页(“Improves readability”),有人专门针对Lifehacker.com(我每天必看的网站)页面写了个Greasemonkey用户脚本,把多余的页面元素删除掉(“Removes various elements from the Lifehacker site”)。
猜猜看Lifehacker的反应是什么?
It removes too many elements of the site’s design, but this custom Lifehacker user style is still a compliment. You like us enough to mod us!
稍微有点不满意(删除掉太多页面设计元素了),但这对Lifehacker.com还是一个认可,因为用户喜欢Lifehacker到了改装页面(mod的感觉没翻译出来)的地步。
所以:
- 如果有用户用user script改装你的页面,那这是一件好事情(你提供了他们不愿意放弃的内容),同时也是一件需要考虑的事情(页面设计也许太花哨或者色彩搭配不够好);
- 页面的mark up不能太复杂,否则user script不好写 ;)
- 页面的mark up不能经常变动,否则user script会失效;
这就让我想起几天前看到的一句话:
Your Markup is an API. With all the hype about APIs and mash-ups, it’s easy to forget that your HTML is also an API, and your users are experimenting with it right now.
— Matthew Magain
但页面设计和编写的重要性绝对不仅仅在为了考虑用户使用Greasemonkey user script(毕竟这样用户比例特别小),在结构化的数据的发布和读取上,尤其是microformats的推广更是证明了“页面是API”。下一个版本的Firefox,Firefox3.0,已经在考虑集成对microformats的支持,这里有一些Firefox3在支持microformats的用户界面设计模拟图,已经包括hCard, hCalendar等格式。
话说回来,无聊一下,如果写Greasemonkey user script来改装网页,你会改装国内的哪个网站?怎么改?