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