Home | 简体中文 | 繁体中文 | 杂文 | Search | ITEYE 博客 | OSChina 博客 | Facebook | Linkedin | 知乎专栏 | Email

14.21. Cache

14.21.1. CDN (Content Delivery Network) 与反向代理

与CDN有关的开发工作

14.21.1.1. CDN接口API

CDN 内容更新,一般厂商会提供一个SOAP接口,你可以通过接口刷新你的内容。但接口有限制,不能随意使用,一般是多少秒可以刷新一次,或者一天可以刷新几次

14.21.1.2. 方向代理页面过期处理

方向代理一般都支持PURGE协议,Squid,Varnish等等向管理端口发送 PURGE 即可是使用页面刷新

PURGE http://netkiller.github.net/index.html
				

有些方向代理如:Varnish 可以使用正则表达式

同时这些代理服务器都承受管理命令

squid: squidclient

varnish: varnishadm

14.21.1.3. 内容版本化

例如这样的URL

http://images.example.com/logo.gif
http://images.example.com/product.jpg
				

我们可以通过Rewrite或PATHINFO等技术做为静态化。例如首次版本

http://images.example.com/logo.1.gif		=> logo.gif
http://images.example.com/product.1.jpg		=> product.jpg
				

原图发生变化后,版本递增

http://images.example.com/logo.2.gif		=> logo.gif
http://images.example.com/product.2.jpg		=> product.jpg
				

就的URL将丢弃

http://images.example.com/logo.1.gif
http://images.example.com/product.1.jpg
				

CDN 就回源去下面的URL,并且取到的是新图

http://images.example.com/logo.2.gif
http://images.example.com/product.2.jpg
				

14.21.2. HTTP Cache

Cache-Control

max-age
max-age 格式写为:max-age=n,n是以秒为单位, 这个值是告知客户端GMT + N 后页面过期,缓存服务器在s-maxage值为空的时候也会使用这个参数的值。

s-maxage
s-maxage的格式跟max-age一样,只不过他是给缓存服务器使用的。

must-revalidate
这个参数用来告知客户端和缓存服务器,在GET请求的时候必须与源服务器验证实体是否为最新版本。

Cache-Control:max-age=1200,s-maxage=3600
			
Last-Modified
这个参数提供了实体最近一次被修改的时间。这个名字起得不错,当实体被修改了之后,这个参数也就会被修改.
			

ETag

ETag
ETag是根据内容生成的一段hash字符串,采用信息摘要算法,保证每一个页面有一个唯一字串。
			

expires

expires 是HTTP 1.0 中定义的,已经不能满足用户的需要在 HTTP 1.1 加入了max-age,建议使用 max-age替代expires

指令					含义
public				可以在任何地方缓存
private				只能被浏览器缓存
no-cache			不能在任何地方缓存
must-revalidate		缓存必须检查更新版本
proxy-revalidate	代理缓存必须检查更新版本
max-age				内容能够被缓存的时期,以秒表示
s-maxage			覆盖共享缓存的max-age设置
			

在Squid, Varnish, Apache, Lighttpd, Nginx 中都可是实现HTTP Cache-Control推送,每次修改都需要重新加载,不太灵活。

ExpiresActive On
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"


server.modules = (
...
"mod_expire",
...
)

$HTTP["url"] =~ "^/images/" {
expire.url = ( "" => "access 30 days" )
}
			

我喜欢自己控制TTL时间,且每个页面单独设置,可以随时调整设置。

14.21.2.1. 在程序中灵活操作 Cache-Control

在MVC框架中每个控制器下的方法都可以单独操作Cache

Class blog extend Controller{
	blog(){
		header('Cache-Control: max-age=28800');
	}
	list(){
		header('Cache-Control: max-age=3600');
	}
	details(){
		header('Cache-Control: max-age=160');
	}
}
				

你还可以封装到Controller中

Class blog extend Controller{
	blog(){
		this->cache('28800');
	}
	list(){
		this->cache('3600');
	}
	details(){
		this->cache('160');
	}
}
				

14.21.2.2. 非程序文件缓存处理

首先做一个Rewrite让程序接管所有图片请求

url.rewrite = ( "^/(.+)" => "/index.php/$1" )
				

然后程序通过PATHINFO取出图片URL

http://images.example.com/your/dir/test.jpg => http://images.example.com/index.php/your/dir/test.jpg
				

程序取出 /your/dir/test.jpg 设置 Content-type 并输出二进制流

详细参考

				
<?php
    // Test image.
    $images = '/test/foo.png';

    $headers = apache_request_headers();

    if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($images))) {
        header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($images)).' GMT', true, 304);
    } else {
        header('Content-Type: image/png');
        print file_get_contents($fn);
		if (file_exists($images)) {
			header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($images)).' GMT', true, 200);
			header("Cache-Control: max-age=3600, must-revalidate");
			header('Content-Length: '.filesize($images));
			header('Content-type: ' .mime_content_type($images));
			flush();
			readfile($images);
			exit;
		}
    }
				
				

javascript 文件也可以使用类似方法处理

				
	private function js($file){
		if (file_exists($file)) {
			header("Cache-Control: max-age=3600, must-revalidate");
			header('Content-type: text/javascript');
			flush();
			readfile($file);
			exit;
		}
	}
				
				

14.21.3. Cache 生存时间

你不必一开始加费劲心机去考虑这个值,当网站运行一段时间后,利用玩站流量数据作为参考,一步一地尝试调整。