Rails 使用 Rails Asset Pipeline 配合 Nginx 的 gzip_static 优化 tips

rainchen for Beansmile · 发布于 2014年05月21日 · 最后由 diguage 回复于 2014年07月15日 · 5056 次阅读
377
本帖已被设为精华帖!

看到大家分享了些关于cache的优化tips,我也搭车来点最近在公司内部做的技术分享:

使用 Rails Asset Pipeline 配合 Nginx 的 gzip_static 优化 tips

Rails 的 Asset Pipeline 的生成文件

使用 Rails 的 Asset Pipeline,会生成2个文件:一个是把所有css/js的打包成的一个文件,一般是application-[hash].css, 另一个是同名gz后缀的gzip文件:application-[hash].css.gz

打包成一个文件很好理解,这样可以减少js请求数量,因为浏览器会限制同一个域名同时发起请求的数量; 带hash作为文件的版本号,一旦有新的版本部署,hash值会变化,这样浏览器也不会去load缓存里的文件。 但为什么还要生成一个gz文件呢?

nginx的gzip输出

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模块

好在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。

rails asset pipeline + nginx gzip_static

在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配置是否生效:

开启 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

开启 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: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。

共收到 23 条回复
De6df3

楼主调整一下排版呗,略乱,另外 asspets precompile -> Assets Pipeline

377

#1楼 @huacnlee 感谢指正,已经update

4755

顶。

8137

gz压缩需要适度,这不但需要考虑服务器的压缩压力,还得考虑浏览器解压缩的效率问题。帖子不错,顶一个

96

还有这样的功能!涨姿势了~

2838

赞!

HTTP Status Code: 304 Not Modified 这个feture 是不是也要提及下比较好。

273
location ~ ^/(assets)/  {
  root /path/to/public;
  gzip_static on; # to serve pre-gzipped version
  expires max;
  add_header Cache-Control public;
}

是不是有默认开启的啊?我记得我从来没有设置过这东西,然后 Content-Encoding:gzip 。

用得是 Nginx + Passenger。

377

@huacnlee 奇怪,内容怎么变了?我有加了段落标题的

De6df3

#11楼 @rainchen 我微调了一下

377

#10楼 @ruby_sky 默认应该没有,你的可能只是开启了nginx对js,png等内容进行自动gzip

987b5d

哈,太赞了!

都是 @quakewang 带的好头!

1232

赞 :plus1:

9800

你明明请求得是js文件,怎么会是text/css

377

#16楼 @pynix 真眼尖,我测试用的是css文件,但文字开头用的是js,所以i随手改了下文件名保持一致,我改一下

8043

😃 赞!最近 Ruby-China 上这些高质量的帖子层出不穷啊

5696

这个不错!!!

13073

对手机页面是福音,弄起来

5759

不错,赞一个。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册