天天看點

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

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,如需轉載請自行聯系原作者