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/tfsp_w_picpath/xxxxxxxx.jpg.20x20.jpg #$reqPath /xxxxxxxx.jpg.20x20.jpg #$filename xxxxxxxx.jpg #$file /Disk/tfsp_w_picpath/xxxxxxxx.jpg.20x20.jpg #$fileone /Disk/tfsp_w_picpath/xxxxxxxx.jpg #定义变量 set $p_w_picpath_root /Disk/tfsp_w_picpath; #这则匹配是否是我们要的格式 if ($uri ~* "/p_w_picpaths/([0-9a-zA-Z_!]+).(([^.]+).*)") { set $filePath "$p_w_picpath_root/$1.$2"; set $reqPath "/$1.$2"; set $filename "$1.$3"; } set $file "$p_w_picpath_root$reqPath"; set $fileone "$p_w_picpath_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/tfsp_w_picpath/ http://192.168.1.244:8080/v1/tfs/"..resfile) # 执行刚才定义的command命令 os.execute(command) #定义命令commandt,给下载的图片打水印(/Disk/jinlejia.png 水印图;/Disk/tfsp_w_picpath/原图;/Disk/tfsp_w_picpath/打水印后的图) commandt = "gm composite -gravity center -dissolve 70 /Disk/jinlejia.png /Disk/tfsp_w_picpath/".. ngx.var.filename .. " /Disk/tfsp_w_picpath/"..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/tfsp_w_picpath/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 #定义变量p_w_picpath_sizes,存放图片的规格 local p_w_picpath_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与p_w_picpath_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与p_w_picpath_sizes中的某个大小匹配的话 if table.contains(p_w_picpath_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地址/p_w_picpath/图片名.jpg
若要访问压缩的图片,访问tfs-nginxIP地址/p_w_picpath/图片名.jpg.800x600.jpg即可