浅析http协议与缓存

标签: http 缓存 | 发表时间:2012-09-04 07:10 | 作者:司徒正美
分享到:
出处:http://www.cnblogs.com/rubylouvre/

最近几天在复习http协议中headers,缓存等相关知识,发现些新知识点。

这篇文章注重结合PHP去理解这些内容,也就是比较注重实践部分。

一、http headers

NO1:对于web应用,用户群在客户端 (各种浏览器)点击任何一个连接向服务器发送http请求,这过程肯定需要3次握手,建立连接,服务器响应返回数据。

每次请求都有头部和实体部分,先看下面笔者监听QQ空间的headers,QQ空间的原因是它头部内容比较全

Request Headers:    GET http://user.qzone.qq.com/445235728 HTTP/1.1    Host: user.qzone.qq.com    Connection: keep-alive    Cache-Control: max-age=0    User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    Referer: http://qzone.qq.com/    Accept-Encoding:gzip,deflate,sdch    Accept-Language: zh-CN,zh;q=0.8    Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3    Cookie:o_cookie=445235728;(省略很多……)    If-Modified-Since: Wed, 13 Jun 2012 01:32:19 GMT    -----------------    Response Headers:    HTTP/1.1 200 OK    Connection:close    Server: QZHTTP-2.34.0    Date: Wed, 13 Jun 2012 02:59:31 GMT    Content-Encoding: gzip    Set-Cookie:login_time=61F0EEA02D704B1DBCF25166A74941B24F4BE24B205C466F;PATH=/; DOMAIN=qzone.qq.com    Set-Cookie:Loading=Yes;expires=Wed,13-Jun-201216:00:00GMT;PATH=/;DOMAIN=qzone.qq.com X-UA-Compatible: IE=Edge Last-Modified: Wed, 13 Jun 2012 02:59:31 GMT    Cache-Control: max-age=0, no-transform    Content-Type: text/html;charset=utf-8    Transfer-Encoding: chunked  

客户端向服务端发请求headers和服务端响应客户端headers图:

通过图片可以看出:

  1. 客户端请求headers包含了请求行和一些头域。
    请求行:请求的方法 统一资源标识器(URL)协议版本 ------这三者用空格分开,最后换行回车(\r\n) 例如:GET http://user.qzone.qq.com/445235728 HTTP/1.1
    各种头域:这些头域都是有关键字和键值成对组合,最后换行回车(\r\n)结束,这些头域告诉服务器应该怎么去响应以及本身一些信息。
  2. 服务器响应

    状态行:协议版本 响应状态 状态描述 ------这三者用空格分开,最后换行回车(\r\n) 例如:HTTP/1.1 200 OK

    各种头域:这些头域也是有关键字和键值成对组合,最后换行回车(\r\n)结束,这些头域告诉客户端应该怎么去响应以及本身一些信息。

NO2

这里就不一一说每个头域的概念和作用,想了解的请看:http://www.phpben.com/?post=34 现在介绍几个认为重要、在一些网站上的测试数据、以及请求返回各头域php代码实现

测试时间:2012.6.14前

测试对象:csdn 、cnbeta 、cnblos、腾讯(QQ空间、朋友网、新闻网)、新浪(微博、主页)、人人网、百度、淘宝、优酷、土豆这些网站

(1) Connection头域:这个头域只有http/1.1才有,默认是keep-alive值表示长连接,这样的话就不用每请求一个资源比如图片,css文件,js文件都要和服务器进行3此握手连接,这个在一定程度上弥补了http没状态的一个缺陷,减少连接服务器的时间。查看测试网站Connection头域发现腾讯QQ空间、腾讯新闻网、新浪主页和微博,优酷和土豆Connection:close;除了这些其他的都是Connection:keep-alive为什么?

1、connection: keep-alive 能正常使用的一个前提条件是还要提供content-length的头域告诉客户端正文的长度。那计算正文长度是个问题,对于多内容,集群服务器来说不是件易事。腾讯和新浪,优酷的这些都很难计算,对与工程师来说之间关闭了(默认是打开的)。

2、老服务器端不支持,对于腾讯,新浪这些老油条,服务器集群很庞大,难免有些老旧的不支持长连接的,为了一些兼容性问题,直接关闭了Ps:这两点原因未求证过!^-^

用php headers(“Connection:keep-alive”);

(2) Content-Encoding头域

Content-Encoding文档的编码(Encode)方法.

上述网站出了cnbeta不用gzip压缩,优酷用deflate,其余都是。这也透漏一个重要信息,那就phper要掌握压缩gzip传输技术。

Php可以通过mod_gzip模块来实现。代码:ob_start("ob_gzhandler");

(3) Server头域暴漏服务器重要的安全信息。

Csdn:Server:nginx/0.7.68 ------------版本都暴露

腾讯QQ空间:Server:QZHTTP-2.34.0--------某位tx朋友透漏这是内部自己开发的服务器,这个可够安全

新浪微博:Server:apache -------------这个没暴漏版本

凤凰网:Server: nginx/0.8.53

人人网:Server:nginx/1.2.0

淘宝网:Tengine ---------这是淘宝内部技术团队开发的web服务器,基于Nginx

cnblogs博客园:Server:Microsoft-IIS/7.5

腾讯朋友网:Tencent/PWS ---------腾讯内部开发

腾讯新闻网:Server:squid/3.1.18

优酷网:Server: fswww1-----------是不是内部就不清楚,至少笔者不知道什么来的^_^

土豆网:Tengine/1.2.3

百度:server: BWS/1.0 ---------应该也是百度内部自己开发的服务器

很明显Server头域是返回服务器的信息,但也可以说暴漏信息,面对这个问题,大公司就自己开发基于自己功能的内部服务器。

(4) X-Powered-By头域可供修改,基于安全则可以修改
X-Powered-By头域反应什么语言什么版本执行后台程序。这个可以同个header函数修改
header("X-Powered-By:acb");

(5) Cache-control、expires、last-modified等重要头域

  • Cache-control:指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。Php代码实现:header("cache-control: abc");abc是上述指令值一个或多个,多个用’,’分开
  • Expires:告诉浏览器指明应该在什么时候认为文档已经过期,从而不再缓存它。代码实现:header("Expires:". date('D, d M Y H:i:s \G\M\T', time()+10));--------这个是把时间截转化成格林时区字符串给expires头域,这个显示时间会比中国北京时间少8个小时,东8区的实现:header("Expires:". date('r', time()+10))
  • last-modified:这个是服务器返回给浏览器,浏览器下次请求则把该值赋给if-modified-since头域传给服务器,服务器就可以根据此值判断是否有改变,有则继续运行下去,否者返回304 not modified。Php设置expires头域一样。

代码:

 

前者是格林时间格式,后者是中国时间。需要注意的就是php.ini 的时区prc则用后则,否者前者。笔者曾经试过在时区是prc的情况下用了前者,导致time()-strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) <0永远成立,因为是负值。

注意:当请求页面有session_start()的时候,则不管是否有expires、cache-control、last-modified设置,则返回给客户端Cache-Control头域为Cache-Control:no-store, no-cache, must-revalidate Expires头域 Expires:Thu, 19 Nov 1981 08:52:00 GMT。这个问题烦了笔者2天,都以为php.ini 或是apache的问题。最后竟然是session_start()的问题。

二、浏览器缓存动态

前面介绍了http headers几个告诉浏览器如何处理缓存。但不同浏览器处理各种头域的方式不同,以下就是笔者。

(1) header(“cache-control: no-store”)

 

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

同上

同上

同上

同上

(2) header(“cache-control: no-cache”)

 

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

同上

From cache

From cache

同上

(3)header(“cache-control:bublic”)

 

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

from cache

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

(4) header("cache-control:private"); header("cache-control: must-revalidate ")

 

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

除第一次外都是from cache

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

(5) header("cache-control:max-age=num");num是秒数

 

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

秒数<num from cache

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

(6) header("Expires:". date('D, d M Y H:i:s \G\M\T', time()+num)); num是秒数

 

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

地址栏回车

秒数<num from cache

重发请求,返回200状态

重发请求,返回200状态

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

(7)

 if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (time()-strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) < num)) {  header("HTTP/1.1 304 Not Modified");     exit;   } header("Last-Modified: " . date('D, d M Y H:i:s \G\M\T', time()) );

 

IE9

Google17.0

Firefox11

Maxthon3

点击刷新键

秒数<num 304 not modified

秒数<num 304 not modified

秒数<num 304 not modified

重发请求,返回200状态

地址栏回车

from cache

秒数<num 304 not modified

秒数<num 304 not modified

重发请求,返回200状态

点击后退键

From cache

From cache

From cache

同上

结论:

  1. 刷新对于任何浏览器且不管是什么cache-control,都会重新请求,一般返回是200,除非Last-Modified设置
  2. 后退键除非no-cache; no-store外都是使用缓存
  3. Cache-control:no-store 在浏览器中任何操作都重新提交请求,包括后退
  4. 遨游3的缓存很差
  5. IE9 的缓存很强,所以用ie9调试的时候尽可能点刷新而不是在地址栏回车

鉴于这种情况,对于不同的应用(有些要缓存,有些经常更新)对于不同的国家各种浏览器份额,而哪种缓存方式。中国IE比较多,加上360浏览器的加入(用IE内核),那就要主要参照IE浏览器。

但笔者还是比较喜欢header("Last-Modified: " . date('D, d M Y H:i:s \G\M\T', time()) );这种方式。结合起来connection:keep-alive能让缓存技术更成熟。

注意

  1. 也许你会问,用Cache-control:no-store或Cache-control:no-store,但调试页面还是没原来的缓存。然后清除浏览器缓存关掉重启浏览器, 缓存还在。这是因为你的web应用用了文件缓存如ecshop常出现这种情况,这种情况就要进web应用后台删除文件缓存。
  2. 调试的时候尽可能不要在地址栏回车,特别是IE,google还好一点,但是要知道这次的测试只是各个浏览器中的一个版本,所以调试的时候尽可能点刷新按钮。
  3. 但在cache-control:max-age=num 和expires 一起使用的时候,前者级别比较高,浏览器会忽略expires的设置。(上面没给出测试内容)

本文链接

相关 [http 缓存] 推荐:

HTTP缓存算法

- - PHP源码阅读,PHP设计模式,PHP学习笔记,项目管理-胖胖的空间
HTTP协议缓存的目标是去除许多情况下对于发送请求的需求和去除许多情况下发送完整请求的需求. 以不发送请求或减少请求传输的数据量来优化整个HTTP架构,此目标的实现可以产生如下好处:. 降低对原始服务器的请求量. 减少了传送距离,降低了因为距离而产生的时延. 缓存基本处理过程包括七个步骤. 接收 – 缓存从网络中读取抵达的请求报文.

合理使用 HTTP 缓存

- - Harttle Land
HTTP 缓存 使用 HTTP 缓存:Etag, Last-Modified 与 Cache-Control 一文对 HTTP 协议的缓存机制进行了简单的讨论,本文集中讨论实际操作中的最佳实践. 谨慎地使用过期时间,最好配合 MD5 一起使用. Last-Modified,动态内容采用. 分离经常变化的部分,也会提高缓存的命中率.

http协议:Web前端-HTTP Cache-control/浏览器缓存(转)

- - 互联网 - ITeye博客
HTTP协议分别在 1.0 / 1.1 两个时代推出了 Expires / Cache-control 两种cache策略,这里我们无需了解全部的细节,无需记住整个RFC内容,但是当我们需要使用HTTP cache策略时,我们需要注意以下细节:. Expires 是HTTP 1.0 那个时代的东西了,目前来看,可以不使用了,因为HTTP 1.0 的user agent占有率在 0.1% 以下(我们主要面向的web浏览器均默认使用HTTP 1.1),Cache-control 是 HTTP 1.1 的新特性,也是我们主要做文章使用cache策略的工具.

浅析http协议与缓存

- - 博客园_Ruby's Louvre
最近几天在复习http协议中headers,缓存等相关知识,发现些新知识点. 这篇文章注重结合PHP去理解这些内容,也就是比较注重实践部分. 一、http headers. NO1:对于web应用,用户群在客户端 (各种浏览器)点击任何一个连接向服务器发送http请求,这过程肯定需要3次握手,建立连接,服务器响应返回数据.

JBoss_053:使用JDG外部缓存HTTP Session

- - 热爱Java ,热爱生活
环境:JBoss EAP 6.4.0 + JBoss Data Grid 6.5.0. JBoss Data Grid 6.5.0 有个新特性:可以把JDG 作为外部缓存来存储HTTP Session,这样做的好处是:. (1)减轻了应用服务器的内存压力以及集群节点间的 Session 复制. (2)利用JDG的横向扩展能力,可以容纳更多的 Session 对象.

web基础-web工作原理,http协议,浏览器缓存

- - 浏览器 - 互联网 - ITeye博客
4,cookie和session. 平时用浏览器,输入网址后回车,页面响应我们想要浏览的内容,简单操作的背后蕴涵了什么原理. 当输入url回车后,客户端(浏览器)会去请求DNS服务器,通过DNS获取域名对应的IP地址,然后通过这个地址找到对应的服务器,要求建立TCP连接,建立连接,客户端发送httpRequest(请求包)后,服务器接收并开始处理请求,调用自身服务,返回httpResponse(响应包),客户端收到响应包后开始渲染body主体,等到全部接收,断开与该服务器端的TCP连接.

聊聊高并发系统之HTTP缓存(转)

- - 企业架构 - ITeye博客
原文网址:http://jinnianshilongnian.iteye.com/blog/2319573. 最近遇到很多人来咨询我关于浏览器缓存的一些问题,而这些问题都是类似的,因此总结本文来解答以后遇到类似问题的朋友. 因本文主要以浏览器缓存场景介绍,所以非浏览器场景下的一些用法本文不会介绍,而且本文以chrome为测试浏览器.

[转][转]浅析http协议、cookies和session机制、浏览器缓存

- - heiyeluren的Blog
来源:http://www.phpben.com/?post=77. 最近几天在复习http协议中headers,cookies、session、缓存等相关知识,发现些新知识点. 这篇文章注重结合PHP去理解这些内容,也就是比较注重实践部分. 一、            http headers          .

基于HTTP缓存轻松实现客户端应用的离线支持及网络优化

- - Oasis Feng
常规的客户端应用开发实践中,为了支持离线特性,往往需要引入本地数据存储并增加相应的『离线状态』逻辑分支. 本地存储的大量使用对数据结构的前后向兼容设计提出了很高的要求,一旦考虑不足,往往不得不引入复杂的版本间数据升降级处理,进一步加剧开发和维护成本. 而且针对『离线』与『在线』状态这两条并行的处理分支,对业务逻辑的清晰性和可维护性有一定的破坏,常常容易在后续开发中造成处理遗漏,给测试和维护带来更多的痛苦.

HTTP Headers 入门

- johnny - Time Machine
非常感谢 @ytzong 同学在twitter上推荐这篇文章,原文在此. 本文系统的对HTTP Headers进行了简明易懂的阐述,我仅稍作笔记. 什么是HTTP Headers. HTTP是“Hypertext Transfer Protocol”的所写,整个万维网都在使用这种协议,几乎你在浏览器里看到的大部分内容都是通过http协议来传输的,比如这篇文章.