随着互联网的快速发展、需求频繁变动、内容数量的俱增、时间的持续增加,图片数量也会愈来愈多。在实际需求中,会出如今若干个页面或同一个页面不一样位置,展现同一条信息以及其缩略图。在这时,若是使用 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 测试结果