OpenResty(Nginx)+Lua+GraphicsMagick實現縮略圖功能

本文來源於  http://www.hopesoft.org/blog/?p=1188

一、背景說明
大多數網站基本都涉及到圖片縮略圖的處理,比如新聞配圖、電商商品圖等,特別是電商類網站,每個商品圖對應多個不同尺寸的縮略圖,用於不同的頁面。

初期訪問量少時,處理流程一般由web程序在上傳成功後,同時生成相應縮略圖。這種方式在訪問量小,單機部署時沒有問題。當訪問量逐漸加大,服務器由單臺變爲多臺時,這種方式擴展性較差。

以下有幾種方案可以解決這個問題:
1、使用七牛又拍雲提供的雲存儲及數據處理服務,解決圖片的處理、存儲、多節點訪問速度的問題,這種方式優點是方案成熟,相應的有一定費用和開發工作,另外有一些小概率的風險,比如雲服務掛掉影響本站訪問。
2、使用第三方的圖片處理程序,比如zimg,點擊查看使用手冊@招牌瘋子開發。zimg的性能和擴展性不錯,文檔也很完善,會繼續保持關注。
3、自己造輪子,根據自身業務,將生成縮略圖功能獨立出來,與web程序解耦。

我們採用的是第三種方案,參考了網友的基礎代碼,利用OpenResty(Nginx)+Lua+GraphicsMagick實現縮略圖功能,圖片上傳及刪除還是由web程序處理,縮略圖由單獨模塊完成。目前可實現配置路徑及縮略尺寸,無圖片時顯示默認圖片,支持多種縮放方式等,後續可基於GraphicsMagick實現更多功能

二、相關規範
1、文件夾規劃

其中img.hopesoft.org爲圖片站點根目錄,avatars和photos目錄是原圖目錄,可根據目錄設置不同的縮略圖尺寸,default文件夾的notfound.jpg文件是在未找到原圖時的默認圖片,thumbnail文件夾用來存放縮略圖,可定時清理。

2、鏈接地址
原圖訪問地址:http://img.hopesoft.org/photos/001/001.jpg
縮略圖訪問地址:http://img.hopesoft.org/photos/001/001_100x100.jpg,(請勿加thumbnail,這個是因爲我們原來的原圖和縮略圖在同一個目錄,後來將縮略圖單獨放了一個文件夾)
不同目錄可設置不同的縮略圖規則,如:
原圖訪問地址:http://img.xxx.com/mall/001/001.jpg
縮略圖訪問地址:http://img.xxx.com/mall/001/001.jpg_100x100.jpg (請勿加thumbnail)

3、訪問流程
首先判斷縮略圖是否存在,如存在則直接顯示縮略圖;
如不存在則按以下流程處理:

  1. 判斷縮略圖鏈接與規則是否匹配,如不匹配,則404退出;如匹配跳至2
  2. 判斷原圖是否存在,如原圖存在則跳至5,如不存在則進入下一步;
  3. 判斷是否顯示默認圖片,如不顯示則404退出;如顯示則進入下一步
  4. 判斷是否存在默認圖片,如不存在則404退出;如存在則將默認圖片代替原始圖片,進入下一步;
  5. 拼接graphicsmagick命令,生成並顯示縮略圖

三、安裝OpenResty
1、關於OpenResty(http://openresty.org/cn/

OpenResty (也稱爲 ngx_openresty)是一個全功能的 Web 應用服務器,它打包了標準的 Nginx 核心,很多的常用的第三方模塊,以及它們的大多數依賴項。
OpenResty 通過匯聚各種設計精良的 Nginx 模塊,
從而將 Nginx 有效的變成一個強大的 Web 應用服務器,
這樣, Web 開發人員可以使用 Lua 腳本語言調動 Nginx 支持的各種C以及Lua 模塊,
快速構造出足以勝任 10K+ 併發連接響應的超高性能Web 應用系統。更多

2、安裝OpenResty
注:drizzle-nginx-module模塊和nginx-http-concat模塊非必選項,各位可按需安裝

3、將OpenResty(Nginx)加入自啓動

文件內容如下

把nginx加入chkconfig,並設置開機啓動

啓動、停止、查看狀態

四、安裝GraphicsMagick
1、安裝

下載libjpeg、libpng、freetype鏈接如失效可訪問:http://www.filewatcher.com/m/libjpeg-6b.tar.gz.961981-0.html

2、用法

原始圖片是input.jpg,尺寸:160×120

1)只縮小不放大

加了>,表示只有當圖片的寬與高,大於給定的寬與高時,才進行“縮小”操作。
生成的圖片大小是:160×120,未進行操作
如果不加>,會導致圖片被比等放大。

2)等比縮圖 (缺點:產生白邊)

生成的圖片大小是:100×75

3)非等比縮圖,按給定的參數縮圖(缺點:長寬比會變化)

生成的圖片大小是:100×100

4)裁剪後保證等比縮圖 (缺點:裁剪了圖片的一部分)

生成的圖片大小是:100×100,還保證了比例。不過圖片經過了裁剪,剪了圖片左右兩邊才達到1:1

5)填充後保證等比縮圖 (缺點:要填充顏色,和第一種方法基本一樣)

生成的圖片大小是:100×100,還保證了比例,同時沒有對圖片進行任何裁剪,缺失的部分按指定顏色進行填充。

6)裁剪、填充相結合 (缺點:最差的方法)

生成的圖片大小是:100×100,這次保證了大小和比例,其中的10000就是100×100的乘積,同時在填充和裁剪之間做了一個平衡。

7)位深度32 轉爲24
IE6,7,8不支持顯示“位深度32”的圖片,但IE9、火狐、谷歌瀏覽器就可以顯示。
使用GM,把“位深度32”的圖片轉換爲“位深度24”的圖片
輸入圖片zzz.jpg就是“位深度32”的圖片,輸出圖片 zzz_out.jpg就是“位深度24”的圖片

轉完後,圖片的顏色會有輕微變化。

更多請參考:http://elf8848.iteye.com/blog/382528

五、相關配置及腳本
1、Nginx配置文件

2、Lua腳本
/usr/local/openresty/nginx/lua/thumbnail.lua

/usr/local/openresty/nginx/lua/config.lua

六、監控腳本

我們的文件上傳和刪除由web程序來完成,當web程序刪除原始文件時,需要同時刪除縮略圖,我們使用Linux的inotify來監控原始文件的變化,當有文件修改或刪除時,刪除相應的縮略圖(注:inotify需要linux的內核版本大於等於2.6.13)。

腳本文件/home/shell/monitor_thumbnail.sh內容如下:

關於inotify的更多資料,請參考:http://www.1987.name/637.html

七、參考文檔
1、OpenResty官網
http://openresty.com/cn/index.html
2、HttpLuaModule模塊介紹
http://wiki.nginx.org/HttpLuaModule
3、[老王]Nginx與Lua
http://huoding.com/2012/08/31/156
4、[老王]嘗試使用GraphicsMagick的縮略圖功能
http://hi.baidu.com/thinkinginlamp/item/753d86383545d10fcfb9fe14
5、GraphicsMagick安裝及使用
http://www.cnblogs.com/javapro/archive/2013/04/28/3048393.html
6、Lua程序設計
http://book.luaer.cn/
7、靈活自定義縮略圖片尺寸大小方案分享(nginx,lua_nginx,GraphicsMagick)
http://www.iteye.com/topic/1125126
8、揭​祕​淘​寶​2​8​6​億​海​量​圖​片​存​儲​與​處​理​架​構
http://wenku.baidu.com/view/7dc77b2e7375a417866f8ff0.html
9、django-nginx-image
https://github.com/adw0rd/django-nginx-image
10、Lua中的正則表達式
http://blog.sina.com.cn/s/blog_512f462201016u3b.html

八、示例圖片(圖片來自老王博客)

原始圖片(160×120)

1、填充後保證等比縮圖(sizes={’350×350′} )

2、等比縮圖(sizes={’300x300_’})

3、非等比縮圖,按給定的參數縮圖,長寬比會變化(sizes={’250×250!’})

4、裁剪後保證等比縮圖,裁剪了圖片的一部分(sizes={’50×50^’})

5、只縮小不放大(sizes={’100×100>’})

6、限制寬度,只縮小不放大(比如網頁版圖片用於手機版時)(sizes={’140×140$’})

原圖不存在時
1、當配置顯示默認圖片,且路徑及縮略圖尺寸符合時,用默認圖片填充

2、當配置不顯示默認圖片或路徑及縮略圖尺寸不符合時,返回404

九、Github
項目地址:https://github.com/hopesoft/nginx-lua-image-module
問題反饋:https://github.com/hopesoft/nginx-lua-image-module/issues



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