这几天看了下nginx的日志,里面很多400 408的记录,像这样:
<remote-ip> - - [17/Nov/2012:15:03:12 +0800] "-" "static.xjpvictor.info" 400 0 "-" "-"
<remote-ip> - - [18/Nov/2012:13:30:05 +0800] "-" "static.xjpvictor.info" 408 0 "-" "-"
除了个ip和host address几乎什么都没有。于是去google了一下,发现大概是3个原因造成的
- cookies太大导致header超出nginx的缓存
- 网络问题
- chrome的preconnect技术
第一个问题应该不是,我的static子域名是个cookie-free的网址,所以不存在header过大的问题。第二个问题无法排除,但这个问题不是简单的服务器端能解决的问题,而且其实这些400 408记录经常是一次正常访问后接着访问第二个页面的时候产生的,所以应该不会是网络问题。
因为产生400 408之前一般都有一次正常访问的记录,于是从这些记录中把所有产生400 408记录的ip的ua给提取出来,发现大概80%来自于chrome,其余大部分来自firefox,但是根据网站的访问记录来看,chrome只占了大概60%,于是可以认为确实是chrome的某些因素造成的。所以用自己电脑的浏览器来测试了一下。测试了主流的3个浏览器,chrome,firefox,和opera。至于ie和国产的浏览器壳子,很遗憾,你们连让我鄙视的机会都没有,直接无视之。
chrome在第一次打开这个博客的时候一切正常。但是当接着打开第二个页面时就会在nginx里留下408记录了。但是再打开第三个页面又没问题,然后接下来继续随意的打开一些页面又会出现几次408的记录。于是可以看出chrome的preconnect技术确实导致了400 408的产生,但是并不是每个页面都会进行preconnect,google貌似用了个所谓的「learning」机制,也就是它会判断这个网页和刚才的很相似但是又不太一样的时候才使用preconnect,而如果网页元素和刚才几乎一样就不会preconnect。
对于firefox,貌似在最新的版本中也加入了preconnect技术,然而和chrome不同的是,firefox在每次打开一个页面时都会preconnect一下,所以每个页面的访问记录中都会产生400记录。没错,是400。chrome会preconnect到https,于是产生了408,而firefox是preconnect到http,所以产生了400,而我的网页全是https链接,所以firefox的preconnect其实是完全在做无用功。
opera貌似没有preconnect的功能,所以也不会产生400和408记录,只有当网页元素还没加载完的时候就关闭浏览器才会有400和408,但这就属于网络问题了。
所以,结论是,400和408记录一般就可以无视了,因为不是nginx方面可以解决的了。但是其实个人认为这个preconnect技术其实很无聊。网络好的时候不在乎那么几毫秒的差别,网络不好的时候倒是有些作用,只是这种作用是以堵塞服务器为代价的,其实不如网页开发者多在网页优化上下点功夫,减少点http请求,做好缓存,用好cookie-free域名,比什么都强。至于firefox这种不管三七二十一先连了再说的就更是没有意义了。但如果浏览器能在关闭preconnect的连接的时候发送一个包告诉服务器是它主动断开而不是网络中断,这样会好很多,至少在分析nginx日志的时候能很容易看出是不是网络问题导致的400 408。