看到大家分享了些关于 cache 的优化 tips,我也搭车来点最近在公司内部做的技术分享:
使用 Rails 的 Asset Pipeline,会生成 2 个文件:一个是把所有 css/js 的打包成的一个文件,一般是 application-[hash].css, 另一个是同名 gz 后缀的 gzip 文件:application-[hash].css.gz
打包成一个文件很好理解,这样可以减少 js 请求数量,因为浏览器会限制同一个域名同时发起请求的数量; 带 hash 作为文件的版本号,一旦有新的版本部署,hash 值会变化,这样浏览器也不会去 load 缓存里的文件。 但为什么还要生成一个 gz 文件呢?
nginx 可以把输出的内容使用 gzip 压缩再发送到浏览器,浏览器如果支持 gzip 解压会在 request header 包含Accept-Encoding: compress, gzip
,这样 nginx 就会发送 gzip 后的内容,并在 reponse header 加入Content-Encoding: gzip
声明这是 gzip 后的内容,告诉浏览器要先解压。
让 nginx 使用 gzip 压缩内容可以减少传输数据大小,但压缩率越高 CPU 消耗越高,CPU 消耗高,意味着 nginx 能同时处理的响应能力就要下降。
好在 nginx 又提供了个gzip_static
模块,只要在部署时预编译好 gzip 文件,同时让 nginx 启用 gzip_static,在响应请求时 nginx 检查到有同名的.gz 文件,就会把 gz 文件的内容直接发送出去。
所以在部署时预先编译好 gzip 文件的话,可以用最高的压缩率使文件最小从而节省带宽,而 nginx 就只需简单发送文件了,不用再做 gzip 处理,这样请求时可以省 cpu。
要启用 nginx 的 gzip_static 模块,首先我们要确认 nginx 的 gzip_static 模块已经被编译进去:
$ /opt/nginx/sbin/nginx -V
如果该命令输出有--with-http_gzip_static_module,则说明 nginx 支持 gzip_static 模块。如果没有,需要加上 --with-http_gzip_static_module 该参数重新编译 nginx。
在 nginx 的 http 配置里添加 gzip_static 的配置:
location ~ ^/(assets)/ {
root /path/to/public;
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
}
检查 nginx 的 gzip_static 配置是否生效:
$ curl -I -H "Accept-Encoding: gzip,deflate" http://example.com/assets/application-cfb3e4017298e9fd00a3bc04d3dea72c.css
HTTP/1.1 200 OK
Server: nginx/1.4.7
Date: Thu, 08 May 2014 14:14:48 GMT
Content-Type: text/css
Content-Length: 7167
Last-Modified: Tue, 06 May 2014 17:27:06 GMT
Connection: keep-alive
ETag: "53691b6a-1bff"
Accept-Ranges: bytes
$ curl -I -H "Accept-Encoding: gzip,deflate" http://example.com/assets/application-cfb3e4017298e9fd00a3bc04d3dea72c.css
HTTP/1.1 200 OK
Server: nginx/1.4.7
Date: Thu, 08 May 2014 14:13:24 GMT
Content-Type: text/css
Content-Length: 2284
Last-Modified: Tue, 06 May 2014 17:27:06 GMT
Connection: keep-alive
ETag: "53691b6a-8ec"
Content-Encoding: gzip
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Cache-Control: public
可以看到 Content-Type: text/css
没有改变,但Content-Length
已经变小,而且有Content-Encoding: gzip
标记。
浏览器识别到Content-Encoding: gzip
的标记,自然就会用 gzip 来解压接收到的内容了。
rails 的 asset pipeline 搭配 nginx 的 gzip_static 使用就可以省带宽省 CPU。