Nginx+Lua+FastDFS+Docker實現圖片縮略圖

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
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章