Nginx+Lua+FastDFS實現圖片縮略圖
1、Docker安裝
yum install docker -y
systemctl start docker #啓動docker
systemctl enable docker #開機啓動docker
systemctl status docker #查看docker狀態
docker version # 查看docker版本
DaoCloud 加速器 是廣受歡迎的 Docker 工具,解決了國內用戶訪問 Docker Hub 緩慢的問題。DaoCloud 加速器結合國內的 CDN 服務與協議層優化,成倍的提升了下載速度。
cat /etc/docker/daemon.json #修改這個文件爲如下內容
{
"registry-mirrors": [
"http://95822026.m.daocloud.io"
],
"insecure-registries": []
}
---------------------------------------------------------
或者用這條命令
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://95822026.m.daocloud.io
systemctl restart docker #事後重啓docker
2、Docker安裝FastDFS
2.1 搜索鏡像
docker search fastdfs #搜索fastdfs鏡像
2.2 拉取鏡像
docker pull delron/fastdfs #拉取最新版本的鏡像
2.3 查詢鏡像
docker images #查詢所有鏡像
2.4 容器安裝
1、使用docker鏡像構建tracker容器(跟蹤服務器,起到調度的作用):
docker run -d --privileged=true --network=host --name tracker -v /mydata/fdfs/tracker:/var/fdfs delron/fastdfs tracker
上面的命令是創建fastdfs的tracker容器並將容器內的文件存儲路徑映射到宿主機的/var/fdfs目錄。
2、使用docker鏡像構建storage容器(存儲服務器,提供容量和備份服務):
docker run -d --privileged=true --network=host --name storage -e TRACKER_SERVER=192.168.1.181:22122 -v /mydata/fdfs/storage:/var/fdfs -e GROUP_NAME=group1 delron/fastdfs storage
TRACKER_SERVER=本機的ip地址:22122 本機ip地址不要使用127.0.0.1。
2.5 修改配置
docker ps -a #查詢所有的鏡像
docker start + storage的CONTAINER ID
docker start + tracker的CONTAINER ID
docker exec -it storage /bin/bash
進入storage容器,到storage的配置文件中配置http訪問的端口,配置文件在/etc/fdfs目錄下的storage.conf。
3、實現方案
由於我這裏圖片處理用的是nginx,所以,有以下兩種解決方法:
- Nginx自帶的http_image_filter_module模塊
- Nginx搭配Lua+GraphicsMagick
Nginx 雖然有自帶的 image filter module 實現此功能,但是有弊端:
- image filter module 使用的是 GD,GD 性能、效率、處理後的圖片質量不如 GraphicsMagick、並且裁剪後也不會保存,這樣每次請求過來都要重新裁剪,所以訪問很慢。
- image filter module 沒法真正生成裁剪/縮放後的圖片,而是通過 Nginx 直接輸出的,這樣每次請求或緩存過期後都需要重新裁剪/縮放,這樣無疑會增加 Nginx 負擔
這裏使用Lua+GraphicsMagick實現圖片自由裁剪、把裁剪後的圖片放到一個目錄,並做好過期或定期刪除,訪問時就去判斷,有裁剪後的就取,沒有的再做裁剪。但是這樣也有個問題就是,用久了之後,會在本地硬盤產生很多縮略圖,對硬盤造成浪費,所以需要定時的清理硬盤下的縮略圖。
如果用Nginx來處理圖片的話,就會有以下的優缺點:
▲ 優點
- 操作簡單。通過簡單配置,省去了後端裁剪程序的複雜性。
- 實時裁剪。可以實時訪問在線裁剪圖片。
- 靈活性強。後端程序裁剪圖片時需要知道裁剪圖片的尺寸和質量,使用nginx裁剪可以實時裁剪任意尺寸的圖片。
- 不佔用硬盤空間。
▲ 缺點
- 消耗CPU和內存,訪問量大的時候就會給服務器帶來很大的負擔。(可以通過使用Nginx緩存和緩存服務器來解決)
- 功能不是很強大,支持的處理圖片類型只包括JPEG, GIF, PNG, or WebP
4、FastDFS鏡像中配置http_image_filter_module
4.1 安裝軟件基礎包
yum -y install epel-release git
yum install -y gcc gcc-c++ zlib zlib-devel openssl openssl-devel pcre pcre-devel gd-devel
yum install -y libpng libjpeg libpng-devel libjpeg-devel ghostscript libtiff libtiff-devel freetype freetype-devel readline-devel ncurses-devel
4.2 其他軟件下載
【注】需要下載的軟件有
- nginx-http-concat
- ngx_devel_kit
- lua-nginx-module
- LuaJIT-2.0.4
- lua-5.3.1
- GraphicsMagick-1.3.18
- nginx1.12.2 (鏡像中自帶)
下載軟件並進行解壓操作
cd /usr/lcoal/src
# 下載依賴包
git clone https://github.com/alibaba/nginx-http-concat.git
git clone https://github.com/simpl/ngx_devel_kit.git
git clone https://github.com/openresty/echo-nginx-module.git
git clone https://github.com/openresty/lua-nginx-module.git
git clone https://github.com/happyfish100/fastdfs-nginx-module.git
# 安裝LuaJIT
cd /usr/local/src
wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz
tar -zxf LuaJIT-2.0.4.tar.gz
cd LuaJIT-2.0.4
make
make install
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0
ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
# 安裝Lua
cd /usr/local/src
wget http://www.lua.org/ftp/lua-5.3.1.tar.gz
tar -zxvpf lua-5.3.1.tar.gz
cd lua-5.3.1
make linux && make install
# 安裝GM
cd /usr/local/src
wget ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/1.3/GraphicsMagick-1.3.18.tar.gz
tar -zxvf GraphicsMagick-1.3.18.tar.gz
cd GraphicsMagick-1.3.18
./configure --prefix=/usr/local/GraphicsMagick-1.3.18 --enable-shared
make && make install
ln -s /usr/local/GraphicsMagick-1.3.18 /usr/local/GraphicsMagick
由於鏡像中自帶nginx,在/tmp/nginx/nginx-1.12.2目錄下
cd /tmp/nginx/nginx-1.12.2
./configure --prefix=/usr/local/nginx-1.12.2 \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_sub_module \
--with-http_flv_module \
--with-http_dav_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_addition_module \
--add-module=/usr/local/src/fastdfs-nginx-module-master/src \
--with-http_image_filter_module \
--with-pcre \
--add-module=/usr/local/src/nginx-http-concat \
--add-module=/usr/local/src/lua-nginx-module-0.10.13 \
--add-module=/usr/local/src/ngx_devel_kit \
--add-module=/usr/local/src/echo-nginx-module \
--with-ld-opt=-Wl,-rpath,$LUAJIT_LIB
執行成功之後先執行make確保編譯沒有問題,成功之後make install
make
make install
cp /usr/local/nginx-1.12.2 /usr/local/nginx
4.3 配置Lua腳本實現剪切
在/usr/local/nginx/conf創建lua文件夾
cd /usr/local/nginx/conf
mkdir lua
# 創建lua腳本
vi fastdfs.lua
-- 寫入文件
local function writefile(filename, info)
local wfile=io.open(filename, "w") --寫入文件(w覆蓋)
assert(wfile) --打開時驗證是否出錯
wfile:write(info) --寫入傳入的內容
wfile:close() --調用結束後記得關閉
end
-- 檢測路徑是否目錄
local function is_dir(sPath)
if type(sPath) ~= "string" then return false end
local response = os.execute( "cd " .. sPath )
if response == 0 then
return true
end
return false
end
-- 檢測文件是否存在
local file_exists = function(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
-- 反向查找路徑
function last_find(str, k)
local ts = string.reverse(str);
local _, i = string.find(ts, k);
return string.len(ts) - i + 1;
end
local area = nil
local originalUri = ngx.var.uri;
local originalFile = ngx.var.file;
local index = last_find(ngx.var.uri, "([0-9]+)x([0-9]+)");
if index then
originalUri = string.sub(ngx.var.uri, 0, index-2);
area = string.sub(ngx.var.uri, index);
index = string.find(area, "([.])");
area = string.sub(area, 0, index-1);
local index = last_find(originalFile, "([0-9]+)x([0-9]+)");
originalFile = string.sub(originalFile, 0, index-2)
end
-- check original file
if not file_exists(originalFile) then
local fileid = string.sub(originalUri, 2);
-- main
local fastdfs = require('restyfastdfs')
local fdfs = fastdfs:new()
fdfs:set_tracker("62.234.0.169", 22122)
fdfs:set_timeout(1000)
fdfs:set_tracker_keepalive(0, 100)
fdfs:set_storage_keepalive(0, 100)
local data = fdfs:do_download(fileid)
if data then
-- check image dir
if not is_dir(ngx.var.image_dir) then
os.execute("mkdir -p " .. ngx.var.image_dir)
end
writefile(originalFile, data)
end
end
-- 創建縮略圖
local image_sizes = {"710x300","735x250","250x150","186x150","122x122","120x120","345x345","295x295","292x292","262x262","274x274","190x190","150x150","144x144","110x110","690x340","72x72","100x100","180x180","480x240","750x740","216x216","490x190","126x126"};
function table.contains(table, element)
for _, value in pairs(table) do
if value == element then
return true
end
end
return false
end
if table.contains(image_sizes, area) then
local bg;
if string.lower(string.sub(ngx.var.file,-3))=="jpg" then
bg=" -background white ";
else
bg=" -background transparent ";
end;
local command = "/usr/local/GraphicsMagick/bin/gm convert -quality 90 " .. originalFile .. " -thumbnail " .. area .. bg .. " -gravity center -extent " .. area .. " " .. ngx.var.file;
os.execute(command);
end;
if file_exists(ngx.var.file) then
--ngx.req.set_uri(ngx.var.uri, true);
ngx.exec(ngx.var.uri)
else
ngx.exit(404)
end
4. 4 配置nginx
nginx配置用戶
user root;
server {
listen 8801;
server_name 10.160.43.26;
# LUA
location /hello {
default_type 'text/plain';
content_by_lua 'ngx.say("hello,lua")';
}
# fastdfs 縮略圖生成
location /group1/M00 {
alias /data/fastdfs/data/data;
set $image_root "/data/fastdfs/data/data";
if ($uri ~ "/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/(.*)") {
set $image_dir "$image_root/$3/$4/";
set $image_name "$5";
set $file "$image_dir$image_name";
}
if (!-f $file) {
# # 關閉lua代碼緩存,方便調試lua腳本
#lua_code_cache off;
content_by_lua_file "/usr/local/nginx/conf/lua/fastdfs.lua";
}
ngx_fastdfs_module;
}
# log file
access_log logs/img_access.log access;
}
其中image_root爲fastdfs的儲存文件的目錄,如果容器目錄共享到宿主機,該配置可以爲宿主機共享的圖片保存地址。
配置完成,重啓Nginx。開始測試
訪問圖片地址,例如:http://192.168.1.108:8888/group1/M00/00/00/wKgBbF0LPYqAWeBcAAhGFpaR88k120.png。效果圖如下:
訪問縮略圖地址,地址如下:
http://192.168.1.108:8888/group1/M00/00/00/wKgBbF0LPYqAWeBcAAhGFpaR88k120.png_640x320.png