如今几乎任何一个网站、Web App以及移动APP等应用都须要有图片展现的功能,对于图片功能从下至上都是很重要的。必需要具备前瞻性的规划好图片服务器,图片的上传和下载速度相当重要,固然这并非说一上来就搞很NB的架构,至少具有必定扩展性和稳定性。虽然各类架构设计都有,在这里我只是谈谈个人一些我的想法。javascript
对于图片服务器来讲IO无疑是消耗资源最为严重的,对于web应用来讲须要将图片服务器作必定的分离,不然极可能由于图片服务器的IO负载致使应用 崩溃。所以尤为对于大型网站和应用来讲,很是有必要将图片服务器和应用服务器分离,构建独立的图片服务器集群,构建独立的图片服务器其主要优点:php
1)分担Web服务器的I/O负载-将耗费资源的图片服务分离出来,提升服务器的性能和稳定性。html
2)可以专门对图片服务器进行优化-为图片服务设置有针对性的缓存方案,减小带宽网络成本,提升访问速度。前端
3)提升网站的可扩展性-经过增长图片服务器,提升图片服务吞吐能力。java
从传统互联网的web1.0,历经web2.0时代以及发展到如今的web3.0,随着图片存储规模的增长,图片服务器的架构也在逐渐发生变化,如下主要论述三个阶段的图片服务器架构演进。node
在介绍初始阶段的早期的小型图片服务器架构以前,首先让咱们了解一下NFS技术,NFS是Network File System的缩写,即网络文件系统。NFS是由Sun开发并发展起来的一项用于在不一样机器,不一样操做系统之间经过网络互相分享各自的文件。NFS server也能够看做是一个FILE SERVER,用于在UNIX类系统之间共享文件,能够轻松的挂载(mount)到一个目录上,操做起来就像本地文件同样的方便。python
若是不想在每台图片服务器同步全部图片,那么NFS是最简单的文件共享方式。NFS是个分布式的客户机/服务器文件系统,NFS的实质在于用户间计算机的共享,用户能够联结到共享计算机并象访问本地硬盘同样访问共享计算机上的文件。具体实现思路是:nginx
1)全部前端web服务器都经过nfs挂载3台图片服务器export出来的目录,以接收web服务器写入的图片。而后[图片1]服务器挂载另外两台图片服务器的export目录到本地给apache对外提供访问。web
2)用户上传图片正则表达式
用户经过Internet访问页面提交上传请求post到web服务器,web服务器处理完图片后由web服务器拷贝到对应的mount本地目录。
3)用户访问图片
用户访问图片时,经过[图片1]这台图片服务器来读取相应mount目录里边的图片。
以上架构存在的问题:
1)性能:现有结构过分依赖nfs,当图片服务器的nfs服务器有问题时,可能影响到前端web服务器。NFS的问题主要是锁的问题. 很容易形成死锁, 只有硬件重启才能解决。尤为当图片达到必定的量级后,nfs会有严重的性能问题。
2)高可用:对外提供下载的图片服务器只有一台,容易出现单点故障。
3) 扩展性:图片服务器之间的依赖过多,并且横向扩展余地不够。
4) 存储:web服务器上传热点不可控,形成现有图片服务器空间占用不均衡。
5) 安全性:nfs方式对于拥有web服务器的密码的人来讲,能够随意修改nfs里边的内容,安全级别不高。
固然图片服务器的图片同步能够不采用NFS,也能够采用ftp或rsync,采用ftp这样的话每一个图片服务器就都保存一份图片的副本,也起到了备 份的做用。可是缺点是将图片ftp到服务器比较耗时,若是使用异步方式去同步图片的话又会有延时,不过通常的小图片文件也还好了。使用rsync同步,当 数据文件达到必定的量级后,每次rsync扫描会耗时好久也会带来必定的延时性。
当网站达到必定的规模后,对图片服务器的性能和稳定性有必定的要求后,上述NFS图片服务架构面临着挑战,严重的依赖NFS,并且系统存在单点机器容易出现故障,须要对总体架构进行升级。因而出现了上图图片服务器架构,出现了分布式的图片存储。
其实现的具体思路以下:
1)用户上传图片到web服务器后,web服务器处理完图片,而后再由前端web服务器把图片post到到[图片1]、[图片2]…[图片N]其中 的一个,图片服务器接收到post过来的图片,而后把图片写入到本地磁盘并返回对应成功状态码。前端web服务器根据返回状态码决定对应操做,若是成功的 话,处理生成各尺寸的缩略图、打水印,把图片服务器对应的ID和对应图片路径写入DB数据库。
2) 上传控制
咱们须要调节上传时,只须要修改web服务器post到的目的图片服务器的ID,就能够控制上传到哪台图片存储服务器,对应的图片存储服务器只须要 安装nginx同时提供一个python或者php服务接收并保存图片,若是不想不想开启python或者php服务,也能够编写一个nginx扩展模 块。
3) 用户访问流程
用户访问页面的时候,根据请求图片的URL到对应图片服务器去访问图片。
如: http://imgN.xxx.com/image1.jpg
此阶段的图片服务器架构,增长了负载均衡和 分布式图片存储,可以在必定程度上解决并发访问量高和存储量大的问题。负载均衡在有必定财力的状况下能够考虑F5硬负载,固然也能够考虑使用开源的LVS 软负载(同时还可开启缓存功能)。此时将极大提高访问的并发量,能够根据状况随时调配服务器。固然此时也存在必定的瑕疵,那就是可能在多台Squid上存 在同一张图片,由于访问图片时可能第一次分到squid1,在LVS过时后第二次访问到squid2或者别的,固然相对并发问题的解决,此种少许的冗余完 全在咱们的容许范围以内。在该系统架构中二级缓存可使用squid也能够考虑使用Varnish或者traffic server,对于cache的开源软件选型要考率如下几点
1)性能:varnish自己的技术上优点要高于squid,它采用了“Visual Page Cache”技术,在内存的利用上,Varnish比Squid具备优点,它避免了Squid频繁在内存、磁盘中交换文件,性能要比Squid高。 varnish是不能cache到本地硬盘上的。还有强大的经过Varnish管理端口,可使用正则表达式快速、批量地清除部分缓存。nginx是用第 三方模块ncache作的缓冲,其性能基本达到varnish,但在架构中nginx通常做为反向(静态文件如今用nginx的不少,并发能支持到2 万+)。在静态架构中,若是前端直接面对的是cdn活着前端了4层负载的话,彻底用nginx的cache就够了。
2)避免文件系统式的缓存,在文件数据量很是大的状况下,文件系统的性能不好,像squid,nginx的 proxy_store,proxy_cache之类的方式缓存,当缓存的量级上来后,性能将不能知足要求。开源的traffic server直接用裸盘缓存,是一个不错的选择,国内大规模应用并公布出来的主要是淘宝,并非由于它作的差,而是开源时间晚。Traffic Server 在 Yahoo 内部使用了超过 4 年,主要用于 CDN 服务,CDN 用于分发特定的HTTP 内容,一般是静态的内容如图片、JavaScript、CSS。固然使用leveldb之类的作缓存,我估计也能达到很好的效果。
3)稳定性:squid做为老牌劲旅缓存,其稳定性更可靠一些,从我身边一些使用者反馈来看varnish偶尔会出现crash的状况。 Traffic Server在雅虎目前使用期间也没有出现已知的数据损坏状况,其稳定性相对也比较可靠,对于将来我其实更期待Traffic Server在国内可以拥有更多的用户。
以上图片服务架构设计消除了早期的NFS依赖以及单点问题,时可以均衡图片服务器的空间,提升了图片服务器的安全性等问 题,可是又带来一个问题是图片服务器的横向扩展冗余问题。只想在普通的硬盘上存储,首先仍是要考虑一下物理硬盘的实际处理能力。是 7200 转的仍是 15000 转的,实际表现差异就很大。至于文件系统选择xfs、ext三、ext4仍是reiserFs, 须要作一些性能方面的测试,从官方的一些测试数据来看,reiserFs更适合存储一些小图片文件。建立文件系统的时候 Inode 问题也要加以考虑,选择合适大小的 inode size ,由于Linux 为每一个文件分配一个称为索引节点的号码inode,能够将inode简单理解成一个指针,它永远指向本文件的具体存储位置。一个文件系统容许的inode 节点数是有限的,若是文件数量太多,即便每一个文件都是0字节的空文件,系统最终也会由于节点空间耗尽而不能再建立文件,所以须要在空间和速度上作取舍,构 造合理的文件目录索引。
2011年李彦宏在百度联盟峰会上就提到过互联网的读图时代已经到来,图片服务早已成为一个互联网应用中占比很大的部分,对图片的处理能力也相应地 变成企业和开发者的一项基本技能,图片的下载和上传速度显得更加剧要,要想处理好图片,须要面对的三个主要问题是:大流量、高并发、海量存储。
阿里云存储服务(OpenStorageService,简称OSS),是阿里云对外提供的海量,安全,低成本,高可靠的云存储服务。用户能够经过 简单的 REST接口,在任什么时候间、任何地点上传和下载数据,也可使用WEB页面对数据进行管理。同时,OSS提供Java、Python、PHP SDK,简化用户的编程。基于OSS,用户能够搭建出各类多媒体分享网站、网盘、我的企业数据备份等基于大规模数据的服务。在如下图片云存储主要以阿里云 的云存储OSS为切入点介绍,上图为OSS云存储的简单架构示意图。
真正意义上的“云存储”,不是存储而是提供云服务,使用云存储服务的主要优点有如下几点:
1)用户无需了解存储设备的类型、接口、存储介质等。
2)无需关心数据的存储路径。
3)无需对存储设备进行管理、维护。
4)无需考虑数据备份和容灾
5)简单接入云存储,尽情享受存储服务。
1)KV Engine
OSS中的Object源信息和数据文件都是存放在KV Engine上。在6.15的版本,V Engine将使用0.8.6版本,并使用为OSS提供的OSSFileClient。
2)Quota
此模块记录了Bucket和用户的对应关系,和以分钟为单位的Bucket资源使用状况。Quota还将提供HTTP接口供Boss系统查询。
3)安全模块
安全模块主要记录User对应的ID和Key,并提供OSS访问的用户验证功能。
1 )Access Key ID & Access Key Secret (API密钥)
用户注册OSS时,系统会给用户分配一对Access Key ID & Access Key Secret,称为ID对,用于标识用户,为访问OSS作签名验证。
2) Service
OSS提供给用户的虚拟存储空间,在这个虚拟空间中,每一个用户可拥有一个到多个Bucket。
3) Bucket
Bucket是OSS上的命名空间;Bucket名在整个OSS中具备全局惟一性,且不能修改;存储在OSS上的每一个Object必须都包含在某个 Bucket中。一个应用,例如图片分享网站,能够对应一个或多个Bucket。一个用户最多可建立10个Bucket,但每一个Bucket中存放的 Object的数量和大小总和没有限制,用户不须要考虑数据的可扩展性。
4) Object
在OSS中,用户的每一个文件都是一个Object,每一个文件需小于5TB。Object包含key、data和user meta。其中,key是Object的名字;data是Object的数据;user meta是用户对该object的描述。其使用方式很是简单,以下为java sdk:
OSSClient ossClient = new OSSClient(accessKeyId,accessKeySecret); PutObjectResult result = ossClient.putObject(bucketname, bucketKey, inStream, new ObjectMetadata());
执行以上代码便可将图片流上传至OSS服务器上。
图片的访问方式也很是简单其url为:http://bucketname.oss.aliyuncs.com/bucketKey
用分布式存储有几个好处,分布式能自动提供冗余,不须要咱们去备份,担忧数据安全,在文件数量特别大的状况下,备份是一件很痛苦的事情,rsync扫一次多是就是好几个小时,还有一点就是分布式存储动态扩容方便。固然在国内的其余一些文件系统里,TFS(http://code.taobao.org/p/tfs/src/)和FASTDFS也有一些用户,可是TFS的优点更是针对一些小文件存储,主要是淘宝在用。另外FASTDFS在并发高于300写入的状况下出现性能问题,稳定性不够友好。OSS存储使用的是阿里云基于飞天5k平台自主研发的高可用,高可靠的分布式文件系统盘古。
分布式文件系统盘古和Google的GFS相似,盘古的架构是Master-Slave主从架构,Master负责元数据管理,Sliave叫作 Chunk Server,负责读写请求。其中Master是基于Paxos的多Master架构,一个Master死了以后,另一个Master能够很快接过去, 基本可以作到故障恢复在一分钟之内 。文件是按照分片存放,每一个会分三个副本,放在不一样的机架上,最后提供端到端的数据校验。
基于haproxy的自动hash架构 ,这是一种新的缓存架构,由nginx做为最前端,代理到缓存机器。 nginx后面是缓存组,由nginx通过url hash后将请求分到缓存机器。
这个架构方便纯squid缓存升级,能够在squid的机器上加装nginx。 nginx有缓存的功能,能够将一些访问量特大的连接直接缓存在nginx上,就不用通过多一次代理的请求,可以保证图片服务器的高可用、高性能。好比 favicon.ico和网站的logo。 负载均衡负责OSS全部的请求的负载均衡,后台的http服务器故障会自动切换,从而保证了OSS的服务不间断。
阿里云CDN服务是一个遍及全国的分布式缓存系统,可以将网站文件(如图片或JavaScript代码文件)缓存到全国多个城市机房中的服务器上,当一个用户访问你的网站时,会就近到靠近TA的城市的服务器上获取数据,这样最终用户访问你的服务速度会很是快。
阿里云CDN服务在全国部署超过100个节点,能提供给用户优良的网络加速效果。当网站业务忽然爆发增加时,无需手忙脚乱地扩容网络带宽,使用 CDN服务便可轻松应对。和OSS服务同样,使用CDN,须要先在aliyun.com网站上开通CDN服务。开通后,须要在网站上的管理中心建立你的 distribution(即分发频道),每一个distribution由两个必须的部分组成:distribution ID和源站地址。
使用阿里云OSS和CDN能够很是方便的针对每一个bucket进行内容加速,由于每一个bucket对应一个独立的二级域名,针对每一个文件进行CDN删除,简单、经济地解决服务的存储和网络问题,毕竟大多数网站或应用的存储和网络带宽多半是被图片或视频消耗掉的。
从整个业界来看,最近这样的面向我的用户的云存储如国外的DropBox和Box.net很是受欢迎,国内的云存储目前比较不错的主要有七牛云存储和又拍云存储。
图片服务器的图片下载比例远远高于上传比例,业务逻辑的处理也区别明显,上传服器对图片重命名,记录入库信息,下载服务器对图片添加水印、修改尺寸 之类的动态处理。从高可用的角度,咱们能容忍部分图片下载失败,但毫不能有图片上传失败,由于上传失败,意味着数据的丢失。上传与下载分开,能保证不会因 下载的压力影响图片的上传,并且还有一点,下载入口和上传入口的负载均衡策略也有所不一样。上传须要通过Quota Server记录用户和图片的关系等逻辑处理,下载的逻辑处理若是绕过了前端缓存处理,穿透后端业务逻辑处理,须要从OSS获取图片路径信息。近期阿里云 会推出基于CDN就近上传的功能,自动选择离用户最近的CDN节点,使得数据的上传下载速度均获得最优化。相较传统IDC,访问速度提高数倍。
若是服务不容许防盗链,那么访问量会引发带宽、服务器压力等问题。比较通用的解决方案是在nginx或者squid反向代理软件上添加refer ACL判断,OSS也提供了基于refer的防盗链技术。固然OSS也提供了更为高级的URL签名防盗链,其其实现思路以下:
首先,确认本身的bucket权限是private,即这个bucket的全部请求必须在签名认证经过后才被认为是合法的。而后根据操做类型、要访 问的bucket、要访问的object以及超时时间,动态地生成一个通过签名的URL。经过这个签名URL,你受权的用户就能够在该签名URL过时时间 前执行相应的操做。
签名的Python代码以下:
h=hmac.new(“OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV”, “GET\n\n\n1141889120\n/oss-example/oss-api.jpg”,sha); urllib.quote_plus (base64.encodestring(h.digest()).strip());
其中method能够是PUT、GET、HEAD、DELETE中的任意一种;最后一个参数“timeout”是超时的时间,单位是秒。一个经过上面Python方法,计算获得的签名URL为:
http://oss-example.oss-cn-hangzhou.aliyuncs.com/oss-api.jpg?OSSAccessKeyId=44CF9590006BF252F707&Expires=1141889120&Signature=vjbyPxybdZaNmGa%2ByT272YEAiv4%3D
经过这种动态计算签名URL的方法,能够有效地保护放在OSS上的数据,防止被其余人盗链。
对于在线图片的编辑处理,GraphicsMagick(GraphicsMagick(http://www.graphicsmagick.org/)) 对于从事互联网的技术人员应该不会陌生。GraphicsMagick是从 ImageMagick 5.5.2 分支出来的,可是如今他变得更稳定和优秀,GM更小更容易安装、GM更有效率、GM的手册很是丰富GraphicsMagick的命令与 ImageMagick基本是同样的。
GraphicsMagick 提供了包括裁、缩放、合成、打水印、图像转换、填充等很是丰富的接口API,其中的开发包SDK也很是丰富,包括了JAVA(im4java)、C、 C++、Perl、PHP、Tcl、Ruby等的调用,支持超过88中图像格式,包括重要的DPX、GIF、JPEG、JPEG-2000、PNG、 PDF、PNM和TIFF,GraphicsMagick能够再绝大多数的平台上使用,Linux、Mac、Windows都没有问题。可是独立开发这些 图片处理服务,对服务器的IO要求相对要高一些,并且目前这些开源的图片处理编辑库,相对来讲还不是很稳定,笔者在使用GraphicsMagick 的时候就遇到了tomcat 进程crash状况,须要手动重启tomcat服务。
阿里云目前已经对外开放图片处理API,包括了大多数经常使用处理解决方案:缩略图、打水印、文字水印、样式、管道等。开发者能够很是方便的使用如上图片处理方案,但愿愈来愈多的开发者可以基于OSS开放出更多优秀的产品。