隨着互聯網的快速發展、需求頻繁變動、內容數量的俱增、時間的持續增加,圖片數量也會愈來愈多。在實際需求中,會出如今若干個頁面或同一個頁面不一樣位置,展現同一條信息以及其縮略圖。在這時,若是使用 CSS 控制圖片顯示的大小,對於那些與該位置不成比例的圖片,縮小後就會出現圖片變形。也不可能讓編輯人員,對全部的圖片進行 PS,這時候就產生了強烈的自動化裁剪、縮放圖片的需求,來適應不一樣規格的縮略圖。
Nginx 雖然有自帶的 image filter module 也能實現此功能,可是有弊端:javascript
image filter module 使用的是 GD,GD 性能、效率、處理後的圖片質量不如 GraphicsMagickcss
image filter module 無法真正生成裁剪/縮放後的圖片,而是經過 Nginx 直接輸出的,這樣每次請求或緩存過時後都須要從新裁剪/縮放,這樣無疑會增長 Nginx 負擔
html
操做系統
java
CPU
linux
內存
nginx
磁盤及分區
git
Tengine:https://github.com/alibaba/tenginegithub
Lua:http://www.lua.org/ftp/web
LuaJIT: http://luajit.org/download.htmlshell
libjpeg、libjpeg-devel
libpng、libpng-devel
giflib、giflib-devel
freetype、freetype-devel
GraphicsMagick:http://sourceforge.net/projects/graphicsmagick/files/graphicsmagick/
readline&readline-devel(Lua 所需)
yum install readline yum install readline-devel
Lua
進入 Lua 源碼目錄
make 會提示相似如下信息:
make
make PLATFORM(例如你的操做系統是Linux,就執行:make linux,若是是 FreeBSD,就執行:make freebsd)
make linux make install
LuaJIT
make make install
Tengine
進入 Tengine 源碼目錄
./configure --prefix=/usr/local/Tengine --dso-path=/usr/local/Tengine/modules --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_concat_module --with-http_lua_module --with-openssl=/usr/local/src/openssl-1.0.1e --with-zlib=/usr/local/src/zlib-1.2.8 --http-proxy-temp-path=/var/tmp/Tengine/proxy_temp --http-fastcgi-temp-path=/var/tmp/Tengine/fastcgi_temp --http-uwsgi-temp-path=/var/tmp/Tengine/uwsgi_temp --http-scgi-temp-path=/var/tmp/Tengine/cgi_temp --http-client-body-temp-path=/var/tmp/Tengine/client_body_temp --http-log-path=/var/log/Tengine/access.log --error-log-path=/var/log/Tengine/error.log make make install
紅色加粗是關鍵部分,其他爲個人其它配置,不是該問題討論範圍以內
若是報有下面錯誤
src/http/modules/lua/ngx_http_lua_log.c: 在函數‘ngx_http_lua_ngx_log’中: src/http/modules/lua/ngx_http_lua_log.c:40: 錯誤:‘LUA_GLOBALSINDEX’未聲明(在此函數內第一次使用) src/http/modules/lua/ngx_http_lua_log.c:40: 錯誤:(即便在一個函數內屢次出現,每一個未聲明的標識符在其 src/http/modules/lua/ngx_http_lua_log.c:40: 錯誤:所在的函數內也只報告一次。) src/http/modules/lua/ngx_http_lua_log.c: 在函數‘ngx_http_lua_print’中: src/http/modules/lua/ngx_http_lua_log.c:81: 錯誤:‘LUA_GLOBALSINDEX’未聲明(在此函數內第一次使用)
時,是由於使用了不兼容的 Lua 的頭文件,configure 須要加上
--with-ld-opt="-Wl,-rpath,$LUAJIT_LIB"
或者
--with-luajit-inc=PATH set LuaJIT headers path (where lua.h/lauxlib.h/... are located) --with-luajit-lib=PATH set LuaJIT library path (where libluajit-5.1.{a,so} are located)
若是在啓動或者執行 Tengine 任意命令時,出現以上錯誤,那麼就是,沒法找到動態庫 libluajit-5.1.so.2 ,64位系統貌似是去 /lib64 目錄中尋找動態庫的。
那麼解決辦法就是,將 /usr/local/lib/libluajit-5.1.so.2 軟鏈接到 /lib64 目錄下:
ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
libjpeg、libjpeg-devel
yum install libjpeg yum install libjpeg-devel
libpng、libpng-devel
yum install libpng yum install libpng-devel
giflib、giflib-devel
yum install giflib yum install giflib-devel
freetype、freetype-devel
yum install freetype yum install freetype-devel
GraphicsMagick
./configure --prefix=/usr/local/GraphicsMagick --enable-shared make make install
執行
/usr/local/GraphicsMagick/bin/gm version
若是獲得
則,說明安裝成功!!!
local command = "/usr/local/GraphicsMagick/bin/gm convert " .. ngx.var.request_filepath .. " -resize " .. ngx.var.width .. "x" .. ngx.var.height .. " +profile \"*\" " .. ngx.var.request_filepath .. "_" .. ngx.var.width .. "x" .. ngx.var.height .. "." .. ngx.var.ext; // 調用 GraphicsMagick 進行圖片轉換,相關信息查看 GraphicsMagick 幫助文檔 os.execute(command); // 執行裁剪命令 ngx.exec(ngx.var.request_uri); // 輸出裁剪後的圖片 // ngx.var.request_filepath、ngx.var.width、ngx.var.height 即 Nginx location 中設置的變量
#group web; user web; worker_processes 12; error_log /var/log/Tengine/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; pid /var/run/nginx.pid; events { use epoll; worker_connections 1024; } http { include mime.types; default_type html/html; charset UTF-8; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/Tengine/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; client_max_body_size 10M; gzip on; gzip_min_length 1k; gzip_buffers 5 12k; gzip_http_version 1.0; gzip_comp_level 2; gzip_vary on; gzip_types text/plain text/css text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml application/xml-dtd image/gif image/jpeg image/png ima ge/x-icon image/bmp image/x-ms-bmp text/javascript application/x-javascript; include "vhosts.conf"; }
server { listen 80; server_name hostname; location / { root /document_root; # 站點根目錄 expires 1h; # 緩存時間 add_header Cache-Control max-age=3600; # 緩存時間 access_log /var/log/Tengine/host_access.log; } # 若是 url 格式如:xxxx.gif_數字x數字.gif location ~* ^(.+\.(jpg|jpeg|gif|png))_(\d+)x(\d+)\.(jpg|jpeg|gif|png)$ { root /document_root; # 這裏必須設置,不然根目錄,即 $document_root 會是 Nginx 默認的 Nginx Root/html,在 Lua 中會得不到指望的值 if (!-f $request_filename) { # 若是文件不存在時才須要裁剪 add_header X-Powered-By 'Lua GraphicsMagick'; # 此 HTTP Header 無實際意義,用於測試 add_header file-path $request_filename; # 此 HTTP Header 無實際意義,用於測試 lua_code_cache off; # 在編寫外部 Lua 腳本時,設置爲 off Nginx 不會緩存 Lua,方便調試 set $request_filepath /document_root/$1; # 設置原始圖片路徑,如:/document_root/1.gif set $width $3; # 設置裁剪/縮放的寬度 set $height $4; # 設置裁剪/縮放的高度 set $ext $5; # 圖片文件格式後綴 content_by_lua_file /document_root/ImageResizer.lua; # 加載外部 Lua 文件 } } }
測試腳本(Lua,修改一下 /document_root/ImageResizer.lua 在作測試時生成隨機圖片)
local command = "/usr/local/GraphicsMagick/bin/gm convert " .. ngx.var.request_filepath .. " -resize " .. ngx.var.width .. "x" .. ngx.var.height .. " +profile \"*\" " .. ngx.var.request_filepath .. "_" .. math.random(0, 100000000) .. ngx.var.width .. "x" .. ngx.var.height .. "." .. ngx.var.ext; os.execute(command); ngx.req.set_uri(ngx.var.request_uri, true);
測試網絡環境:局域網
測試工具: Apache AB
測試方法:
ab -n 100 -c 1 image_url
測試結果(哎!前先後後、斷斷續續測試+整理內容,花了四五個小時)
A、GIF (大圖)
啓用 poll 測試結果
未啓用 poll 測試結果
B、GIF (小圖)
啓用 poll 測試結果
未啓用 poll 測試結果
C、JPEG(大圖)
啓用 poll 測試結果
未啓用 poll 測試結果
D、JPEG(小圖)
啓用 poll 測試結果
未啓用 poll 測試結果
E、PNG(大圖)
啓用 poll 測試結果
未啓用 poll 測試結果
F、PNG(小圖)
啓用 poll 測試結果
未啓用 poll 測試結果
G、照片原始圖片
啓用 poll 測試結果
未啓用 poll 測試結果