# 14. gzip static 模塊探索
本站有一篇文章[nginx之gzip壓縮提升網站性能(三)](http://www.rails365.net/articles/nginx-zhi-gzip-ya-suo-ti-sheng-wang-zhan-xing-neng-san)介紹過nginx中`ngx_http_gzip_module`這個模塊的使用,這個模塊主要是用來壓縮靜態資源或者任何響應內容的。而這篇文章主要介紹的是`ngx_http_gzip_static_module`這個模塊的使用。
它是這樣使用的:
```
location ~ ^/assets/ {
gzip_static on;
}
```
`assets`目錄下有很多靜態資源,比如js,css等文件。
我們使用strace工具來追蹤nginx worker進程的系統調用。
首先,查看一下nginx的進程號。
```
$ ps -ef | grep nginx
www-data 17187 24035 0 Jan26 ? 00:00:04 nginx: worker process
root 24035 1 0 Jan02 ? 00:00:00 nginx: master process /usr/sbin/nginx
```
可以看到nginx的worker進程的pid是17187。
使用strace追蹤相關的gz的信息。
```
sudo strace -p 17187 2>&1 | grep gz
```
我們使用curl工具嘗試訪問assets目錄下的靜態資源。
```
$ curl -I http://www.rails365.net/assets/application-66a0c9fef334cb918dbbe88caf095db309cb3806af50808f7216a500434b96ec.js
```
可以看到strace出現了一行信息。
```
$ sudo strace -p 17187 2>&1 | grep gz
open("/home/yinsigan/rails365/current/public/assets/application-66a0c9fef334cb918dbbe88caf095db309cb3806af50808f7216a500434b96ec.js.gz", O_RDONLY|O_NONBLOCK) = -1 ENOENT (No such file or directory)
```
它會嘗試打開找剛才那個js的靜態文件,不過后面加了gz作為后綴,也就是壓縮過的文件。這個模塊的作用就是首先會去找gz文件,找到的話就直接返回給客戶端,沒有找到,才用`ngx_http_gzip_module`這個模塊壓縮之后再返回。畢竟壓縮,再怎樣還是要消耗內存,消耗CPU的,如果原本就有gz文件,那肯定是會縮短處理時間的,這也正是這個模塊存在的意義。
來看一下assets目錄下的文件。
```
~/rails365/current/public/assets$ ls
application-66a0c9fef334cb918dbbe88caf095db309cb3806af50808f7216a500434b96ec.js
```
可以發現,果然是沒有任何gz文件存在的。
現在我們來生成gz文件,看看strace是如何輸出的。
我的應用是使用rails開發的,下面是一段自動生成gz文件腳本,從網上摘錄的。
```
# lib/tasks/assets.rake
namespace :assets do
desc "Create .gz versions of assets"
task :gzip => :environment do
zip_types = /\.(?:css|html|js|otf|svg|txt|xml)$/
public_assets = File.join(
Rails.root,
"public",
Rails.application.config.assets.prefix)
Dir["#{public_assets}/**/*"].each do |f|
next unless f =~ zip_types
mtime = File.mtime(f)
gz_file = "#{f}.gz"
next if File.exist?(gz_file) && File.mtime(gz_file) >= mtime
File.open(gz_file, "wb") do |dest|
gz = Zlib::GzipWriter.new(dest, Zlib::BEST_COMPRESSION)
gz.mtime = mtime.to_i
IO.copy_stream(open(f), gz)
gz.close
end
File.utime(mtime, mtime, gz_file)
end
end
# Hook into existing assets:precompile task
Rake::Task["assets:precompile"].enhance do
Rake::Task["assets:gzip"].invoke
end
end
```
生成gz文件:
```
$ mina "rake[assets:gzip]"
```
```
~/rails365/current/public/assets$ ls
application-66a0c9fef334cb918dbbe88caf095db309cb3806af50808f7216a500434b96ec.js
application-66a0c9fef334cb918dbbe88caf095db309cb3806af50808f7216a500434b96ec.js.gz
```
需要注意的事,別對二進制文件,比如圖片做gz壓縮,因為沒有任何意義。
再次用curl工具訪問,可以看到strace的輸出:
```
$ sudo strace -p 17187 2>&1 | grep gz
open("/home/yinsigan/rails365/current/public/assets/application-66a0c9fef334cb918dbbe88caf095db309cb3806af50808f7216a500434b96ec.js.gz", O_RDONLY|O_NONBLOCK) = 9
```
可見,已經不會提示文件找不到了。
完結。