一、需求背景
互联网电商网站,大量不同需求的图片(同一个图片需要不同尺寸的缩略图),需要对图片进行处理。
二、解决方案
- 在上传图片时就生成所需缩略图。
- 根据请求指定尺寸的图片自动生成相应的缩略图(使用Tengine+Lua+GraphicsMagick实现)。
三、软件介绍
- Tengine : 淘宝改良的Nginx,并集成了Lua模块,负责展示图片和调度Lua脚本。
- Lua : 脚本语言,嵌入到应用程序中,提供灵活的扩展和定制功能;Tengine通过Lua实现对GraphicsMagick操作,控制裁 剪、缩放图片的规格等。
- GraphicsMagick : 强大的图片处理工具、没有UI的PS、动态生成图片,负责图片的处理。
四、软件安装
安装环境:CentOS7 64位
新建安装目录:mkdir -p /usr/local/soft
将介质上传到服务器后
解tar包:
cd /usr/local/soft
tar -zxvf lua-5.3.1.tar.gz
tar -zxvf LuaJIT-2.0.4.tar.gz
tar -zxvf GraphicsMagick-1.3.18.tar.gz
安装Lua:
安装Lua依赖(readline和readline-devel,使用yum安装):
yum install readline
yum install readline-devel
安装Lua:
cd lua-5.3.1
make linux
make install
安装LuaJIT:
cd LuaJIT-2.0.4
make
make install
安装Tengine:
yum安装相关依赖:
yum install gcc-c++
yum -y install pcre pcre-devel
yum -y install zlib zlib-devel
yum -y install openssl openssl-devel
cd tengine-master
./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 --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
报错:-bash: ./configure: Permission denied
赋权:chmod 777 configure
重新执行上面./configure..
make
make install
启动:/usr/local/Tengine/sbin/nginx
报错:/usr/local/Tengine/sbin/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory。
作软连接:ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
启动:/usr/local/Tengine/sbin/nginx
报错:nginx: [emerg] mkdir() "/var/tmp/Tengine/client_body_temp" failed (2: No such file or directory)
创建路径:mkdir -p /var/tmp/Tengine/client_body_temp
启动:/usr/local/Tengine/sbin/nginx 成功:
安装 GraphicsMagick:
安装依赖(yum安装):
yum install libjpeg libjpeg-devel libpg libpng-devel giflib giflib-devel freetype freetype-devel -y
安装 GraphicsMagick
cd GraphicsMagick-1.3.18
./configure --prefix=/usr/local/GraphicsMagick --enable-shared
make
make install
查看安装是否成功:/usr/local/GraphicsMagick/bin/gm -version
五、配置
Lua脚本文件(ImageResizer.lua):位置:/usr/local/Tengine/lua/ImageResizer.lua,需可执行权限。
mkdir -p /usr/local/Tengine/lua/
vim /usr/local/Tengine/lua/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 .. "_" .. ngx.var.width .. "x" .. ngx.var.height .. "." .. ngx.var.ext;
os.execute(command);
ngx.exec(ngx.var.request_uri);
保存退出。
授权:chmod 777 /usr/local/Tengine/lua/ImageResizer.lua
Tengine配置(nginx.conf文件)
user root;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
# load modules compiled as Dynamic Shared Object (DSO)
#
#dso {
# load ngx_http_fastcgi_module.so;
# load ngx_http_rewrite_module.so;
#}
http {
include mime.types;
default_type application/octet-stream;
#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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
root /data/gm/uploadimg;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /data/gm/uploadimg;
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 /data/gm/uploadimg; #这里必须设置,否则根目录,即 $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 on; #在编写外部 Lua脚本时,设置为off Nginx不会缓存 Lua,方便调试
set $request_filepath /data/gm/uploadimg/$1; #设置原始图片路径,如:/document_root/1.gif
set $width $3; # 设置裁剪/缩放的宽度
set $height $4; # 设置裁剪/缩放的高度
set $ext $5; # 图片文件格式后缀
content_by_lua_file /usr/local/Tengine/lua/ImageResizer.lua; #加载外部 Lua 文件
}
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
mkdir -p /data/gm/uploadimg
检测配置文件是否正确配置:/usr/local/Tengine/sbin/nginx -t
重启:/usr/local/Tengine/sbin/nginx -s reload
测试:
先将img01.jpg放到服务器/data/gm/uploadimg 目录下
http://服务IP/img01.jpg_200x200.jpg 成功。