Tengine + Lua + GraphicsMagick 實現圖片自動裁剪/縮放

1、背景

      隨着互聯網的快速發展、需求頻繁變動、內容數量的俱增、時間的持續增加,圖片數量也會愈來愈多。在實際需求中,會出如今若干個頁面或同一個頁面不一樣位置,展現同一條信息以及其縮略圖。在這時,若是使用 CSS 控制圖片顯示的大小,對於那些與該位置不成比例的圖片,縮小後就會出現圖片變形。也不可能讓編輯人員,對全部的圖片進行 PS,這時候就產生了強烈的自動化裁剪、縮放圖片的需求,來適應不一樣規格的縮略圖。
      Nginx 雖然有自帶的 image filter module 也能實現此功能,可是有弊端:javascript

  • image filter module 使用的是 GD,GD 性能、效率、處理後的圖片質量不如 GraphicsMagickcss

  • image filter module 無法真正生成裁剪/縮放後的圖片,而是經過 Nginx 直接輸出的,這樣每次請求或緩存過時後都須要從新裁剪/縮放,這樣無疑會增長 Nginx 負擔
    html

2、系統環境

  1. 操做系統



    java

  2. CPU



    linux

  3. 內存



    nginx

  4. 磁盤及分區



    git

3、軟件準備

4、軟件安裝

  1. readline&readline-devel(Lua 所需)

    yum install readline
    yum install readline-devel
  2. Lua

    • 進入 Lua 源碼目錄

    • make 會提示相似如下信息:

      make


    • make PLATFORM(例如你的操做系統是Linux,就執行:make linux,若是是 FreeBSD,就執行:make freebsd)

      make linux
      make install
  3. LuaJIT

    make
    make install
  4. 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
  5. libjpeg、libjpeg-devel

    yum install libjpeg
    yum install libjpeg-devel
  6. libpng、libpng-devel

    yum install libpng
    yum install libpng-devel
  7. giflib、giflib-devel

    yum install giflib
    yum install giflib-devel
  8. freetype、freetype-devel

    yum install freetype
    yum install freetype-devel
  9. GraphicsMagick

    ./configure --prefix=/usr/local/GraphicsMagick --enable-shared
    make
    make install

    執行

    /usr/local/GraphicsMagick/bin/gm version

    若是獲得


    則,說明安裝成功!!!
     

5、腳本編寫

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 中設置的變量

6、配置

#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 文件
                }
        }
}

7、測試

  1.     測試腳本(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);
  2. 測試網絡環境局域網

  3. 測試工具: Apache AB

  4. 測試方法:

    ab -n 100 -c 1 image_url
  5. 測試結果(哎!前先後後、斷斷續續測試+整理內容,花了四五個小時)

    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 測試結果

         

         

相關文章
相關標籤/搜索