2014年2月9日星期日

Architect_008:大型网站架构设计方案(摘录+整理)

何谓大型网站?简单来讲,日均流量至少IP>1,000,000,即平均每天有100万用户访问的网站。
根据alexa统计,目前世界排名第一的网站是Facebook,日均 IP 访问量 ≈ 254,580,000。

1. 总架构图

说明:这里的Web Server指的是HTTP服务器和应用服务器的综合体。

2. 架构技术要点说明

2.1 Web资源动静分离
静态网页由Nginx负载,PHP动态网页由Apache负载,JSF动态网页由Tomcat/JBoss/Glassfish负载。


毋庸置疑,静态网页访问速度最快,对Web服务器的负担最小,因此应该尽可能的采用静态页面。
对于内容多并且更新频繁的网站,比如各大门户的新闻频道,一般使用CMS(Content Management System,内容管理系统)发布信息,发布后的信息就是静态化的HTML网页。
当然CMS除了发布信息,还有很多其它功能比如频道管理,权限管理,自动抓取等等,以后有机会另文专述。
对于交互性很强的大型社区网站,可以考虑把帖子进行实时的静态化;对于系统中频繁使用数据库查询但是内容更新很小的字典信息,也可以考虑将其静态化,比如论坛中的公用设置信息。这样不仅减少了Web服务的负担,也减轻了数据库的负担。

2.2 Web服务器与数据库所在机器物理分离
网站初期可能由于资金压力比较大,用户也比较少,Web Server和Database Server可能放在同一台服务器上。

当网站访问量逐渐增大,特别是CPU处理能力是瓶颈的时候,此时应该把Web Server和Database Server物理分开,可以达到不错的性能。

2.3 建立独立的图片服务器
对Web服务器来说,图片是最消耗资源的,因此有必要将图片与页面进行分离。
很多大型网站都有独立的图片服务器,甚至很多台图片服务器,比如人人网和淘宝网。
独立的图片服务器的好处有哪些?
(1)浏览器会控制对一个站点的并发请求数量,一般在10以下,如果对于网站有很多资源需要加载的话,比如样式文件、脚本文件和大量图片,那么请求的过程会被阻塞,影响网站的打开速度。
(2)降低Web服务器的压力,并且可以保证系统不会因为图片问题而崩溃。
(3)Web服务器和图片服务器可以各自优化,互不影响。
比如Apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,以保证更高的执行效率。
比如图片会消耗带宽和IO资源,可以在图片服务器上专门优化带宽和IO。

2.4 缓存
这里的缓存指的是浏览器缓存、页面缓存、页面片段缓存、本地数据缓存。下面逐一说明。

2.4.1 浏览器缓存
根据HTTP1.1协议,修改与缓存有关的Header参数:Cache-Control、Expires、Pragma、Last-Modified、Etag。
浏览器缓存减少了用户对网站的访问。

2.4.2 页面缓存


当用户向网站发出的GET和POST请求时,Web服务器的处理进程会做出响应,获取网页内容,并将结果缓存到代理服务器上。如有其他用户请求相同内容,代理服务器会直接从自身的内存中获取网页内容返回给用户,无需再次请求Web服务器。
页面缓存减少了对Web服务器的访问,大大加快用户上网流畅度,有效提升访问量,显著降低带宽占用,加快响应速度,降低了成本。
在总架构图中,反向代理服务器充当了页面缓存器,关于反向代理服务器,请参考《反向代理服务器的工作原理》。
具备页面缓存功能的反向代理服务器有:Varnish、Squid、Ncache、AiCache、硬件F5。

2.4.3 页面片段缓存:Edge Side Includes
ESI是一个基于XML的标记语言,目的是在HTTP中组装各种资源。
在实际环境中,一个动态生成的页面,当中可能只有少量的内容是频繁变化的或是个性化的,对于传统的缓存服务器来说,为了能够保证页面的时效性,却由于页面中这些少量的动态内容而无法将整个页面进行缓存。
ESI通过使用简单的标记语言来对那些可以缓存和不能缓存的网页中的内容片断进行描述,每个网页都被划分成不同的小部分分别赋予不同的缓存控制策略,使得缓存服务器可以根据这些策略在将完整的网页发送给用户之前将不同的小部分动态地组合在一起。
通过这种控制,可以有效地减少从Web服务器抓取整个页面的次数,而只用从Web服务器中提取少量的不能缓存的片断,因此可以有效降低Web服务器的负载,同时提高用户访问的响应时间。
注意,ESI需要服务器端支持,常见apache(mod_esi)、WebLogic、JSP标签库(JESI)等。

2.4.4 本地数据缓存
本地数据缓存减少了对数据库的查询,设计时需要从数据库和应用服务器两个层面考虑。


2.4.4.1 数据库缓存
(1)关系数据库Query Cache策略
以SQL语句为key来缓存查询结果,所以尽量不要拼SQL字符串,而要使用PreparedStatement的“?”模式来构造SQL语句。
Query Cache大小要根据数据库系统具体情况合理设置,过大只会浪费内存,参考值:128M。
(2)关系数据库系统Data Buffer策略
即数据库数据内存缓存器,其访问命中率决定数据库性能,可根据实际物理内存大小适量增大,如:MySQL建议buffer值为物理内存60-80%。

2.4.4.2 应用服务器缓存
(1)对象缓存:例如对象线程安全,做成单例。
(2)更新频率不大的数据可以考虑缓存:例如字典数据、配置文件信息。
(3)考虑使用线程池,对象池,连接池。
常见的Java解决方案有:Map、OSCache、EHCache等等。
常见的缓存算法有:
(1)贝莱蒂算法(Belady's Algorithm)
最有效率的缓存算法会丢掉未来最长时间内不使用的数据。
这种理想情况被称作贝莱蒂最优算法或者千里眼算法。由于要预计数据要多久后才被使用基本上是不可能的,所以这种算法没有实际的可操作性。它的作用在于为不同的缓存算法订立一个优劣标准。
(2)最近最少使用算法(LRU,Least Recently Used)
最近最少使用算法的思路是丢弃近段时间内最少被使用的数据。要实现这种算法需要跟踪数据何时被使用,用这种方法来筛选去近一段时间被最少使用次数的数据其代价往往是昂贵的。它的实现往往是通过在缓存数据上设立时间标志位,用以跟踪最近最少被使用的缓存数据。一个数据每被使用一次,其他数据的时间标志位数值就要增加。
(3)最近最频繁使用算法(MRU,Most Recently Used)
最近最频繁使用算法和最近最少使用算法相反,它会首先丢弃最近最常使用的数据。有观点认为“当文件在顺序访问时,MRU算法是最佳选择”,抱有这样观点人也认为在反复进行大量数据的随机存储时,MRU因为倾向于保留旧的数据,随意比LRU算法有着更高的命中率。MRU算法经常用于旧的数据更常被用到的情况下。
(4)伪LRU算法(PLRU,Pseudo-LRU)
因为缓存有着大量的关联性,LRU算法实现的代价往往比较昂贵。如果实际情况在丢弃任一个最近最少使用的数据就能满足,那么伪LRU算法就派上用场了,它为每一个缓存数据设立一个标志位就可以工作。

2.5 增加Web服务器机器做集群
这一步很显然是为了增加高可用性(High Availablility)。

2.6 负载均衡
实现负载均衡的方式主要有以下几种:

2.6.1 DNS 负载均衡
最简单而有效的方法,但是它不能区分服务器的差异,也不能反映服务器的当前运行状态。

2.6.2 反向代理软件
如HAProxy、Nginx、Apache、Lighttpd等。

2.6.3 硬件产品
如F5、NetScaler等。

2.6.4 LVS(Linux Virtual Server):http://www.linuxvirtualserver.org/
LVS/LVS集群采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的,而且无需修改客户端和服务器端的程序。
LVS主要特性有:
(1)Virtual Server via NAT(VS-NAT)
用地址翻译实现虚拟服务器。地址转换器有能被外界访问到的合法IP地址,它修改来自专有网络的流出包的地址。外界看起来包是来自地址转换器本身,当外界包送到转换器时,它能判断出应该将包送到内部网的哪个节点。优点是节省IP 地址,能对内部进行伪装;缺点是效率低,因为返回给请求方的流量经过转换器。
(2)Virtual Server via IP Tunneling (VS-TUN)
用IP隧道技术实现虚拟服务器。这种方式是在集群的节点不在同一个网段时可用的转发机制,是将IP包封装在其他网络流量中的方法。为了安全的考虑,应该使用隧道技术中的VPN,也可使用租用专线。 集群所能提供的服务是基于TCP/IP的Web服务、Mail服务、News服务、DNS服务、Proxy服务器等等.
(3)Virtual Server via Direct Routing(VS-DR)
用直接路由技术实现虚拟服务器。当参与集群的计算机和作为控制管理的计算机在同一个网段时可以用此法,控制管理的计算机接收到请求包时直接送到参与集群的节点。优点是返回给客户的流量不经过控制主机,速度快开销少。

2.6.5 Smart Client 
适合自己写代码的情况。

2.7 数据库读写分离
详细内容请参考《数据库读写分离架构》。

2.8 数据库分表、分库
详细内容请分别参考《大容量数据如何分表?》和《数据库分库设计》。

2.9 CDN (Content Delivery Network,内容分发网络)
CDN通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络"边缘",使用户可以就近取得所需的内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。
从技术上全面解决由于网络带宽小、用户访问量大、网点分布不均等原因所造成的用户访问网站响应速度慢的问题。
也就是把部署在一个服务器的内容,平均分部到多个服务器上,服务器智能识别,让用户获取离用户最近的服务器,提高速度。
CDN主要适合静态内容(如:静态页面、图片、视频等)及页面内容实时性要求不高的网站(如:新闻类门户网站)。
CDN构建可以做的很简单,也可以很复杂,主要根据自己网站实际情况而定。


2.10 分布式缓存
当数据量过大时,前面介绍的本地缓存性能就无法满足要求了,因为毕竟本地缓存容量有限,采用分布式缓存是必然选择。
分布式缓存可以突破容量限制,具备良好伸缩性;但分布式涉及远程网络通信消耗、节点状态维护、数据复制问题,对其稳定性和可靠性是个挑战。
目前流行分布式缓存方案:Memcached、Membase、Redis等,基本上当前的NoSQL方案都可以用来做分布式缓存方案。
关于NoSQL,以后将另文专述。

2.11 基于分布式文件系统计算架构构建数据中心
当用户过亿,数据量达到pb级时,网站性能不是通过简单增加硬件服务器就能够满足的。
这时就需要建立数据中心了,参照Google的GFS、Map/Reduce、BigTable技术模式搭建分布式存储和计算的架构就是必然选择了。

参考文献:
1. http://wenku.baidu.com/view/281da442b307e87101f69646.html
2. http://wenku.baidu.com/view/da3ef7c42cc58bd63186bd5c.html
3. http://houxiyang.com/archives/23/

没有评论: