天天看点

通过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,如需转载请自行联系原作者