1. 程式人生 > >通過tfs-nginx進行圖片壓縮過程

通過tfs-nginx進行圖片壓縮過程

tfs 壓縮 lua

TFS是一個高可擴展、高可用、高性能、面向互聯網服務的分布式文件系統,主要針對海量的非結構化數據,它構築在普通的Linux機器 集群上,可為外部提供高可靠和高並發的存儲訪問。TFS為淘寶提供海量小文件存儲,通常文件大小不超過1M,滿足了淘寶對小文件存儲的需求,被廣泛地應用 在淘寶各項應用中。它采用了HA架構和平滑擴容,保證了整個文件系統的可用性和擴展性。同時扁平化的數據組織結構,可將文件名映射到文件的物理地址,簡化了文件的訪問流程,一定程度上為TFS提供了良好的讀寫性能。

NameServer主要功能是: 管理維護Block和DataServer相關信息,包括DataServer加入,退出, 心跳信息, block和DataServer的對應關系建立,解除。正常情況下,一個塊會在DataServer上存在, 主NameServer負責Block的創建,刪除,復制,均衡,整理, NameServer不負責實際數據的讀寫,實際數據的讀寫由DataServer完成。

DataServer主要功能是: 負責實際數據的存儲和讀寫。

原理:https://my.oschina.net/zimingforever/blog/174879

當客戶端要上傳一個圖片,通過nameserver將圖片寫入dataserver中,在nameserver中保留文件的名字;當客戶端需要下載圖片時,通過訪問tfs-nginx去nameserver中找到該圖片,然後再去dataserver中下載。

在三臺虛擬機上分別安裝tfs-ns、tfs-ds、tfs-nginx

在nameserver,dataserver,nginx三部分都安裝好後,來研究一下將圖片進行壓縮的代碼過程,下面是項目真實環境,可以直接訪問圖片並壓縮到對應的大小格式

在tfs-nginx安裝了lua模塊,在tfs-nginx中添加配置文件lua.conf。在主配置文件中加載lua.conf

下面是lua.conf文件中的一部分內容,編寫了將圖片壓縮的過程

#$filePath /Disk/tfsimage/xxxxxxxx.jpg.20x20.jpg
#$reqPath /xxxxxxxx.jpg.20x20.jpg
#$filename xxxxxxxx.jpg
#$file /Disk/tfsimage/xxxxxxxx.jpg.20x20.jpg
#$fileone  /Disk/tfsimage/xxxxxxxx.jpg
#定義變量
set $image_root /Disk/tfsimage;
#這則匹配是否是我們要的格式
if ($uri ~* "/images/([0-9a-zA-Z_!]+).(([^.]+).*)") {
set $filePath "$image_root/$1.$2";
set $reqPath  "/$1.$2";
set $filename "$1.$3";
}
set $file "$image_root$reqPath";
set $fileone "$image_root/$filename";
#lua語法入口
rewrite_by_lua ‘
#定義方法file_exists
function file_exists(name)
#以只讀模式打開一個文件
local f=io.open(name,"r")
# 打開的文件是否不等於空,如果不等於空證明之前有這個文件,關閉文件並返回真;如果等於空則返回假;
if f~=nil then io.close(f) return true else return false end
end ;
#定義方法tfsfile
function  tfsfile(name)
# 把嘆號替換成點,並把替換後的字符串復制給res
local res =string.gsub(name,"!",".");
#返回res
return res;
end;
# 首先更改圖片名字中的嘆號,在判斷圖片是否存在,如果存在就重定向到innerImages
if file_exists(tfsfile(ngx.var.file)) then  ngx.req.set_uri("/innerImages" .. tfsfile(ngx.var.reqPath), true);
else
# 如果不存在,則判斷源文件在不在,如果在打印111
if file_exists(tfsfile(ngx.var.fileone)) then print("111") else
# 如果不在,首先把圖片名字中的嘆號替換,然後把圖片名字賦值給resfile
local resfile = tfsfile(ngx.var.filename);
# 定義命令command,下載需要的圖片
command = string.format("wget -P /Disk/tfsimage/ http://192.168.1.244:8080/v1/tfs/"..resfile)
# 執行剛才定義的command命令
os.execute(command)
#定義命令commandt,給下載的圖片打水印(/Disk/jinlejia.png 水印圖;/Disk/tfsimage/原圖;/Disk/tfsimage/打水印後的圖)
commandt = "gm composite -gravity center -dissolve 70 /Disk/jinlejia.png /Disk/tfsimage/".. ngx.var.filename ..  " /Disk/tfsimage/"..ngx.var.filename;
#執行commandt命令
os.execute(commandt)
end;
#定義變量originalUri,area
local originalUri;
local area;
#將圖片名中嘆號替換,在filepath中找到20x20.jpg的索引位置,並賦值給index
local index = string.find(tfsfile(ngx.var.filePath), "([0-9]+)x([0-9]+)");
#如果index為空,則originalUri=嘆號替換後的filePath
if index==nil then  originalUri = tfsfile(ngx.var.filePath);
else
#如果index存在,首先把圖片名字中的嘆號替換,將filepath從頭截取到20x20.jpg的索引位置的前兩位,也就是/Disk/tfsimage/xxxxxxxx.jpg,將值賦給originalUri
originalUri = string.sub(tfsfile(ngx.var.filePath), 0, index-2);
#首先把圖片名字中的嘆號替換,將filePath的20x20.jpg截取出來並賦給area
area = string.sub(tfsfile(ngx.var.filePath), index);
#在area中,也就是20x20.jpg中找到“.”的索引位置,將索引位置賦值給index
index = string.find(area, "([.])");
#將area截取到“.”的前一位,就是20x20,並賦值給新的area
area = string.sub(area, 0, index-1);
end
#定義變量image_sizes,存放圖片的規格
local image_sizes={"100x66","105x70","1200x125","1200x260","1200x320","130x45","140x165","185x123","190x126","200x133","205x135","210x140","214x142","220x146","220x180","290x193","395x90","400x340","595x130","60x60","600x320","650x240","912x95","105x90","130x130","360x200","200x200","370x246","600x600","250x200","600x400","670x420","100x100","160x160","80x80","200x150","80x45","138x84","820x425","290x204","810x497","90x90","260x160","290x178","450x280","380x240","596x276","292x346","292x178","292x345","294x346","294x182","294x272","290x276","320x180","620x382","120x40","300x180","80x50","360x194","550x337","800x600"};
#定義方法,如果得到的area與image_sizes中的某個大小匹配的話,返回真
function table.contains(table, element)
#將table中的值進行循環,挨個與element匹配
for _, value in pairs(table) do
#如果匹配上則返回真,否則返回假
if value == element then
return true
end
end
return false
end
#如果area與image_sizes中的某個大小匹配的話
if table.contains(image_sizes, area) then
# 定義命令command ,將原圖壓縮成對應的大小 
local command = "gm convert " ..  originalUri  .. " -thumbnail " .. area .. " -background white -gravity center -extent " .. area .. " " .. tfsfile(ngx.var.file);
# 執行剛才定義的command命令
os.execute(command);
#如果圖片沒有壓縮,執行上面的一系列壓縮過程,然後重定向
ngx.req.set_uri("/innerImages" .. tfsfile(ngx.var.reqPath), true);
else
#如果能夠找到壓縮過的圖片,直接重定向
ngx.req.set_uri("/innerImages" .. tfsfile(ngx.var.reqPath), true);
end;
end
‘;
}

瀏覽器訪問路徑為tfs-nginxIP地址/image/圖片名.jpg

若要訪問壓縮的圖片,訪問tfs-nginxIP地址/image/圖片名.jpg.800x600.jpg即可




通過tfs-nginx進行圖片壓縮過程