西西河

主题:【半原创】Flickr 网站架构研究(1) -- 西电鲁丁

共:💬69 🌺366 新:
全看分页树展 · 主题 跟帖
家园 【原创】Flickr 网站架构研究(5)

"Flickr File System"探秘(上)

Flickr在美国东西海岸各建了4个数据中心用于提供静态内容(主要是照片)的后台访问服务,组成了4个相互镜像和冗余的“Photo Farm Pair",各自服务于不同地域的客户。同Flickr"Master-Maste Pair"数据库一样,每个数据中心的设计容量是能够处理整个"Pair"100%的访问,这样在"Pair"中的一个数据中心因为停电,地震等灾难或必要维护而停止服务时,另一个数据中心仍然能够支持全部的访问而不降低性能。

每个"Photo Farm"的架构示意图如下:

点看全图

外链图片需谨慎,可能会被源头改

这个就是所谓的"Flickr File System",主要由三部分组成:1)Perbal(未在图中标出)和PHP APP Servers提供文件访问的权限控制,获取文件的内部URL并转向Squid/Apache服务器;2)Layer 7 Load Balancer和多台Squid/Apache Servers(Apache未在图中标出)提供文件“读”访问服务;3)几台Storage Managers用于文件“写”访问服务,PHP APP Server和Storage Manager之间采用了Flickr自己开发的“文件传输轻量协议“。NetApp用于文件存储,Squid/Apache Server和Storage Manager Server和NetApp之间采用NFS连接。

我们先来看访问控制这一部分。

Flickr的访问权限控制是通过Perlbal(Perlbal是一个Perl 编写的单线程的事件驱动服务器,可充当 reverse proxy,Web 服务器 和 HTTP Balancer,与大名鼎鼎的memcache同出于www.danga.com)的"reproxy"功能来实现的,如下图:

点看全图

外链图片需谨慎,可能会被源头改

例如,当Perlbal收到以下URL访问请求时,”http://www.flickr.com/photos/41174610@N05/3999568691/“,首先将访问请求转向后台的PHP App Server 进行权限检查,如果当前浏览器用户具有访问权限,则向Perlbal返回HTTP Response 200,并设置"X-REPROXY-URL" Header为实际的静态URL地址,既”http://farm3.static.flickr.com/2434/3999568691_d836afbb57.jpg“,Perlbal收到X-REPROXY-URL后,将请求转向Asset Server既Squid/Apache Server进行处理,整个过程对用户透明。

以上例子中我们看到Flickr采用了两种不同方式的URL格式,第一种方式(例如”http://www.flickr.com/photos/41174610@N05/3999568691/“)我们姑且称之为“动态URL",当最终用户采用这种方式访问时,后台系统将进行权限检查;而如果用户采用第二种方式(例如”http://farm3.static.flickr.com/2434/3999568691_d836afbb57.jpg“),我们姑且称之为“静态URL",系统将略过权限检查,直接指向Squid/Apache服务器。这就是Flickr所谓“Permission URLs”的概念,即将授权信息作为URL的一部分,从而省略授权过程而提高网站的访问性能和吞吐量。

个人认为,Flickr是鼓励采用其Flickr API开发第三方接口的合作伙伴采用这种“静态URL"方式的。Flickr的API文档中提供了这种静态URL的信息格式

”http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}.jpg“

or

”http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[mstb].jpg“

or

”http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{o-secret}_o.(jpg|gif|png)“

Size Suffixes

The letter suffixes are as follows:

s small square 75x75

t thumbnail, 100 on longest side

m small, 240 on longest side

- medium, 500 on longest side

b large, 1024 on longest side (only exists for very large original images)

o original image, either a jpg, gif or png, depending on source format

“静态URL"也可以通过“动态URL”来获得,而且是“终生授权”,即使将来作者修改了照片的权限,采用静态URL依然可以继续访问,除非作者删除照片,或者对照片进行修改,一旦照片经过修改,则系统自动生成一个新的“静态URL",原有的授权则因URL不存在而自动失效。

对于Flickr这类以"照片共享"为主要目的的社交类网站,安全并不是其首要的考虑因素,因而采用这种“折衷”方式的权限控制方式是可以接受的。(听说Amazon S3也是采用了这种方式,不禁为那些S3商业用户的数据安全悄悄捏了把汗

"Flickr File System"探秘(中)

对于Flickr这样每秒需要响应和处理4万个以上的照片文件读取请求的大型网站系统,Web Cache和reverse proxy系统的重要性,无论怎么强调都不过分。常见的Web Cache系统有,Squid,Varnish,Apache mod_cache等。

Flickr采用Squid作为缓存代理服务器,这里有一张2005年Flickr展示的系统配置原理示意图:

点看全图

外链图片需谨慎,可能会被源头改

简单解释一下,Squid采用2GB 内存作为一级缓存(注这个值仅仅是Squid用于缓存的内存大小,Squid实际所用的内存要大于这个值);服务器内置的6块15K RPM 高速硬盘作为二级缓存;小于64KB的文件缓存于内存,大于64KB而小于512KB的缓存于高速硬盘;当缓存空间不够时采用LRU(Least recently used)算法将”最近最少使用的文件“清除。

对于不在Squid缓存的文件,Squid则将请求转向Apache Web Server,Apache 根据ReWrite规则将URL转化成实际的NFS路径并取得相应的文件返回(图中只列出了一个Filer卷,实际上每个Squid服务器通过NFS mount了多个NetApp Filer的所有的卷)。值得一提的是,Apache在处理大于10MB以上的文件时,性能会有显著的下降,这也是为什么YouTube采用lighttpd的原因,所幸的是,一般照片的尺寸远远小于10MB,因而Flickr并不需要考虑额外维护另外一个Web Server,Apache已经足够满足需要。

Web缓存代理服务器常见的两个问题是:

1)如何避免”多次缓存“,即我们希望同一份文件只缓存一次,而不是在多个Squid中保留多份COPY,以最大限度的利用缓存空间。解决这个问题的办法是在Squid服务器集群之前放置Layer 7的Load Balancer。相对于传统的基于IP地址加PORT端口的Layer 4的Load Balancer,Layer 7的Load Balancer可以根据规则,对应用层的信息,如HTTP的Header,URL,Cookie Name等进行哈希或CRC计算,从而确保同一URL的请求总是指向后台集群中的同一台Squid服务器。

根据需要和负载,网站可以选择基于硬件的Layer 7 Load Balancer,如Flickr;也可以选择开源的软件方案,如具有Layer 7负载均衡功能的HAProxy,Perlbal,或者是利用Apache的mod_rewrite功能通过script来简易实现,示例代码如下:

RewriteEngine on

RewriteMap balance prg:/var/balance.pl

RewriteLock /var/balance.lock

RewriteRule ^/(.*)$ ${balance:$1} [P,L]

每一个到达的URL请求将被转向到/var/balance.pl脚本,由balance.pl脚本决定最终由哪台Cache服务器提供服务。

#!/usr/bin/perl -w

use strict;

use String::CRC;

$|++;

my @servers = qw(cache1 cache2 cache3);

while (<STDIN>) {

my $crc = String::CRC::crc($_, 16);

my $server = $servers[$crc % scalar @servers];

print "http://$server/$_";

}

(以上脚本省略了fail-over和后台服务器状态检查部分)

2)如何处理缓存”过期”问题,即当后台文件(如照片)修改后,如何保证用户能够访问到最新的版本而不是过期的版本。简单的更新Squid缓存并不总能解决问题,过期的文件依然有可能缓存在客户端的浏览器Cache,或是互联网上CDN,Proxy Server等处,而且还增加了后台应用的处理复杂程度和系统负荷。

Flickr的方案是引入了“虚拟版本”的概念(对于Flickr这样的应用,没有必要采用真正的版本管理和维护多个版本),让我们来回顾一下Flickr "静态URL"的格式:“http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}.jpg”,

每当用户修改照片时,数据库将重新生成一个新的的版本号码,即{secret}号码,从而产生一个新的静态URL并返回给客户,原有的缓存中的老文件则随着时间而“自然死亡”。(为了节省I/O,真正的物理文件名是没有这个{secret}号码的,在Apache的ReWrite处理中将这一部分去掉了。)这种方案,应该说至少可以保证通过“动态URL”访问的客户总是取得最新的文件版本,通过Flickr API访问的用户,则总是可以通过相应的应用逻辑判断来获取最新的“静态URL"。至于那些的Bookmark在浏览器端的旧的“静态URL",看起来也只能听之任之了,好象也没有更好的办法。

Flickr的缓存系统是相当高效的,这里有一些2007年的数据:

  

点看全图
外链图片需谨慎,可能会被源头改

点看全图
外链图片需谨慎,可能会被源头改

点看全图
外链图片需谨慎,可能会被源头改

  总体来看Squid的命中率在75%-80%之间,命中时的响应时间为15-50ms,应该是相当不错了。Flickr的运营团队得出的结论是在当前服务器配置下,每一台Squid服务器可以支持每秒900-1000个请求,同时响应时间控制在100ms以内。换句话说就是,随着业务的发展,当每秒新增加900个请求时,只要添加一台新的Squid服务器就可以了。

通宝推:铁手,
全看分页树展 · 主题 跟帖


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河