实操 Web Cache

实操 Web Cache

摘要

写这篇文章的原因,是我看到网上很多谈这类的文章,多是人云亦云,不求实事,误导读者。

下面文中我会一个一个做实验,并展示给你,说明为什么会这样。只有自己亲自尝试才能拿出有说服力的真凭实据。

2014-03-12 首次发布

2015-08-27 修改,增加特殊数据缓存


目录

  • 1. 测试环境
  • 2. 文件修改日期 If-Modified-Since / Last-Modified
    • 2.1.1. if_modified_since
    • 2.1. 静态文件
    • 2.2. 通过rewrite伪静态处理
    • 2.3. 动态文件
  • 3. ETag / If-None-Match
    • 3.1. 静态文件
    • 3.2. 动态程序
  • 4. Expires / Cache-Control
    • 4.1. 静态文件
    • 4.2. 动态文件
  • 5. FastCGI 缓存相关
  • 6. HTML META 与 Cache
  • 7. gzip
    • 7.1. gzip 总结
  • 8. 反向代理与缓存
    • 8.1. gzip 处理
  • 9. 特殊数据缓存
    • 9.1. json
    • 9.2. XML
  • 10. 总结

1. 测试环境

CentOS 6.5

Nginx安装脚本 https://github.com/oscm/shell/blob/master/nginx/nginx.sh

php安装脚本 https://github.com/oscm/shell/blob/master/php/5.5.8.sh

2. 文件修改日期 If-Modified-Since / Last-Modified

If-Modified-Since 小于 Last-Modified 返回 HTTP/1.1 200 OK, 否则返回 HTTP/1.0 304 Not Modified

每次浏览器请求文件会携带 If-Modified-Since 头,将当前时间发送给服务器,与服务器的Last-Modified时间对对比,如果大于Last-Modified时间,返回HTTP/1.0 304 Not Modified不会重新打开文件,否则重新读取文件并返回内容

2.1. 静态文件

nginx/1.0.15 静态文件自动产生 Last-Modified 头

# nginx -v
nginx version: nginx/1.0.15

# curl -I http://192.168.6.9/index.html
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 07:36:03 GMT
Content-Type: text/html
Content-Length: 6
Last-Modified: Thu, 27 Feb 2014 07:29:50 GMT
Connection: keep-alive
Accept-Ranges: bytes			

图片文件

# curl -I http://192.168.6.9/image.png
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 07:37:18 GMT
Content-Type: image/png
Content-Length: 41516
Last-Modified: Thu, 27 Feb 2014 07:36:59 GMT
Connection: keep-alive
Accept-Ranges: bytes			

提示

疑问 nginx/1.4.5 默认没有 Last-Modified

# nginx -v
nginx version: nginx/1.4.5

# curl -I http://192.168.2.15/index.html
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 02:13:44 GMT
Content-Type: text/html
Connection: keep-alive				

经过一番周折最终找到答案 Nginx 如果开启 ssi 会禁用Last-Modified 关闭 ssi 后输出如下

# curl -I  http://localhost/index.html
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 05:44:29 GMT
Content-Type: text/html
Content-Length: 6
Last-Modified: Wed, 25 Dec 2013 03:18:16 GMT
Connection: keep-alive
ETag: "52ba4e78-6"
Accept-Ranges: bytes				

再测试一次

# curl -H "If-Modified-Since: Fir, 28 Feb 2014 07:42:55 GMT" -I http://192.168.2.15/test.html
HTTP/1.1 304 Not Modified
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 02:34:54 GMT
Last-Modified: Fri, 28 Feb 2014 01:55:50 GMT
Connection: keep-alive
ETag: "530feca6-8b"			

测试结果成功返回 HTTP/1.1 304 Not Modified, 但又莫名其妙的出现了 ETag。 这就是Nignx本版差异,非常混乱。

既然出现了ETag我们也顺便测试一下

# curl -H 'If-None-Match: "530feca6-8b"' -I http://192.168.2.15/test.html
HTTP/1.1 304 Not Modified
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 02:39:18 GMT
Last-Modified: Fri, 28 Feb 2014 01:55:50 GMT
Connection: keep-alive
ETag: "530feca6-8b"			

也是成功的

测试图片

# curl -I http://localhost/logo.jpg
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 02:59:04 GMT
Content-Type: image/jpeg
Content-Length: 10103
Last-Modified: Fri, 28 Feb 2014 02:56:37 GMT
Connection: keep-alive
ETag: "530ffae5-2777"
Accept-Ranges: bytes


# curl -H 'If-None-Match: "530ffae5-2777"' -I http://localhost/logo.jpg
HTTP/1.1 304 Not Modified
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 03:03:33 GMT
Last-Modified: Fri, 28 Feb 2014 02:56:37 GMT
Connection: keep-alive
ETag: "530ffae5-2777"

# curl -H "If-Modified-Since: Fri, 28 Feb 2014 12:04:18 GMT" -I http://localhost/logo.jpg
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 03:04:45 GMT
Content-Type: image/jpeg
Content-Length: 10103
Last-Modified: Fri, 28 Feb 2014 02:56:37 GMT
Connection: keep-alive
ETag: "530ffae5-2777"
Accept-Ranges: bytes			

测试结果,ETag通过测试,If-Modified-Since无论如何也无法返回 304 可能还需要其他的HTTP头,浏览器测试都通过返回 HTTP/1.1 304 Not Modified

现在换成浏览器测试 Chrome Firefox成功, 因为浏览器不会主动发送If-Modified-Since, 浏览器只有发现Last-Modified后,第二次请求才会推送 If-Modified-Since 需要刷新两次页面。

2.1.1. if_modified_since

在开启ssi的情况下,通过参数 if_modified_since 可以开启 Last-Modified

server {
    listen       80;
    server_name  192.168.2.15;
    if_modified_since before;
}				

测试结果看不到 Last-Modified, 因为 Nginx 的 if_modified_since before;参数只有接收到浏览器发过来的If-Modified-Since头才会发送Last-Modified

# curl -I http://192.168.2.15/test.html
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 02:39:42 GMT
Content-Type: text/html
Connection: keep-alive				

最终 if_modified_since before; 数没有起到作用

参数设置为 if_modified_since exact;

# curl -I http://192.168.2.15/test.html
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 02:45:40 GMT
Content-Type: text/html
Connection: keep-alive

# curl -H 'If-None-Match: "530feca6-8b"' -I http://192.168.2.15/test.html
HTTP/1.1 304 Not Modified
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 02:45:44 GMT
Last-Modified: Fri, 28 Feb 2014 01:55:50 GMT
Connection: keep-alive
ETag: "530feca6-8b"

# curl -H "If-Modified-Since: Fir, 28 Feb 2014 07:42:55 GMT" -I http://192.168.2.15/test.html
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 02:45:50 GMT
Content-Type: text/html
Connection: keep-alive				

测试失败,浏览器也是实测失败,ETag却成功

2.2. 通过rewrite伪静态处理

index.php仍然是上面的那个php文件,我们只是做了伪静态

			location / {
        root   /www;
        index  index.html index.htm;
		rewrite ^/test.html$ /index.php last;
}			

现在我们分别通过curl有chrome/firefox进行测试

			# curl -H "If-Modified-Since: Fri, 28 Feb 2014 08:42:55 GMT" -I  http://192.168.6.9/test.html
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 08:55:19 GMT
Content-Type: text/html
Connection: keep-alive
Last-Modified: Thu, 26 Feb 2014 08:39:35 GMT			

经过测试无论是 curl 还是 chrome/firefox 均无法返回304.

下面是我的分析,仅供参考。用户请求index.html Nginx 会找到该文件读取 mtime 与 If-Modified-Since 匹配,如果If-Modified-Since大于 Last-Modified返回 304否则返回200.

为什么同样操作经过伪静态的test.html就不行呢? 我分析当用户请求test.html Nginx 首先做Rewrite处理,然后跳转到index.php 整个过程nginx 并没有访问实际物理文件test.html也就没有mtime, 所以Nginx 返回200.

如果 Nginx 按预想的返回304,nginx 需要读取程序返回的HTTP头,Nginx 并没有这样的处理逻辑。

2.3. 动态文件

动态文件没有 Last-Modified 头,我们可以伪造一个

			# curl -I http://192.168.6.9/index.php
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 07:57:59 GMT
Content-Type: text/html
Connection: keep-alive			

在程序中加入HTTP头推送操作,Last-Modified时间是27号,当前时间是28号,我们要让Last-Modified 小于当前时间才行。

			# cat index.php
<?php
header('Last-Modified: Thu, 27 Feb 2014 08:39:35 GMT' );
//header('Last-Modified: ' .gmdate('D, d M Y H:i:s') . ' GMT' );
?>
Hello			

现在你将看到 Last-Modified

			# curl -I http://localhost/modified.php
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 05:59:28 GMT
Content-Type: text/html
Connection: keep-alive
Last-Modified: Fri, 28 Feb 2014 10:04:18 GMT			

注意

虽然我们让动态程序返回了 Last-Modified ,但浏览器不认,经过测试 Chrome / Firefox 均不会承认.php文件,并缓存其内容。

				# curl -I http://localhost/modified.php
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 05:59:28 GMT
Content-Type: text/html
Connection: keep-alive
Last-Modified: Fri, 28 Feb 2014 10:04:18 GMT

# curl -H "If-Modified-Since: Fri, 28 Feb 2014 08:42:55 GMT" -I  http://localhost/modified.php
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Fri, 28 Feb 2014 05:32:30 GMT
Content-Type: text/html
Connection: keep-alive
Last-Modified: Thu, 26 Feb 2014 08:39:35 GMT				

Last-Modified 对动态程序来说没有起到实际作用

Last-Modified是程序产生的,Nginx无法读到,让程序去处理状态返回是可行的,下面我们修改程序如下。

			# cat modified.php
<?php
$mtime = 'Fri, 28 Feb 2014 12:04:18 GMT';
cache($mtime);
function cache($mtime)
{
	$http_if_modified_since = null;
	if(array_key_exists ('HTTP_IF_MODIFIED_SINCE',$_SERVER)){
		$http_if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
	}
	echo $http_if_modified_since;
	if ($http_if_modified_since >= $mtime)
	{
		header('Last-Modified: '.$mtime, true, 304);
		exit;
	} else {
		header('Last-Modified: ' . $mtime );
	}

}
print_r($_SERVER);
echo date("Y-m-d H:i:s");
?>			

测试效果

			# curl -I http://localhost/modified.php
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 05:22:28 GMT
Content-Type: text/html
Connection: keep-alive			

伪造一个 If-Modified-Since 日期小于我们指定的日期程序返回HTTP/1.1 200 OK

			# curl -H "If-Modified-Since: Fri, 28 Feb 2014 10:04:18 GMT" -I http://localhost/modified.php
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 05:22:13 GMT
Content-Type: text/html
Connection: keep-alive			

伪造一个 If-Modified-Since 日期大于我们指定的日期程序返回HTTP/1.1 304 Not Modified

			# curl -H "If-Modified-Since: Fri, 28 Feb 2014 20:04:18 GMT" -I http://localhost/modified.php
HTTP/1.1 304 Not Modified
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 05:21:31 GMT
Connection: keep-alive
Last-Modified: Fri, 28 Feb 2014 12:04:18 GMT			

测试成功,并且在浏览器端也测试成功 HTTP/1.1 304 Not Modified

将modified.php伪静态处理

    location / {
        root   /www;
        index  index.html index.htm;
		rewrite ^/modified.html$ /modified.php last;
    }			

测试

# curl -I http://localhost/modified.html
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 06:21:10 GMT
Content-Type: text/html
Connection: keep-alive
Last-Modified: Fri, 28 Feb 2014 10:04:18 GMT

# curl -H "If-Modified-Since: Fri, 28 Feb 2014 12:04:18 GMT" -I http://localhost/modified.html
HTTP/1.1 304 Not Modified
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 06:21:22 GMT
Connection: keep-alive
Last-Modified: Fri, 28 Feb 2014 10:04:18 GMT			

达到预期效果

3. ETag / If-None-Match

上面的Last-Modified测试中发现ETag虽然不限制,但是暗中还是可用的:)

etag on; 开启Nginx etag支持,lighttpd 默认开启

		server {
    listen       80;
    server_name phalcon;

    charset utf-8;

    access_log  /var/log/nginx/host.access.log  main;
	etag on;
    location / {
        root   /www/phalcon/public;
        index  index.html index.php;
    }
}		

检查ETag输出

# curl -I http://localhost/index.html
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 03:08:28 GMT
Content-Type: text/html
Connection: keep-alive

# curl -I http://phalcon/img/css.png
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 27 Feb 2014 09:20:49 GMT
Content-Type: image/png
Content-Length: 1133
Last-Modified: Fri, 14 Feb 2014 08:05:03 GMT
Connection: keep-alive
ETag: "52fdce2f-46d"
Accept-Ranges: bytes3		

即使你开启了 ETag Nginx 对 HTML、CSS文件也不做处理。最终在一个外国网站是找到一个nginx-static-etags模块,有兴趣自己尝试,这里就不讲了。

3.1. 静态文件

首先查询etag值

# curl -I http://phalcon/img/css.png
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 27 Feb 2014 09:25:41 GMT
Content-Type: image/png
Content-Length: 1133
Last-Modified: Fri, 14 Feb 2014 08:05:03 GMT
Connection: keep-alive
ETag: "52fdce2f-46d"
Accept-Ranges: bytes			

然后向服务器发送If-None-Match HTTP头

# curl -H 'If-None-Match: "52fdce2f-46d"' -I http://phalcon/img/css.png
HTTP/1.1 304 Not Modified
Server: nginx
Date: Thu, 27 Feb 2014 09:25:44 GMT
Last-Modified: Fri, 14 Feb 2014 08:05:03 GMT
Connection: keep-alive
ETag: "52fdce2f-46d"			

这次比较顺利,成功返回HTTP/1.1 304 Not Modified

3.2. 动态程序

默认情况输出如下

# curl -I http://192.168.6.9/index.php
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 27 Feb 2014 09:29:13 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive			

测试程序

			<?php
header('Last-Modified: Thu, 26 Feb 2014 08:39:35 GMT' );
header('Etag: "abcdefg"');
#header('Last-Modified: ' .gmdate('D, d M Y H:i:s') . ' GMT' );
?>
Hello			

测试效果

# curl -I http://192.168.6.9/index.php
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 09:41:06 GMT
Content-Type: text/html
Connection: keep-alive
Last-Modified: Thu, 26 Feb 2014 08:39:35 GMT
Etag: "abcdefg"

[root@centos6 ~]# curl -H 'If-None-Match: "abcdefg"' -I http://192.168.6.9/index.php
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 09:41:42 GMT
Content-Type: text/html
Connection: keep-alive
Last-Modified: Thu, 26 Feb 2014 08:39:35 GMT
Etag: "abcdefg"			

测试情况与之前的Last-Modified结果一样

动态程序返回Etag真的就没有用了吗?

答案是:非也, 有一个方法可以让动态程序返回的 Etag 也能发挥作用,程序修改如下

			<?php
$etag = md5('http://netkiller.github.io');
cache($etag);
function cache($etag)
{
        $http_if_none_match = null;
        if(array_key_exists ('HTTP_IF_NONE_MATCH',$_SERVER)){
                $http_if_none_match = $_SERVER['HTTP_IF_NONE_MATCH'];
        }

        if ($http_if_none_match == $etag)
        {
                header('Etag: '.$etag, true, 304);
                exit;
        } else {
                header('Etag: '.$etag);
        }

}
print_r($_SERVER);
echo date("Y-m-d H:i:s");
?>			

首先查看Etag值

# curl  -I http://192.168.6.9/test.php
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 10:07:19 GMT
Content-Type: text/html
Connection: keep-alive
Etag: 7467675324d0f7a3e01ce5151848fedb			

发送If-None-Match头

# curl -H 'If-None-Match: 7467675324d0f7a3e01ce5151848fedb' -I http://192.168.6.9/test.php
HTTP/1.1 304 Not Modified
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 10:07:39 GMT
Connection: keep-alive
Etag: 7467675324d0f7a3e01ce5151848fedb			

达成预计效果,此种方法同样可以用于 Last-Modified,伪静态后效果更好

Etag 值的运算技巧,我习惯上采用URL同时配合伪静态例如

$etag = $_SERVER['REQUEST_URI']			

URL类似 http://www.example.com/news/100/1000.html 一次请求便缓存页面,这样带来一个更新的问题,于是又做了这样的处理

http://www.example.com/news/100/1000.1.html			

.1.是版本号,每次修改后+1操作,.1.没有人格意义rewrite操作是会丢弃这个参数,仅仅是为了始终有新的URL对应内容

4. Expires / Cache-Control

前面所讲 Last-Modified 与 Etag 主要用于分辨文件是否修改过, 无法控制页面在浏览器端缓存的时间。Expires / Cache-Control 可以控制缓存的时间段

Expires 是 HTTP/1.0标准,Cache-Control是 HTTP/1.1标准。都能正常工作,HTTP/1.1规范中max-age优先级高于Expires,有些浏览器会联动设置,例如你设置了Cache-Control随之自动生成Expires,仅仅为了兼容。

4.1. 静态文件

首先配置nginx设置html与png文件缓存1天

location ~ .*\.(html|png)$
{
    expires      1d;
}			

当前情况

# curl -I http://192.168.6.9/index.html
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 10:47:08 GMT
Content-Type: text/html
Content-Length: 6
Last-Modified: Thu, 27 Feb 2014 07:29:50 GMT
Connection: keep-alive
Accept-Ranges: bytes			

重启Nginx后的HTTP协议头多出Expires与Cache-Control

# curl -I http://192.168.6.9/index.html
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 10:42:09 GMT
Content-Type: text/html
Content-Length: 3698
Last-Modified: Fri, 26 Apr 2013 20:36:51 GMT
Connection: keep-alive
Expires: Fri, 28 Feb 2014 10:42:09 GMT
Cache-Control: max-age=86400
Accept-Ranges: bytes			

4.2. 动态文件

默认返回

# curl -I http://192.168.6.9/index.php
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 11:45:05 GMT
Content-Type: text/html
Connection: keep-alive			

index.php 增加 Cache-Control 输出控制

			header('Cache-Control: max-age=259200');			

再次查看

# curl -I http://192.168.6.9/index.php
HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Thu, 27 Feb 2014 11:53:48 GMT
Content-Type: text/html
Connection: keep-alive
Cache-Control: max-age=259200			

现在使用 Chrome 、Firefox 测试,你会发现始终返回200,并且max-age=259200数值不会改变。

原因是Cache-Control程序输出的,Nginx并不知道,所以Nginx 不会给你返回304

			header('Last-Modified: ' .gmdate('D, d M Y H:i:s') . ' GMT' );

$offset = 60 * 60 * 24;
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $offset) . ' GMT');

$ttl=3600;
header("Cache-Control: max-age=$ttl, must-revalidate");			

这种方法不能实现缓存的目的

5. FastCGI 缓存相关

我们做个尝试将 expires 1d;加到location ~ \.php$中,看看能不能实现缓存的目的。

    location ~ \.php$ {
        root           /www;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /www$fastcgi_script_name;
        include        fastcgi_params;
		expires      1d;
    }		

测试程序

		# cat expires.php
<?php
echo date("Y-m-d H:i:s");
?>		

测试结果

# curl -I http://localhost/expires.php
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Fri, 28 Feb 2014 04:39:57 GMT
Content-Type: text/html
Connection: keep-alive
Expires: Sat, 01 Mar 2014 04:39:57 GMT
Cache-Control: max-age=86400		

虽然推送 Cache-Control: max-age=86400 但是 IE Chrome Firefox 仍不能缓存页面

9. 特殊数据缓存

缓存并非只能缓存静态内容,HTML,CSS,JS以及图片意外的数据一样可以缓存。

只要处理好HTTP头即可。例如Ajax动态内容缓存,JSON数据缓存。

9.1. json

当用户请求json地址时,我们将 json 数据附加HTTP头(Cache-Control, Expires, ETag),然后返回给用户,用户的设备会遵循HTTP的声明,进行缓存操作。

curl -I http://api.example.com/article/json/2/20/0.html
HTTP/1.1 200 OK
Expires: Wed, 26 Aug 2015 05:40:57 GMT
Date: Wed, 26 Aug 2015 05:39:57 GMT
Server: nginx
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: max-age=60
ETag: 4238111283
Age: 69475
X-Via: 1.1 kaifeng45:3 (Cdn Cache Server V2.0)
Connection: keep-alive			

注意这里使用了伪静态 /article/json/2/20/0.html 伪静态与缓存没有关系,实际起作用的是HTTP头。

我们可以看到 Content-Type: application/json; charset=utf-8 声明,表明这是json数据,而不是HTML。

现在我们来演示一下JSON被缓存的效果,首先要说明 http://api.example.com/article/json/2/20/0.html 不是0.html文件,而是采用phalcon框架开发的一个程序,article是控制器类名称,json是jsonAction方法, 2/20/0 是传递给jsonAction的参数。

$ curl -I http://api.example.com/article/json/2/20/0.html
HTTP/1.1 200 OK
Expires: Thu, 27 Aug 2015 05:24:21 GMT
Date: Thu, 27 Aug 2015 05:23:21 GMT
Server: nginx/1.5.7
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: max-age=60
ETag: 558918903
Age: 1
X-Via: 1.1 kaifeng45:3 (Cdn Cache Server V2.0)
Connection: keep-alive			

上面第一次请求数据将被缓存。我们第二次请求推送 HTTP 头 If-None-Match。

$ curl -H 'If-None-Match: 558918903' -I http://api.example.com/article/json/2/20/0.html
HTTP/1.0 304 Not Modified
Date: Thu, 27 Aug 2015 05:23:22 GMT
Content-Type: application/json; charset=utf-8
Expires: Thu, 27 Aug 2015 05:24:22 GMT
ETag: 558918903
Cache-Control: max-age=60
Age: 15
X-Via: 1.0 kaifeng45:3 (Cdn Cache Server V2.0)
Connection: keep-alive			

数据被缓存并返回结果 HTTP/1.0 304 Not Modified,304代码是告诉用户端该页面或者数据没有变动,无需要再次下载数据。

9.2. XML

这里是指动态生成的XML,处理方式与 JSON一样,XML数据附加HTTP头(Cache-Control, Expires, ETag)后返回给用户。

10. 总结

经过详细的测试我们发现不同的浏览器,不同的Web服务器,甚至每个版本都有所差异。

测试总结 Apache HTTPD 最完善 Lighttpd 其次, Nignx仍在快速发展中,Nignx每个版本差异很大,对HTTP协议实现标准也不太严谨,因为Nignx在大陆是趋势,所以下面给出的例子都是nginx

我比较看好Lighttpd,FastCGI 部分我一般是用php-fpm替代Lighttpd的spawn-fcgi

切记使用Nginx要注意每个本版细微变化,否则升级后会有影响。我习惯使用yum 安装 nginx 随时 yum update 升级。

另外FastCGI 与 mod_php也有所区别

延伸阅读《Netkiller Web 手札》http://netkiller.github.io/www/index.html

原文发布于微信公众号 - Netkiller(netkiller-ebook)

原文发表时间:2015-09-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏沈唁志

PHP中常用的header头

1323
来自专栏Laoqi's Linux运维专列

ZABBIX 3.2 监控服务器TCP连接状态

1163
来自专栏北京马哥教育

TCP三次握手与四次分手傻傻分不清?看大神图解五分钟讲明白

引言 TCP三次握手和四次挥手不管是在开发还是面试中都是一个非常重要的知识点,它是我们优化web程序性能的基础。但是大部分教材都对这部分解释的比较抽象,本文我们...

3067
来自专栏王亚昌的专栏

短连接过多时,TIME_WAIT问题解决

        日常运维中用netstat -an命令发现服务器中有大量状态为TIME-WAIT的TCP连接,于是用/sbin/sysctl -a查看了一下Li...

653
来自专栏散尽浮华

SS命令和Netstat命令比较

在早期运维工作中,查看服务器连接数一般都会用netstat命令。其实,有一个命令比netstat更高效,那就是ss(Socket Statistics)命令! ...

2366
来自专栏小白安全

微信小程序游戏跳一跳刷分神器

PS:此文需要一定的电脑基础知识的人员,没有基础的请关闭本页,避免不适。玩这个的前提是你的微信升级到了最新版。 相关工具下载: https://develope...

3409
来自专栏转载gongluck的CSDN博客

第21章 多播

1·多播(组播)地址:224.0.0.0~139.255.255.255 2·发送多播数据报无需任何特殊处理,发送应用程序不必为此加入多播组 3·多播相对于广播...

33610
来自专栏小筱月

三次握手和四次挥手

OSI参考模型中的网络层,在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。(TCP在运输层,IP在网络层)

581
来自专栏bboysoul

httpstat一个实用的网络工具

这个工具可以收集一些网站的基础信息,而且它使用ascii字符的方式显示网站各种连接的时间,方便我们根据这个去优化网站,从而提高网站的连接响应速度。

822
来自专栏Python

TCP协议三次握手与四次挥手通俗解析

 TCP/IP协议三次握手与四次握手流程解析 一、TCP报文格式 TCP/IP协议的详细信息参看《TCP/IP协议详解》三卷本。下面是TCP报文格式图: ? 图...

1947

扫描关注云+社区