TFS是一個高可擴充、高可用、高性能、面向網際網路服務的分布式檔案系統,主要針對海量的非結構化資料,它構築在普通的Linux機器 叢集上,可為外部提供高可靠和高并發的存儲通路。TFS為淘寶提供海量小檔案存儲,通常檔案大小不超過1M,滿足了淘寶對小檔案存儲的需求,被廣泛地應用 在淘寶各項應用中。它采用了HA架構和平滑擴容,保證了整個檔案系統的可用性和擴充性。同時扁平化的資料組織結構,可将檔案名映射到檔案的實體位址,簡化了檔案的通路流程,一定程度上為TFS提供了良好的讀寫性能。
NameServer主要功能是: 管理維護Block和DataServer相關資訊,包括DataServer加入,退出, 心跳資訊, block和DataServer的對應關系建立,解除。正常情況下,一個塊會在DataServer上存在, 主NameServer負責Block的建立,删除,複制,均衡,整理, NameServer不負責實際資料的讀寫,實際資料的讀寫由DataServer完成。
DataServer主要功能是: 負責實際資料的存儲和讀寫。
當用戶端要上傳一個圖檔,通過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檔案中的一部分内容,編寫了将圖檔壓縮的過程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<code>#$filePath /Disk/tfsimage/xxxxxxxx.jpg.20x20.jpg</code>
<code>#$reqPath /xxxxxxxx.jpg.20x20.jpg</code>
<code>#$filename xxxxxxxx.jpg</code>
<code>#$file /Disk/tfsimage/xxxxxxxx.jpg.20x20.jpg</code>
<code>#$fileone /Disk/tfsimage/xxxxxxxx.jpg</code>
<code>#定義變量</code>
<code>set</code> <code>$image_root </code><code>/Disk/tfsimage</code><code>;</code>
<code>#這則比對是否是我們要的格式</code>
<code>if</code> <code>($uri ~* </code><code>"/images/([0-9a-zA-Z_!]+).(([^.]+).*)"</code><code>) {</code>
<code>set</code> <code>$filePath </code><code>"$image_root/$1.$2"</code><code>;</code>
<code>set</code> <code>$reqPath </code><code>"/$1.$2"</code><code>;</code>
<code>set</code> <code>$filename </code><code>"$1.$3"</code><code>;</code>
<code>}</code>
<code>set</code> <code>$</code><code>file</code> <code>"$image_root$reqPath"</code><code>;</code>
<code>set</code> <code>$fileone </code><code>"$image_root/$filename"</code><code>;</code>
<code>#lua文法入口</code>
<code>rewrite_by_lua '</code>
<code>#定義方法file_exists</code>
<code>function</code> <code>file_exists(name)</code>
<code>#以隻讀模式打開一個檔案</code>
<code>local</code> <code>f=io.</code><code>open</code><code>(name,</code><code>"r"</code><code>)</code>
<code># 打開的檔案是否不等于空,如果不等于空證明之前有這個檔案,關閉檔案并傳回真;如果等于空則傳回假;</code>
<code>if</code> <code>f~=nil </code><code>then</code> <code>io.close(f) </code><code>return</code> <code>true</code> <code>else</code> <code>return</code> <code>false</code> <code>end</code>
<code>end ;</code>
<code>#定義方法tfsfile</code>
<code>function</code> <code>tfsfile(name)</code>
<code># 把歎号替換成點,并把替換後的字元串複制給res</code>
<code>local</code> <code>res =string.gsub(name,</code><code>"!"</code><code>,</code><code>"."</code><code>);</code>
<code>#傳回res</code>
<code>return</code> <code>res;</code>
<code>end;</code>
<code># 首先更改圖檔名字中的歎号,在判斷圖檔是否存在,如果存在就重定向到innerImages</code>
<code>if</code> <code>file_exists(tfsfile(ngx.var.</code><code>file</code><code>)) </code><code>then</code> <code>ngx.req.set_uri(</code><code>"/innerImages"</code> <code>.. tfsfile(ngx.var.reqPath), </code><code>true</code><code>);</code>
<code>else</code>
<code># 如果不存在,則判斷源檔案在不在,如果在列印111</code>
<code>if</code> <code>file_exists(tfsfile(ngx.var.fileone)) </code><code>then</code> <code>print(</code><code>"111"</code><code>) </code><code>else</code>
<code># 如果不在,首先把圖檔名字中的歎号替換,然後把圖檔名字指派給resfile</code>
<code>local</code> <code>resfile = tfsfile(ngx.var.filename);</code>
<code># 定義指令command,下載下傳需要的圖檔</code>
<code>command</code> <code>= string.</code><code>format</code><code>(</code><code>"wget -P /Disk/tfsimage/ http://192.168.1.244:8080/v1/tfs/"</code><code>..resfile)</code>
<code># 執行剛才定義的command指令</code>
<code>os.execute(</code><code>command</code><code>)</code>
<code>#定義指令commandt,給下載下傳的圖檔打水印(/Disk/jinlejia.png 水印圖;/Disk/tfsimage/原圖;/Disk/tfsimage/打水印後的圖)</code>
<code>commandt = </code><code>"gm composite -gravity center -dissolve 70 /Disk/jinlejia.png /Disk/tfsimage/"</code><code>.. ngx.var.filename .. </code><code>" /Disk/tfsimage/"</code><code>..ngx.var.filename;</code>
<code>#執行commandt指令</code>
<code>os.execute(commandt)</code>
<code>#定義變量originalUri,area</code>
<code>local</code> <code>originalUri;</code>
<code>local</code> <code>area;</code>
<code>#将圖檔名中歎号替換,在filepath中找到20x20.jpg的索引位置,并指派給index</code>
<code>local</code> <code>index = string.</code><code>find</code><code>(tfsfile(ngx.var.filePath), </code><code>"([0-9]+)x([0-9]+)"</code><code>);</code>
<code>#如果index為空,則originalUri=歎号替換後的filePath</code>
<code>if</code> <code>index==nil </code><code>then</code> <code>originalUri = tfsfile(ngx.var.filePath);</code>
<code>#如果index存在,首先把圖檔名字中的歎号替換,将filepath從頭截取到20x20.jpg的索引位置的前兩位,也就是/Disk/tfsimage/xxxxxxxx.jpg,将值賦給originalUri</code>
<code>originalUri = string.sub(tfsfile(ngx.var.filePath), 0, index-2);</code>
<code>#首先把圖檔名字中的歎号替換,将filePath的20x20.jpg截取出來并賦給area</code>
<code>area = string.sub(tfsfile(ngx.var.filePath), index);</code>
<code>#在area中,也就是20x20.jpg中找到“.”的索引位置,将索引位置指派給index</code>
<code>index = string.</code><code>find</code><code>(area, </code><code>"([.])"</code><code>);</code>
<code>#将area截取到“.”的前一位,就是20x20,并指派給新的area</code>
<code>area = string.sub(area, 0, index-1);</code>
<code>end</code>
<code>#定義變量image_sizes,存放圖檔的規格</code>
<code>local</code> <code>image_sizes={</code><code>"100x66"</code><code>,</code><code>"105x70"</code><code>,</code><code>"1200x125"</code><code>,</code><code>"1200x260"</code><code>,</code><code>"1200x320"</code><code>,</code><code>"130x45"</code><code>,</code><code>"140x165"</code><code>,</code><code>"185x123"</code><code>,</code><code>"190x126"</code><code>,</code><code>"200x133"</code><code>,</code><code>"205x135"</code><code>,</code><code>"210x140"</code><code>,</code><code>"214x142"</code><code>,</code><code>"220x146"</code><code>,</code><code>"220x180"</code><code>,</code><code>"290x193"</code><code>,</code><code>"395x90"</code><code>,</code><code>"400x340"</code><code>,</code><code>"595x130"</code><code>,</code><code>"60x60"</code><code>,</code><code>"600x320"</code><code>,</code><code>"650x240"</code><code>,</code><code>"912x95"</code><code>,</code><code>"105x90"</code><code>,</code><code>"130x130"</code><code>,</code><code>"360x200"</code><code>,</code><code>"200x200"</code><code>,</code><code>"370x246"</code><code>,</code><code>"600x600"</code><code>,</code><code>"250x200"</code><code>,</code><code>"600x400"</code><code>,</code><code>"670x420"</code><code>,</code><code>"100x100"</code><code>,</code><code>"160x160"</code><code>,</code><code>"80x80"</code><code>,</code><code>"200x150"</code><code>,</code><code>"80x45"</code><code>,</code><code>"138x84"</code><code>,</code><code>"820x425"</code><code>,</code><code>"290x204"</code><code>,</code><code>"810x497"</code><code>,</code><code>"90x90"</code><code>,</code><code>"260x160"</code><code>,</code><code>"290x178"</code><code>,</code><code>"450x280"</code><code>,</code><code>"380x240"</code><code>,</code><code>"596x276"</code><code>,</code><code>"292x346"</code><code>,</code><code>"292x178"</code><code>,</code><code>"292x345"</code><code>,</code><code>"294x346"</code><code>,</code><code>"294x182"</code><code>,</code><code>"294x272"</code><code>,</code><code>"290x276"</code><code>,</code><code>"320x180"</code><code>,</code><code>"620x382"</code><code>,</code><code>"120x40"</code><code>,</code><code>"300x180"</code><code>,</code><code>"80x50"</code><code>,</code><code>"360x194"</code><code>,</code><code>"550x337"</code><code>,</code><code>"800x600"</code><code>};</code>
<code>#定義方法,如果得到的area與image_sizes中的某個大小比對的話,傳回真</code>
<code>function</code> <code>table.contains(table, element)</code>
<code>#将table中的值進行循環,挨個與element比對</code>
<code>for</code> <code>_, value </code><code>in</code> <code>pairs(table) </code><code>do</code>
<code>#如果比對上則傳回真,否則傳回假</code>
<code>if</code> <code>value == element </code><code>then</code>
<code>return</code> <code>true</code>
<code>return</code> <code>false</code>
<code>#如果area與image_sizes中的某個大小比對的話</code>
<code>if</code> <code>table.contains(image_sizes, area) </code><code>then</code>
<code># 定義指令command ,将原圖壓縮成對應的大小 </code>
<code>local</code> <code>command</code> <code>= </code><code>"gm convert "</code> <code>.. originalUri .. </code><code>" -thumbnail "</code> <code>.. area .. </code><code>" -background white -gravity center -extent "</code> <code>.. area .. </code><code>" "</code> <code>.. tfsfile(ngx.var.</code><code>file</code><code>);</code>
<code>os.execute(</code><code>command</code><code>);</code>
<code>#如果圖檔沒有壓縮,執行上面的一系列壓縮過程,然後重定向</code>
<code>ngx.req.set_uri(</code><code>"/innerImages"</code> <code>.. tfsfile(ngx.var.reqPath), </code><code>true</code><code>);</code>
<code>#如果能夠找到壓縮過的圖檔,直接重定向</code>
<code>';</code>
浏覽器通路路徑為tfs-nginxIP位址/image/圖檔名.jpg
若要通路壓縮的圖檔,通路tfs-nginxIP位址/image/圖檔名.jpg.800x600.jpg即可
本文轉自 xinsir999 51CTO部落格,原文連結:http://blog.51cto.com/xinsir/1962611,如需轉載請自行聯系原作者