15.21.1. CDN (Content Delivery Network) 与反向代理
与CDN有关的开发工作
15.21.1.1. CDN接口API
CDN 内容更新,一般厂商会提供一个SOAP接口,你可以通过接口刷新你的内容。但接口有限制,不能随意使用,一般是多少秒可以刷新一次,或者一天可以刷新几次
15.21.1.2. 方向代理页面过期处理
方向代理一般都支持PURGE协议,Squid,Varnish等等向管理端口发送 PURGE 即可是使用页面刷新
PURGE http://netkiller.github.net/index.html
有些方向代理如:Varnish 可以使用正则表达式
同时这些代理服务器都承受管理命令
squid: squidclient
varnish: varnishadm
15.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
15.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时间,且每个页面单独设置,可以随时调整设置。
15.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'); } }
15.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; } }
15.21.3. Cache 生存时间
你不必一开始加费劲心机去考虑这个值,当网站运行一段时间后,利用玩站流量数据作为参考,一步一地尝试调整。
原文出处:Netkiller 系列 手札
本文作者:陈景峯
转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。