关闭

高并发高流量网站架构

2011人阅读 评论(0) 收藏 举报

Web2.0的兴起,掀起了互联网新一轮的网络创业大潮。以用户为导向的新网站建设概念,细分了网站功能和用户群,不仅成功的造就了一大批新生的网站,也极大的方便了上网的人们。但Web2.0以用户为导向的理念,使得新生的网站有了新的特点——高并发,高流量,数据量大,逻辑复杂等,对网站建设也提出了新的要求。

    本文围绕高并发高流量的网站架构设计问题,主要研究讨论了以下内容:

    首先在整个网络的高度讨论了使用镜像网站,CDN内容分发网络等技术对负载均衡带来的便利及各自的优缺点比较。然后在局域网层次对第四层交换技术,包括硬件解决方案F5软件解决方案LVS,进行了简单的讨论。接下来在单服务器层次,本文着重讨论了单台服务器Socket优化,硬盘级缓存技术,内存级缓存技术,CPUIO平衡技术(即以运算为主的程序与以数据读写为主的程序搭配部署),读写分离技术等。在应用层,本文介绍了一些大型网站常用的技术,以及选择使用该技术的理由。最后,在架构的高度讨论了网站扩容,容错等问题。

本文以理论与实践相结合的形式,结合作者实际工作中得到的经验,具有较广泛的适用性。

1 引言

1.1 互联网的发展
最近十年间,互联网已经从一个单纯的用于科研的,用来传递静态文档的美国内部网络,发展成了一个应用于各行各业的,传送着海量多媒体及动态信息的全球网络。从规模上看,互联网在主机数、带宽、上网人数等方面几乎一直保持着指数增长的趋势,2006年7月,互联网上共有主机439,286,364 台,WWW 站点数量达到 96,854,877个 [1]。全球上网人口在2004 年达到 7 亿 2900万 [2],中国的上网人数在 2006 年 12 月达到了约 1亿3700 万[3]。另一方面,互联网所传递的内容也发生了巨大的变化,早期互联网以静态、文本的公共信息为主要内容,而目前的互联网则传递着大量的动态、多媒体及人性化的信息,人们不仅可以通过 互联网阅读到动态生成的信息,而且可以通过它使用电子商务、即时通信、网上游戏等交互性很强的服务。因此,可以说互联网已经不再仅仅是一个信息共享网络,而已经成为了一个无所不在的交互式服务的平台。

1.2 互联网网站建设的新趋势

互联网不断扩大的规模,日益增长的用户群,以及web2.0[4]的兴起,对互联网网站建设提出了新的要求:

高性能和高可扩展性。2000 年 5 月,访问量排名世界第一(统计数据来源[5])的Yahoo [6]声称其日页浏览数达到 6 亿 2500 万,即每秒约 30,000 次HTTP 请求(按每个页面浏览平均产生 4 次请求计算) 。这样大规模的访问量对服务的性能提出了非常高的要求。更为重要的是,互联网受众的广泛性,使得成功的互联网服务的访问量增长潜力和速度非常大,因此服务系统必须具有非常好的可扩展性,以应付将来可能的服务增长。

支持高度并发的访问。高度并发的访问对服务的存储与并发能力提出了很高的要求,当前主流的超标量和超流水线处理器能处理的并发请求数是有限的,因为随着并发数的上升,进程调度的开销会很快上升。互联网广域网的本质决定了其访问的延迟时间较长,因此一个请求完成时间也较长,按从请求产生到页面下载完成 3 秒计算, Yahoo 在 2000 年 5 月时平均有 90,000 个并发请求。而且对于较复杂的服务,服务器往往要维护用户会话的信息,例如一个互联网网站如果每天有 100 万次用户会话,每次 20分钟的话,那平均同时就会有约 14000 个并发会话。

高可用性。互联网服务的全球性决定了其每天 24 小时都会有用户访问,因此任何服务的停止都会对用户造成影响。而对于电子商务等应用,暂时的服务中止则意味着客户的永久失去及大量的经济损失,例如 ebay.com[7]1999 年 6 月的一次 22小时的网站不可访问,对此网站的 380万用户的忠诚度造成巨大影响,使得 Ebay 公司不得不支付了近500万美元用于补偿客户的损失,而该公司的市值同期下降了 40 亿美元[8]。因此,关键互联网应用的可用性要求非常高。

1.3 新浪播客的简介

以YouTube[9]为代表的微视频分享网站近来方兴未艾,仅2006年一年,国内就出现近百家仿YouTube的微视频分享网站[10],试图复制YouTube的成功模式。此类网站可以说是Web2.0概念下的代表网站,具有Web2.0网站所有典型特征:高并发,高流量,数据量大,逻辑复杂,用户分散等等。新浪[11]作为国内最大的门户网站,在2005年成功运作新浪博客的基础上,于2006年底推出了新浪播客服务。新浪播客作为国内门户网站中第一个微视频分享服务的网站,依靠新浪网站及新浪博客的巨大人气资源,在推出后不到半年的时间内,取得了巨大的成功:同类网站中上传视频数量第一、流量增长最快、用户数最多[12],所有这些成绩的取得的背后,是巨大的硬件投入,良好的架构支撑和灵活的应用层软件设计。


2.1 镜像网站技术

镜像网站是指将一个完全相同的站点放到几个服务器上,分别有自己的URL,这些服务器上的网站互相称为镜像网站[13]。镜像网站和主站并没有太大差别,或者可以视为主站的拷贝。镜像网站的好处是:如果不能对主站作正常访问(如服务器故障,网络故障或者网速太慢等),仍能通过镜像服务器获得服务。不便之处是:更新网站内容的时候,需要同时更新多个服务器;需要用户记忆超过一个网址,或需要用户选择访问多个镜像网站中的一个,而用户选择的,不一定是最优的。在用户选择的过程中,缺乏必要的可控性。

在互联网发展的初期,互联网上的网站内容很少,而且大都是静态内容,更新频率底。但因为服务器运算能力低,带宽小,网速慢,热门网站的访问压力还是很大。镜像网站技术在这种情况下作为一种有效解决方案,被广泛采用。随着互联网的发展,越来越多的网站使用服务器端脚本动态生成内容,同步更新越来越困难,对可控性要求越来越高,镜像技术因为不能满足这类网站的需要,渐渐的淡出了人们的视线。但有一些大型的软件下载站,因为符合镜像网站的条件——下载的内容是静态的,更新频率较低,对带宽,速度要求又比较高,如国外的SourceForge (http://www.SourceForge.net,著名开源软件托管网站),Fedora(http://fedoraproject.org,RedHat赞助的Linux发行版),国内的华军软件园(http://www.onlinedown.net),天空软件站(http://www.skycn.com)等,还在使用这项技术(图1)。


 

在网站建设的过程中,可以根据实际情况,将静态内容作一些镜像,以加快访问速度,提升用户体验。

2.2 CDN内容分发网络

    CDN的全称是Content Delivery Network,即内容分发网络。其目的是通过在现有的互联网中增加一层新的网络架构,将网站的内容发布到最接近用户的网络“边缘”,使用户可以就近取得所需的内容,分散服务器的压力,解决互联网拥挤的状况,提高用户访问网站的响应速度。从而解决由于网络带宽小、用户访问量大、网点分布不均等原因所造成的用户访问网站响应速度慢的问题[14]。

    CDN与镜像网站技术的不同之处在于网站代替用户去选择最优的内容服务器,增强了可控制性。CDN其实是夹在网页浏览者和被访问的服务器中间的一层镜像或者说缓存,浏览者访问时点击的还是服务器原来的URL地址,但是看到的内容其实是对浏览者来说最优的一台镜像服务器上的页面缓存内容。这是通过调整服务器的域名解析来实现的。使用CDN技术的域名解析服务器需要维护一个镜像服务器列表和一份来访IP到镜像服务器的对应表。当一个用户的请求到来的时候,根据用户的IP,查询对应表,得到最优的镜像服务器的IP地址,返回给用户。这里的最优,需要综合考虑服务器的处理能力,带宽,离访问者的距离远近等因素。当某个地方的镜像网站流量过大,带宽消耗过快,或者出现服务器,网络等故障的时候,可以很方便的设置将用户的访问转到另外一个地方(图2)。这样就增强了可控制性。

CDN网络加速技术也有它的局限性。首先,因为内容更新的时候,需要同步更新多台镜像服务器,所以它也只适用于内容更新不太频繁,或者对实时性要求不是很高的网站;其次,DNS解析有缓存,当某一个镜像网站的访问需要转移时,主DNS服务器更改了IP解析结果,但各地的DNS服务器缓存更新会滞后一段时间,这段时间内用户的访问仍然会指向该服务器,可控制性依然有不足。

目前,国内访问量较高的大型网站如新浪、网易等的资讯频道,均使用CDN网络加速技术(图3),虽然网站的访问量巨大,但无论在什么地方访问,速度都会很快。但论坛,邮箱等更新频繁,实时性要求高的频道,则不适合使用这种技术。

ChinaCache的服务节点全球超过130个,

其中中国节点超过80个,

覆盖全国主要6大网络的主要省份[15]。

2.3 应用层分布式设计
新浪播客为了获得CDN网络加速的优点,又必须避免CDN的不足,在应用层软件设计上,采取了一个替代的办法。新浪播客提供了一个供播放器查询视频文件地址的接口。当用户打开视频播放页面的时候,播放器首先连接查询接口,通过接口获得视频文件所在的最优的镜像服务器地址,然后再到该服务器去下载视频文件。这样,用一次额外的查询获得了全部的控制性,而这次查询的通讯流量非常小,几乎可以忽略不计。CDN中由域名解析获得的灵活性也保留了下来:由接口程序维护镜像网站列表及来访IP到镜像网站的对应表即可。镜像网站中不需要镜像所有的内容,而是只镜像更新速度较慢的视频文件。这是完全可以承受的。

2.4 网络层架构小结
从整个互联网络的高度来看网站架构,努力的方向是明确的:让用户就近取得内容,但又要在速度和可控制性之间作一个平衡。对于更新比较频繁内容,由于难以保持镜像网站之间的同步,则需要使用其他的辅助技术。


3 交换层架构

3.1 第四层交换简介
按照OSI[16]七层模型,第四层是传输层。传输层负责端到端通信,在IP协议栈中是TCP和UDP所在的协议层。TCP和UDP数据包中包含端口号(port number),它们可以唯一区分每个数据包所属的协议和应用程序。接收端计算机的操作系统根据端口号确定所收到的IP包类型,并把它交给合适的高层程序。IP地址和端口号的组合通常称作“插口(Socket)”。

第四层交换的一个简单定义是:它是一种传输功能,它决定传输不仅仅依据MAC地址(第二层网桥)或源/目标IP地址(第三层路由),而且依据IP地址与TCP/UDP (第四层) 应用端口号的组合(Socket)[17]。第四层交换功能就像是虚拟IP,指向实际的服务器。它传输的数据支持多种协议,有HTTP、FTP、NFS、Telnet等。

以HTTP协议为例,在第四层交换中为每个服务器组设立一个虚拟IP(Virtue IP,VIP),每组服务器支持某一个或几个域名。在域名服务器(DNS)中存储服务器组的VIP,而不是某一台服务器的真实地址。

当用户请求页面时,一个带有目标服务器组的VIP连接请求发送给第四层交换机。第四层交换机使用某种选择策略,在组中选取最优的服务器,将数据包中的目标VIP地址用实际服务器的IP地址取代,并将连接请求传给该服务器。第四层交换一般都实现了会话保持功能,即同一会话的所有的包由第四层交换机进行映射后,在用户和同一服务器间进行传输[18]。

第四层交换按实现分类,分为硬件实现和软件实现。

3.2 硬件实现
第四层交换的硬件实现一般都由专业的硬件厂商作为商业解决方案提供。常见的有Alteon[19],F5[20]等。这些产品非常昂贵,但是能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了[21]。鉴于条件关系,这里不展开讨论。

3.3 软件实现
第四层交换也可以通过软件实现,不过性能比专业硬件稍差,但是满足一定量的压力还是可以达到的,而且软件实现配置起来更灵活。软件四层交换常用的有Linux上的LVS(Linux Virtual Server),它提供了基于心跳(heart beat)的实时灾难应对解决方案,提高了系统的鲁棒性,同时提供了灵活的VIP配置和管理功能,可以同时满足多种应用需求[22]。


服务器优化

4.1 服务器整体性能考虑
对于价值昂贵的服务器来说,怎样配置才能发挥它的最大功效,又不至于影响正常的服务,这是在设计网站架构的时候必须要考虑的。常见的影响服务器的处理速度的因素有:网络连接,硬盘读写,内存空间,CPU速度。如果服务器的某一个部件满负荷运转仍然低于需要,而其他部件仍有能力剩余,我们将之称为性能瓶颈。服务器想要发挥最大的功效,关键的是消除瓶颈,让所有的部件都被充分的利用起来。

4.2 Socket优化
以标准的 GNU/Linux 为例。GNU/Linux 发行版试图对各种部署情况都进行优化,这意味着对具体服务器的执行环境来说,标准的发行版可能并不是最优化的[23]。GNU/Linux 提供了很多可调节的内核参数,可以使用这些参数为服务器进行动态配置,包括影响 Socket 性能的一些重要的选项。这些选项包含在 /proc 虚拟文件系统中。这个文件系统中的每个文件都表示一个或多个参数,它们可以通过 cat 工具进行读取,或使用 echo 命令进行修改。这里仅列出一些影响TCP/IP 栈性能的可调节内核参数[24]:

/proc/sys/net/ipv4/tcp_window_scaling “1”(1表示启用该选项,0表示关闭,下同) 启用 RFC[25] 1323[26] 定义的 window scaling;要支持超过 64KB 的窗口,必须启用该值。

/proc/sys/net/ipv4/tcp_sack “1”启用有选择的应答(Selective Acknowledgment),通过有选择地应答乱序接收到的报文来提高性能(这样可以让发送者只发送丢失的报文段);对于广域网通信来说,这个选项应该启用,但是这也会增加对 CPU 的占用。

/proc/sys/net/ipv4/tcp_timestamps “1” 以一种比重发超时更精确的方法(参阅 RFC 1323)来启用对 RTT 的计算;为了实现更好的性能应该启用这个选项。

/proc/sys/net/ipv4/tcp_mem “24576 32768 49152” 确定 TCP 栈应该如何反映内存使用;每个值的单位都是内存页(通常是 4KB)。第一个值是内存使用的下限。第二个值是内存压力模式开始对缓冲区使用应用压力的上限。第三个值是内存上限。超过这个上限时可以将报文丢弃,从而减少对内存的使用。

/proc/sys/net/ipv4/tcp_wmem “4096 16384 131072” 为自动调优定义每个 socket 使用的内存。第一个值是为 socket 的发送缓冲区分配的最少字节数。第二个值是默认值(该值会被 wmem_default 覆盖),缓冲区在系统负载不重的情况下可以增长到这个值。第三个值是发送缓冲区空间的最大字节数(该值会被 wmem_max 覆盖)。

/proc/sys/net/ipv4/tcp_westwood “1” 启用发送者端的拥塞控制算法,它可以维护对吞吐量的评估,并试图对带宽的整体利用情况进行优化;对于 WAN 通信来说应该启用这个选项。

与其他调优努力一样,最好的方法实际上就是不断进行实验。具体应用程序的行为、处理器的速度以及可用内存的多少都会影响到这些参数对性能作用的效果。在某些情况中,一些认为有益的操作可能恰恰是有害的(反之亦然)。因此,需要逐一试验各个选项,然后检查每个选项的结果,最后得出最适合具体机器的一套参数。

如果重启了 GNU/Linux 系统,设置的内核参数都会恢复成默认值。为了将所设置的值作为这些参数的默认值,可以使用 /etc/rc.local 文件,在系统每次启动时自动将这些参数配置成所需要的值。

在检测每个选项的更改带来的效果的时候,GNU/Linux上有一些非常强大的工具可以使用:

ping 这是用于检查主机的可用性的最常用的工具,也可以用于计算网络带宽延时。

traceroute 打印连接到特定网络主机所经过的一系列路由器网关的路径(路由),从而确定每个 hop 之间的延时。

netstat 确定有关网络子系统、协议和连接的各种统计信息。

tcpdump 显示一个或多个连接的协议级的报文跟踪信息,其中包括时间信息,可以使用这些信息来研究不同协议的报文时间。

Ethereal 以一个易于使用的图形化界面提供 tcpump (报文跟踪)的信息,支持报文过滤功能。

iperf 测量 TCP 和 UDP 的网络性能;测量最大带宽,并汇报延时和数据报的丢失情况。

4.3 硬盘级缓存
硬盘级别的缓存是指将需要动态生成的内容暂时缓存在硬盘上,在一个可接受的延迟时间范围内,同样的请求不再动态生成,以达到节约系统资源,提高网站承受能力的目的。Linux环境下硬盘级缓存一般使用Squid[27]。

Squid是一个高性能的代理缓存服务器。和一般的代理缓存软件不同,Squid用一个单独的、非模块化的、I/O驱动的进程来处理所有的客户端请求。它接受来自客户端对目标对象的请求并适当地处理这些请求。比如说,用户通过浏览器想下载(即浏览)一个web页面,浏览器请求Squid为它取得这个页面。Squid随之连接到页面所在的原始服务器并向服务器发出取得该页面的请求。取得页面后,Squid再将页面返回给用户端浏览器,并且同时在Squid本地缓存目录里保存一份副本。当下一次有用户需要同一页面时,Squid可以简单地从缓存中读取它的副本,直接返回给用户,而不用再次请求原始服务器。当前的Squid可以处理HTTP, FTP, GOPHER, SSL和WAIS等协议。

Squid默认通过检测HTTP协议头的Expires和 Cache-Control字段来决定缓存的时间。在实际应用中,可以显式的在服务器端脚本中输出HTTP头,也可以通过配置apache的 mod_expires模块,让apache自动的给每一个网页加上过期时间。对于静态内容,如图片,视频文件,供下载的软件等,还可以针对文件类型(扩展名),用 Squid 的 refresh_pattern 来指定缓存时间。

Squid 运行的时候,默认会在硬盘上建两层hash目录,用来存储缓存的Object。它还会在内存中建立一个Hash Table,用来记录硬盘中Object分布的情况。如果Squid配置成为一个Squid集群中的一个的话,它还会建立一个 Digest Table(摘要表),用来存储其它 Squid 上的Object摘要。当用户端想要的资料本地硬盘上没有时,可以很快的知道应该去集群中的哪一台机器获得。在硬盘空间快要达到配置限额的时候,可以配置使用某种策略(默认使用LRU:Least Recently Used-最近最少用)删除一些Object,从而腾出空间[28][29]。

集群中的Squid Server 之间可以有两种关系:第一种关系是:Child 和 Parent。当 Child Squid Server 没有资料时,会直接向 Parent Squid Server 要资料,然后一直等,直到 Parent 给它资料为止。 第二种关系是:Sibling 和 Sibling。当 Squid Server 没有资料时,会先向 Sibling 的 Squid Server 要资料,如果 Sibling 没资料,就跳过它向 Parent 要或直接上原始网站去拿。

默认配置的Squid,没有经过任何优化的时候,一般可以达到 50% 的命中率[30](图4)。如果需要,还可以通过参数优化,拆分业务,优化文件系统等办法,使得Squid达到 90% 以上的缓存命中率。 Squid处理TCP连接消耗的服务器资源比真正的HTTP服务器要小的多,当Squid分担了大部分连接,网站的承压能力就大大增强了。

蓝线表示Squid的流量,绿色部分表示Apache流量

4.4 内存级缓存
内存级别的缓存是指将需要动态生成的内容暂时缓存在内存里,在一个可接受的延迟时间范围内,同样的请求不再动态生成,而是直接从内存中读取。Linux环境下内存级缓存Memcached[31]是一个不错的选择。

Memcached是danga.com(运营Live Journal[32]的技术团队)开发的一套非常优秀的分布式内存对象缓存系统,用于在动态系统中减少数据库负载,提升性能。和 Squid 的前端缓存加速不同,它是通过基于内存的对象缓存来减少数据库查询的方式改善网站的性能,而其中最吸引人的一个特性就是支持分布式部署;也就是说可以在一群机器上建立一堆 Memcached 服务,每个服务可以根据具体服务器的硬件配置使用不同大小的内存块,这样,理论上可以建立一个无限大的基于内存的缓存系统。

Memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等[附录1]。客户端首先与 Memcached 服务建立连接,然后存取对象。每个被存取的对象都有一个唯一的标识符 key,存取操作均通过这个 key 进行,保存的时候还可以设置有效期。保存在 Memcached 中的对象实际上是放置在内存中的,而不是在硬盘上。Memcached 进程运行之后,会预申请一块较大的内存空间,自己进行管理,用完之后再申请一块,而不是每次需要的时候去向操作系统申请。Memcached将对象保存在一个巨大的Hash表中,它还使用NewHash算法来管理Hash表,从而获得进一步的性能提升。所以当分配给Memcached的内存足够大的时候,Memcached的时间消耗基本上只是网络Socket连接了[33]。

Memcached也有它的不足。首先它的数据是保存在内存当中的,一旦服务进程重启(进程意外被关掉,机器重启等),数据会全部丢失。其次Memcached以root权限运行,而且Memcached本身没有任何权限管理和认证功能,安全性不足。第一条是Memcached作为内存缓存服务使用无法避免的,当然,如果内存中的数据需要保存,可以采取更改Memcached的源代码,增加定期写入硬盘的功能。对于第二条,我们可以将Memcached服务绑定在内网IP上,通过Linux防火墙进行防护。

4.5 CPU与IO均衡
在一个网站提供的所有功能中,有的功能可能需要消耗大量的服务器端IO资源,像下载,视频播放等,而有的功能则可能需要消耗大量的服务器CPU资源,像视频格式转换,LOG统计等。在一个服务器集群中,当我们发现某些机器上CPU和IO的利用率相差很大的时候,例如CPU负载很高而IO负责很低,我们可以考虑将该服务器上的某些耗CPU资源的进程换成耗IO的进程,以达到均衡的目的。均衡每一台机器的CPU和IO消耗,不仅可以获得更充分的服务器资源利用,而且还能够支持暂时的过载,遇到突发事件,访问流量剧增的时候, 实现得体的性能下降(Graceful performance degradation)[34],而不是立即崩溃。

4.6 读写分离
如果网站的硬盘读写性能是整个网站性能提升的一个瓶颈的话,可以考虑将硬盘的读,写功能分开,分别进行优化。在专门用来写的硬盘上,我们可以在Linux 下使用软件RAID-0(磁盘冗余阵列0级)[35]。RAID-0在获得硬盘IO提升的同时,也会增加整个文件系统的故障率——它等于RAID中所有驱动器的故障率之和。如果需要保持或提高硬盘的容错能力,就需要实现软件RAID-1,4或5,它们能在某一个(甚至几个)磁盘驱动器故障之后仍然保持整个文件系统的正常运行[36],但文件读写效率不如RAID-0。而专门用来读的硬盘,则不用如此麻烦,可以使用普通的服务器硬盘,以降低开销。

一般的文件系统,会综合考虑各种大小和格式的文件的读,写效率,因而对特定的文件读或写的效率不是最优。如果有必要,可以通过选择文件系统,以及修改文件系统的配置参数来达到对特定文件的读或写的效率最大化。比如说,如果文件系统中需要存储大量的小文件,则可以使用 ReiserFS[37]来替代Linux操作系统默认的ext3系统,因为ReiserFS是基于平衡树的文件系统结构,尤其对于大量文件的巨型文件系统,搜索速度要比使用局部的二分查找法的ext3快。 ReiserFS里的目录是完全动态分配的,因此不存在ext3中常见的无法回收巨型目录占用的磁盘空间的情况。ReiserFS里小文件(< 4K)可以直接存储进树,小文件读取和写入的速度更快,树内节点是按字节对齐的,多个小文件可共享同一个硬盘块,节约大量空间。ext3使用固定大小的块分配策略,也就是说,不到4K的小文件也要占据4K的空间,导致的空间浪费比较严重[38]。但ReiserFS对很多Linux内核支持的不是很好,包括2.4.3、2.4.9 甚至相对较新的 2.4.16,如果网站想要使用它,就必须要安装与它配合的较好的2.4.18内核——一般管理员都不是很乐意使用太新的内核,因为在它上面运行的软件,都还没有经过大量的实践测试,也许有一些小的bug还没有被发现,但对于服务器来说,再小的bug也是不能接受的。ReiserFS还是一个较为年轻的,发展迅速的文件系统,它相对于ext3来说有一个很大的缺陷就是,每次ReiserFS文件系统升级的时候,必须完全重新格式化整个磁盘分区。所以在选择使用的时候,需要权衡取舍[39]。


5 应用程序层优化

5.1 网站服务器程序的选择
经统计[40],当前互联网上有超过50%的网站主机使用Apache[41]服务器程序。 Apache是开源界的首选Web服务器,因为它的强大和可靠,而且适用于绝大部分的应用场合。但是它的强大有时候却显得笨重,配置文件复杂得让人望而生畏,高并发情况下效率不太高。而轻量级的Web服务器Lighttpd[42]却是后起之秀,基于单进程多路复用技术,其静态文件的响应能力远高于 Apache。 Lighttpd对PHP的支持也很好,还可以通过Fastcgi方式支持其他的语言,比如Python等。虽然Lighttpd是轻量级的服务器,功能上不能跟Apache比,某些复杂应用无法胜任,但即使是大部分内容动态生成的网站,仍免不了会有一些静态元素,比如图片、JS脚本、CSS等等,可以考虑将Lighttpd放在Squid的前面,构成 Lighttpd->Squid->Apache的一条处理链,Lighttpd在最前面,专门处理静态内容的请求,把动态内容请求通过 Proxy模块转发给Squid,如果Squid中有该请求的内容且没有过期,则直接返回给Lighttpd。新请求或者过期的页面请求交由Apache 中的脚本程序来处理。经过Lighttpd和Squid的两级过滤,Apache需要处理的请求大大减少,减少了Web应用程序的压力。同时这样的构架,便于把不同的处理分散到多台计算机上进行,由Lighttpd在前面统一分发。

在这种架构下,每一级都是可以进行单独优化的,比如Lighttpd可以采用异步IO方式,Squid可以启用内存来缓存,Apache可以启用MPM(Multi -Processing Modules,多道处理模块)等,并且每一级都可以使用多台机器来均衡负载,伸缩性好。

著名视频分享网站YouTube就是选择使用Lighttpd作为网站的前台服务器程序。

5.2 数据库选择
MySQL[43]是一个快速的、多线程、多用户和健壮的SQL数据库服务器,支持关键任务、重负载系统的使用,是最受欢迎的开源数据库管理系统,是Linux下网站开发的首选。它由MySQL AB开发、发布和提供支持。

MySQL数据库能为网站提供:

高性能。MySQL支持海量,快速的数据库存储和读取。还可以通过使用64位处理器来获取额外的一些性能,因为MySQL在内部里很多时候都使用64位的整数处理。

易用性。MySQL的核心是一个小而快速的数据库。它的快速连接,快速存取和安全可靠的特性使MySQL非常适合在互联网站上使用。

开放性。MySQL提供多种后台存储引擎的选择,如MyISAM, Heap, InnoDB,Berkeley Db等。缺省格式为MyISAM。 MyISAM 存储引擎与磁盘兼容的非常好[44]。

支持企业级应用。MySQL有一个用于记录数据改变的二进制日志。因为它是二进制的,这一日志能够快速地将数据的更改从一台机器复制(replication)到另一台机器上。即使服务器崩溃,这一二进制日志也能够保持完整。这一特性通常被用来搭建数据库集群,以支持更大的流量访问要求[30](图5)。


 

MySQL也有一些它自身的缺陷,如缺乏图形界面,缺乏存储过程, 还不支持触发器,参照完整性,子查询和数据表视图等,但这些功能都在开发者的TO-DO列表当中。这就是开源的力量:你永远可以期待更好。

国外的Yahoo!,国内的新浪,搜狐等很多大型商业网站都使用MySQL 作为后台数据库。对于一般的网站系统,无论从成本还是性能上考虑,MySQL应该是最佳的选择。

5.3 服务器端脚本解析器的选择
目前最常见的服务器端脚本有三种:ASP(Active Server Pages),JSP(Java Server Pages),PHP (Hypertext Preprocessor)[45][46]。

ASP全名Active Server Pages,以及它的升级ASP.NET,是微软公司出品的一个WEB服务器端的开发环境,利用它可以产生和运行动态的、交互的、高性能的WEB服务应用程序。ASP采用脚本语言VBScript(C#)作为自己的开发语言。 但因为只能运行在Windows环境下,这里我们不讨论它。

PHP是一种跨平台的服务器端的嵌入式脚本语言。它大量地借用C,Java和Perl语言的语法,并耦合PHP自己的特性,使WEB开发者能够快速地写出动态生成页面。它支持目前绝大多数数据库。PHP也是开源的,它的发行遵从GPL开源协议,你可以从 PHP官方站点(http://www.php.net)自由下载到它的二进制安装文件及全部的源代码。如果在Linux平台上与MySQL搭配使用,PHP是最佳的选择。

JSP是Sun公司推出的新一代站点开发语言,是Java语言除Java应用程序和Java Applet之外的第三个应用。Jsp可以在Serverlet和JavaBean的支持下,完成功能强大的站点程序。作为采用Java技术家族的一部分,以及Java 2(企业版体系结构)的一个组成部分,JSP技术拥有Java技术带来的所有优点,包括优秀的跨平台性,高度可重用的组件设计,健壮性和安全性等,能够支持高度复杂的基于Web的应用。

除了这三种常见的脚本之外,在Linux下我们其实还有很多其他的选择:Python(Google使用),Perl等,如果作为CGI调用,那么可选择范围就更广了。使用这些不太常见的脚本语言的好处是,它们对于某些特殊的应用有别的脚本所不具有的优势;不好的地方是,这些脚本语言在国内使用的人比较少,当碰到技术上的问题的时候,能找到的资料也较少。

5.4 可配置性
在大型网站开发过程中,不管使用什么技术,网站的可配置性是必须的。在网站的后期运营过程中,肯定会有很多的需求变更。如果每一次的需求变更都会导致修改源代码,那么,这个网站的开发可以说是失败的。

首先,也是最重要的一点,功能和展示必须分开。PHP和JSP都支持模板技术,如PHP的 Smarty,Phplib,JSP的JSTL(JSP Standard Tag Library)等。核心功能使用脚本语言编写,前台展示使用带特殊标签的HTML,不仅加快了开发速度,而且方便以后的维护和升级[47]。

其次,对于前台模板,一般还需要将页面的头,尾单独提取出来,页面的主体部分也按模块或者功能拆分。对CSS,JS等辅助性的代码,也建议以单独的文件形式存放。这样不仅方便管理,修改,而且还可以在用户访问的时候进行缓存,减少网络流量,减轻服务器压力。

再次,对于核心功能脚本,必须将与服务器相关的配置内容,如数据库连接配置,脚本头文件路径等,与代码分离开。尤其当网站使用集群技术,CDN加速等技术的时候,每一台服务器上的配置可能都会不一样。如果不使用配置文件,则需要同时维护几份不同的代码,很容易出错。

最后,应该尽量做到修改配置文件后能实时生效,避免修改配置文件之后需要重启服务程序的情况。

5.5 封装和中间层思想
在功能块层次,如果使用JSP,基于纯面向对象语言Java的面向对象思想,类似数据库连接,会话管理等基本功能都已经封装成类了。如果使用PHP,则需要在脚本代码中显式的封装,将每一个功能块封装成一个函数,一个文件或者一个类。

在更高的层次,可以将网站分为表示层,逻辑层,持久层,分别进行封装,做到当某一层架构发生变化时,不会影响到其他层。比如新浪播客在一次升级的时候,将持久层的数据库由原来的集中式改为分布式架构,因为封装了数据库连接及所有操作[附录2],做到了不修改任何上层代码,平稳的实现了过渡。近来流行的MVC架构,将整个网站拆分成Model(模型/逻辑)、View(视图/界面)、Controller(控制/流程)三个部分,而且有很多优秀的代码框架可供选择使用, 像JSP的Structs,Spring,PHP的php.MVC, Studs 等。使用现成的代码框架,可以使网站开发事半功倍。


6 扩容、容错处理

6.1 扩容
一个大型网站,在设计架构的时候,必须考虑到以后可能的容量扩充。新浪播客在设计时充分地考虑了这一点。对于视频分享类网站来说,视频存储空间消耗是巨大的。新浪播客在主存储服务器上,采用配置文件形式指定每一个存储盘柜上存储的视频文件的ID范围。当前台服务器需要读取一个视频的时候,首先通过询问主存储服务器上的接口获得该视频所在的盘柜及目录地址,然后再去该盘柜读取实际的视频文件。这样如果需要增加存储用的盘柜,只需要修改配置文件即可,前台程序丝毫不受影响。

新浪播客采用MySQL数据库集群,在逻辑层封装了所有的数据库连接及操作。当数据库存储架构发生改变的时候,如增加一台主库,将某些数据表独立成库,增加读取数据用的从库等,都只需要修改封装了的数据库操作类,上层代码不用修改。

新浪播客的前台页面服务器使用F5公司的硬件第四层交换机,网通,电信分别导向不同的虚拟IP,每一个虚拟IP后面又有多个服务器提供服务。当访问流量增大的时候,可以很方便往虚拟IP后面增加服务器,分担压力。

6.2 容错
对于商业性网站来说,可用性是非常重要的。7*24的访问要求网站具有很强的容错能力。错误包括网络错误,服务器错误以及应用程序错误。

2006年12月27日台湾东部外海发生里氏7.6级地震,造成途径台湾海峡的多条海底电缆中断,导致许多国外网站,像MSN, NBA, Yahoo!(英文主站)等国内无法访问,但也有例外,以Google为代表的在国内建设有分布式数据节点的很多网站却仍然可以访问。虽然说地震造成断网是不可抗原因,但如果在这种情况下网站仍然可以访问,无疑能给网站用户留下深刻的印象。这件事情给大型商业网站留下的教训是:网站需要在用户主要分布区域保持数据存在,以防止可能的网络故障。

对于服务器错误,一般采取冗余设计的方法来避免。对于存储服务器(主要是负责写入的服务器),可以使用RAID(冗余磁盘阵列);对于数据库(主要是负责写入的主库),可以采用双主库设计[30];对于提供服务的前台,则可以使用第四层交换的集群,由多台服务器同时提供服务,不仅分担了流量压力,同时还可以互相作为备份。

在应用层程序中,也要考虑“用户友好”的出错设计。典型例子如HTTP 404 出错页面,程序内部错误处理,错误返回提示等,尽可能的做到人性化。


7 总结及展望

7.1 总结



对于一个高并发高流量的网站来说,任何一个环节的瓶颈都会造成网站性能的下降,影响用户体验,进而造成巨大的经济损失。在全互联网层面,应该使用分布式设计,缩短网站与用户的网络距离,减少主干网上的流量,以及防止在网络意外情况下网站无法访问的问题。在局域网层面,应该使用服务器集群,一方面可以支撑更大的访问量,另一方面也作为冗余备份,防止服务器故障导致的网站无法访问。在单服务器层面,应该配置操作系统,文件系统及应用层软件,均衡各种资源的消耗,消除系统性能瓶颈,充分发挥服务器的潜能。在应用层,可以通过各种缓存来提升程序的效率,减少服务器资源消耗(图6)。另外,还需要合理设计应用层程序,为以后的需求变更,扩容做好准备。

在每一个层次,都需要考虑容错的问题,严格消除单点故障,做到无论应用层程序错误,服务器软件错误,服务器硬件错误,还是网络错误,都不影响网站服务。

7.2展望
当前Linux环境下有著名的LAMP(Linux+Apache+MySQL+PHP/PERL/PYTHON)网站建设方案,但只是针对一般的中小网站而言。对于高并发高流量的大型商业网站,还没有一个完整的,性价比高的解决方案。除去服务器,硬盘,带宽等硬件投资外,还需要花费大量的预算和时间精力在软件解决方案上。

随着互联网的持续发展,Web2.0的兴起,在可以预见的未来里,互联网的用户持续增多,提供用户参与的网站不断增加,用户参与的内容日益增长,越来越多的网站的并发量,访问量会达到一个新的高度,这就会促使越来越多的个人,公司以及研究机构来关注高并发高流量的网站架构问题。就像Web1.0成就了无数中小网站,成就了LAMP一样,Web2.0注定也会成就一个新的,高效的,成本较低的解决方案。这个方案应该包括透明的第三方CDN网络加速服务,价格低廉的第四层甚至更高层网络交换设备,优化了网络性能的操作系统,优化了读写性能,分布式,高可靠的文件系统,揉合了内存,硬盘等各个级别缓存的HTTP服务器,更为高效的服务器端脚本解析器,以及封装了大部分细节的应用层设计框架。

技术的进步永无止境。我们期待互联网更为美好的明天。

http://blog.csdn.net/smarttony/article/details/5874485






网站架构
维基百科的网站架构
使用GeoDNS再配合Bind,可以使不同地方的用户访问时可以到达离用户最近的那台服务器,提高响应速度,也就是可以让DNS解析的时候考虑地域因素,让用户能够访问离他地域最近的Web服务器
在Squid前面架设了LVS,可能是有一个Squid集群吧,LVS用来做Squid的负载均衡(不知道对不对,只是猜测而已)
如果用户请求的数据是图片,则Squid将请求交给Lighttpd进行处理,Lighttpd处理静态数据性能更高。Squid中的其它数据通过NFS方式进行存储,NFS由Sun公司开发;如果Squid的缓存命中,则直接将数据返回给用户,如果缓存没有命中,则通知Squid,然后Squid将请求提交给Squid后面LVS,同理这里的LVS也是用来做负载均衡的,只不过此时的LVS是用于Web Server的负载均衡,Web Server是Apache
到了Web Server这一层面以后,PHP程序可以访问缓存Memcached里面的数据,同时PHP程序也可以访问MySQL里面的数据,另外可以通过HTCP协议访问Lucene里面的数据,Lucene主要用来做搜索,是用Java语言开发的
维基百科使用的系统是自己开发的MediaWiki,采用PHP语言开发
http://blog.csdn.net/smarttony/article/details/5811734


1.开心网的主站采用了DNS轮询技术,所谓DNS轮询,就是一个域名对应几条A记录,如开心网的主站有6台服务器
DNS轮询有一个缺点,如果域名所指向的某一个台服务器或几台服务器出现了问题(如Web服务器停止服务),则DNS轮询无法判断
C:/Users/caihuafeng>nslookup www.kaixin001.com
服务器:  ns.crcbj.com
Address:  61.233.9.9


非权威应答:
名称:    a.kaixin001.com
Addresses:  220.181.100.30
          220.181.100.35
          220.181.100.33
          220.181.100.34
          220.181.100.32
          220.181.100.31
Aliases:  www.kaixin001.com


2.a.kaixin001.com应该是域名www.kaixin001.com的别名,也就是大家用http://a.kaixin001.com/同样可以访问开心网
C:/Users/caihuafeng>nslookup a.kaixin001.com
服务器:  ns.crcbj.com
Address:  61.233.9.9


非权威应答:
名称:    a.kaixin001.com
Addresses:  220.181.100.31
          220.181.100.35
          220.181.100.32
          220.181.100.34
          220.181.100.33
          220.181.100.30


3.查询域名服务器ns.crcbj.com的一些情况
C:/Users/caihuafeng>nslookup -qt=ns ns.crcbj.com
服务器:  ns.crcbj.com
Address:  61.233.9.9


crcbj.com
        primary name server = dns7.hichina.com
        responsible mail addr = hostmaster.hichina.com
        serial  = 2008070200
        refresh = 3600 (1 hour)
        retry   = 600 (10 mins)
        expire  = 604800 (7 days)
        default TTL = 3600 (1 hour)


4.查看开心网的邮件服务器情况
根据nslookup查询出的情况,我猜想mail1.kaixin001.com及mail2.kaixin002.com应该是开心网的邮件服务器,开心网有上千万的用户,专门有两台邮件服务器是比较正常的;另外ns1.kaixin001.com ~ ns4.kaixin001.com这4台服务器应该是开心网的域名服务器
C:/Users/caihuafeng>nslookup -qt=mx kaixin001.com
服务器:  ns.crcbj.com
Address:  61.233.9.9


非权威应答:
kaixin001.com   MX preference = 10, mail exchanger = mail1.kaixin001.com
kaixin001.com   MX preference = 20, mail exchanger = mail2.kaixin001.com


kaixin001.com   nameserver = ns3.kaixin001.com
kaixin001.com   nameserver = ns1.kaixin001.com
kaixin001.com   nameserver = ns2.kaixin001.com
kaixin001.com   nameserver = ns4.kaixin001.com
mail2.kaixin001.com     internet address = 123.125.59.127
mail1.kaixin001.com     internet address = 119.161.132.228
ns2.kaixin001.com       internet address = 220.181.100.173
ns1.kaixin001.com       internet address = 123.103.102.240
ns3.kaixin001.com       internet address = 119.161.132.240
ns4.kaixin001.com       internet address = 123.125.57.13


5.开心网域名解析过程的模拟


在默认情况下nslookup使用的是我们在本机TCP/IP配置中的DNS服务器进行查询,但有时候我们需要指定一个特定的服务器进行查询试验。这时候我们不需要更改本机的TCP/IP配置,只要在命令后面加上指定的服务器IP或者域名就可以了。这个参数在我们对一台指定服务器排错是非常必要的,另外我们可以通过指定服务器直接查询授权服务器的结果避免其他服务器缓存的结果


例如下面的测试在域名服务器f.gtld-servers.net下找不到域名www.kaixin001.com解析结果,而在域名服务器ns1.kaixin001.com下能查询到域名www.kaixin001.com解析结果,说明域名服务器ns.kaixin001.com保持有域名www.kaixin001.com的信息
C:/Users/caihuafeng>nslookup -norecurse www.kaixin001.com f.gtld-servers.net
(root)  nameserver = c.root-servers.net
(root)  nameserver = h.root-servers.net
(root)  nameserver = b.root-servers.net
(root)  nameserver = f.root-servers.net
(root)  nameserver = d.root-servers.net
(root)  nameserver = a.root-servers.net
(root)  nameserver = j.root-servers.net
(root)  nameserver = l.root-servers.net
(root)  nameserver = g.root-servers.net
(root)  nameserver = e.root-servers.net
(root)  nameserver = k.root-servers.net
(root)  nameserver = i.root-servers.net
(root)  nameserver = m.root-servers.net
c.root-servers.net      internet address = 192.33.4.12
h.root-servers.net      internet address = 128.63.2.53
h.root-servers.net      AAAA IPv6 address = 2001:500:1::803f:235
b.root-servers.net      internet address = 192.228.79.201
f.root-servers.net      internet address = 192.5.5.241
f.root-servers.net      AAAA IPv6 address = 2001:500:2f::f
d.root-servers.net      internet address = 128.8.10.90
a.root-servers.net      internet address = 198.41.0.4
a.root-servers.net      AAAA IPv6 address = 2001:503:ba3e::2:30
j.root-servers.net      internet address = 192.58.128.30
j.root-servers.net      AAAA IPv6 address = 2001:503:c27::2:30
l.root-servers.net      internet address = 199.7.83.42
g.root-servers.net      internet address = 192.112.36.4
服务器:  UnKnown
Address:  192.35.51.30


*** UnKnown 找不到 www.kaixin001.com: BAD ERROR VALUE


C:/Users/caihuafeng>nslookup -norecurse www.kaixin001.com ns1.kaixin001.com
DNS request timed out.
    timeout was 2 seconds.
服务器:  UnKnown
Address:  123.103.102.240


名称:    a.kaixin001.com
Addresses:  220.181.100.31
          220.181.100.30
          220.181.100.34
          220.181.100.32
          220.181.100.33
          220.181.100.35
Aliases:  www.kaixin001.com
同理输入nslookup -norecurse www.kaixin001.com ns2.kaixin001.com,nslookup -norecurse www.kaixin001.com ns3.kaixin001.com,nslookup -norecurse www.kaixin001.com ns4.kaixin001.com也会有类似的解析结果,只不过Addresses后面的ip地址输出顺序不完全一样。



说说大型高并发高负载网站的系统架构
转载请保留出处:俊麟 Michael’s blog (http://www.toplee.com/blog/?p=71)
Trackback Url :http://www.toplee.com/blog/wp-trackback.php?p=71

  我在CERNET做过拨号接入平台的搭建,而后在Yahoo&3721从事过搜索引擎前端开发,又在MOP处理过大型社区猫扑大杂烩的架构升级等工作,同时自己接触和开发过不少大中型网站的模块,因此在大型网站应对高负载和并发的解决方案上有一些积累和经验,可以和大家一起探讨一下。


  一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求,已经不是原来简单的html静态网站所能比拟的。

  大型网站,比如门户网站。在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面,还没法根本解决大型网站面临的高负载和高并发问题。

  上面提供的几个解决思路在一定程度上也意味着更大的投入,并且这样的解决思路具备瓶颈,没有很好的扩展性,下面我从低成本、高性能和高扩张性的角度来说说我的一些经验。

1、HTML静态化
  其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。

  除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。目前很多博客也都实现了静态化,我使用的这个Blog程序WordPress还没有静态化,所以如果面对高负载访问,www.toplee.com一定不能承受 

  同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。

  在进行html静态化的时候可以使用一种折中的方法,就是前端使用动态实现,在一定的策略下进行定时静态化和定时判断调用,这个能实现很多灵活性的操作,我开发的台球网站故人居(www.8zone.cn)就是使用了这样的方法,我通过设定一些html静态化的时间间隔来对动态网站内容进行缓存,达到分担大部分的压力到静态页面上,可以应用于中小型网站的架构上。故人居网站的地址:http://www.8zone.cn,顺便提一下,有喜欢台球的朋友多多支持我这个免费网站:)

2、图片服务器分离
  大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃。

  在应用服务器和图片服务器上,可以进行不同的配置优化,比如Apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗和执行效率。

  我的台球网站故人居8zone.cn也使用了图片服务器架构上的分离,目前是仅仅是架构上分离,物理上没有分离,由于没有钱买更多的服务器:),大家可以看到故人居上的图片连接都是类似img.9tmd.com或者img1.9tmd.com的URL。

  另外,在处理静态页面或者图片、js等访问方面,可以考虑使用lighttpd代替Apache,它提供了更轻量级和更高效的处理能力。

3、数据库集群和库表散列
  大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。

  在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。

  上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。

4、缓存
  缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。

  架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的mod_proxy缓存模块,也可以使用外加的Squid进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。

  网站程序开发方面的缓存,Linux上提供的Memcached是常用的缓存方案,不少web编程语言都提供memcache访问接口,php、perl、c和java都有,可以在web开发中使用,可以实时或者Cron的把数据、对象等内容进行缓存,策略非常灵活。一些大型社区使用了这样的架构。

  另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块和eAccelerator加速和Cache模块,还要知名的Apc、XCache(国人开发的,支持!)php缓存模块,Java就更多了,.net不是很熟悉,相信也肯定有。

5、镜像
  镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等工具。

6、负载均衡
  负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。

  负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,我个人接触过一些解决方法,其中有两个架构可以给大家做参考。另外有关初级的负载均衡DNS轮循和较专业的CDN架构就不多说了。

6.1 硬件四层交换
  第四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。 第四层交换功能就象是虚IP,指向物理服务器。它传输的业务服从的协议多种多样,有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上,需要复杂的载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。

  在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。

6.2 软件四层交换
  大家知道了硬件四层交换机的原理后,基于OSI模型来实现的软件四层交换也就应运而生,这样的解决方案实现的原理一致,不过性能稍差。但是满足一定量的压力还是游刃有余的,有人说软件实现方式其实更灵活,处理能力完全看你配置的熟悉能力。

  软件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满足多种应用需求,这对于分布式的系统来说必不可少。

  一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。

总结:
  对于大型网站来说,前面提到的每个方法可能都会被同时使用到,Michael这里介绍得比较浅显,具体实现过程中很多细节还需要大家慢慢熟悉和体会,有时一个很小的squid参数或者apache参数设置,对于系统性能的影响就会很大,希望大家一起讨论,达到抛砖引玉之效。

  转载请保留出处:俊麟 Michael’s blog (http://www.toplee.com/blog/?p=71)
Trackback Url :http://www.toplee.com/blog/wp-trackback.php?p=71

This entry is filed under C / C++ / 其他技术, 技术交流. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.


 (2 votes, average: 6.5 out of 10)
 Loading ...
65 Responses to “说说大型高并发高负载网站的系统架构”
1
pi1ot says:

April 29th, 2006 at 1:00 pm
Quote
各模块间或者进程间的通信普遍异步化队列化也相当重要,可以兼顾轻载重载时的响应性能和系统压力,数据库压力可以通过file cache分解到文件系统,文件系统io压力再通过mem cache分解,效果很不错.

3
guest says:

May 1st, 2006 at 8:13 am
Quote
完全胡说八道!
“大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的”,你以为是在内存中动态生成图片啊.无论是什么文件,在容器输出时只是读文件,输出给response而已,和是什么文件有什么关系.

关键是静态文件和动态页面之间应该采用不同策略,如静态文件应该尽量缓存,因为无论你请求多少次输出内容都是相同的,如果用户页面中有二十个就没有必要请求二十次,而应该使用缓存.而动态页面每次请求输出都不相同(否则就应该是静态的),所以不应该缓存.

所以即使在同一服务器上也可以对静态和动态资源做不同优化,专门的图片服务器那是为了资源管理的方便,和你说的性能没有关系.

4
Michael says:

May 2nd, 2006 at 1:15 am
Quote
动态的缓存案例估计楼上朋友没有遇到过,在处理inktomi的搜索结果的案例中,我们使用的全部是面对动态的缓存,对于同样的关键词和查询条件来说,这样的缓存是非常重要的,对于动态的内容缓存,编程时使用合理的header参数可以方便的管理缓存的策略,比如失效时间等。

我们说到有关图片影响性能的问题,一般来说都是出自于我们的大部分访问页面中图片往往比html代码占用的流量大,在同等网络带宽的情况下,图片传输需要的时间更长,由于传输需要花很大开销在建立连接上,这会延长用户client端与server端的http连接时长,这对于apache来说,并发性能肯定会下降,除非你的返回全部是静态的,那就可以把 httpd.conf 中的 KeepAlives 为 off ,这样可以减小连接处理时间,但是如果图片过多会导致建立的连接次数增多,同样消耗性能。

另外我们提到的理论更多的是针对大型集群的案例,在这样的环境下,图片的分离能有效的改进架构,进而影响到性能的提升,要知道我们为什么要谈架构?架构可能为了安全、为了资源分配、也为了更科学的开发和管理,但是终极目都是为了性能。

另外在RFC1945的HTTP协议文档中很容易找到有关Mime Type和Content length部分的说明,这样对于理解图片对性能影响是很容易的。

楼上的朋友完全是小人作为,希望别用guest跟我忽悠,男人还害怕别人知道你叫啥?再说了,就算说错了也不至于用胡说八道来找茬!大家重在交流和学习,我也不是什么高人,顶多算个普通程序员而已。

5
Ken Kwei says:

June 3rd, 2006 at 3:42 pm
Quote
Michael 您好,这篇文章我看几次了,有一个问题,您的文章中提到了如下一段:

“对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。”

对于大型的站点来说,他的数据库和 Web Server 一般都是分布式的,在多个区域都有部署,当某个地区的用户访问时会对应到一个节点上,如果是对社区内的帖子实时静态化,有更新时再重新静态化,那么在节点之间如何立刻同步呢?数据库端如何实现呢?如果用户看不到的话会以为发帖失败?造成重复发了,那么如何将用户锁定在一个节点上呢,这些怎么解决?谢谢。

6
Michael says:

June 3rd, 2006 at 3:57 pm
Quote
对于将一个用户锁定在某个节点上是通过四层交换来实现的,一般情况下是这样,如果应用比较小的可以通过程序代码来实现。大型的应用一般通过类似LVS和硬件四层交换来管理用户连接,可以制定策略来使用户的连接在生命期内保持在某个节点上。

静态化和同步的策略比较多,一般采用的方法是集中或者分布存储,但是静态化却是通过集中存储来实现的,然后使用前端的proxy群来实现缓存和分担压力。


一般对于一个中型网站来说,交互操作非常多,日PV百万左右,如何做合理的负载?

交互如果非常多,可以考虑使用集群加Memory Cache的方式,把不断变化而且需要同步的数据放入Memory Cache里面进行读取,具体的方案还得需要结合具体的情况来分析。

11
donald says:

June 27th, 2006 at 5:39 pm
Quote
请问,如果一个网站处于技术发展期,那么这些优化手段应该先实施哪些后实施哪些呢?
或者说从成本(技术、人力和财力成本)方面,哪些先实施能够取得最大效果呢?

12
Michael says:

June 27th, 2006 at 9:16 pm
Quote
donald on June 27, 2006 at 5:39 pm said:

请问,如果一个网站处于技术发展期,那么这些优化手段应该先实施哪些后实施哪些呢?
或者说从成本(技术、人力和财力成本)方面,哪些先实施能够取得最大效果呢?

先从服务器性能优化、代码性能优化方面入手,包括webserver、dbserver的优化配置、html静态化等容易入手的开始,这些环节争取先榨取到最大化的利用率,然后再考虑从架构上增加投入,比如集群、负载均衡等方面,这些都需要在有一定的发展积累之后再做考虑比较恰当。

16
echonow says:

September 1st, 2006 at 2:28 pm
Quote
赞一个先,是一篇很不错的文章,不过要真正掌握里面的东西恐怕还是需要时间和实践!

先问一下关于图片服务器的问题了!

我的台球网站故人居9tmd.com也使用了图片服务器架构上的分离,目前是仅仅是架构上分离,物理上没有分离,由于没有钱买更多的服务器:),大家可以看到故人居上的图片连接都是类似img.9tmd.com或者img1.9tmd.com的URL。

这个,楼主这个img.9tmd.com是虚拟主机吧,也就是说是一个apache提供的服务吧,这样的话对于性能的提高也很有意义吗?还是只是铺垫,为了方便以后的物理分离呢?

17
Michael says:

September 1st, 2006 at 3:05 pm
Quote
echonow on September 1, 2006 at 2:28 pm said:

赞一个先,是一篇很不错的文章,不过要真正掌握里面的东西恐怕还是需要时间和实践!

先问一下关于图片服务器的问题了!

我的台球网站故人居9tmd.com也使用了图片服务器架构上的分离,目前是仅仅是架构上分离,物理上没有分离,由于没有钱买更多的服务器:),大家可以看到故人居上的图片连接都是类似img.9tmd.com或者img1.9tmd.com的URL。

这个,楼主这个img.9tmd.com是虚拟主机吧,也就是说是一个apache提供的服务吧,这样的话对于性能的提高也很有意义吗?还是只是铺垫,为了方便以后的物理分离呢?

这位朋友说得很对,因为目前只有一台服务器,所以从物理上无法实现真正的分离,暂时使用虚拟主机来实现,是为了程序设计和网站架构上的灵活,如果有了一台新的服务器,我只需要把图片镜像过去或者同步过去,然后把img.9tmd.com的dns解析到新的服务器上就自然实现了分离,如果现在不从架构和程序上实现,今后这样的分离就会比较痛苦:)

18
echonow says:

September 7th, 2006 at 4:59 pm
Quote
谢谢lz的回复,现在主要实现问题是如何能在素材上传时直接传到图片服务器上呢,总不至于每次先传到web,然后再同步到图片服务器吧

19
Michael says:

September 7th, 2006 at 11:25 pm
Quote
echonow on September 7, 2006 at 4:59 pm said:

谢谢lz的回复,现在主要实现问题是如何能在素材上传时直接传到图片服务器上呢,总不至于每次先传到web,然后再同步到图片服务器吧

通过samba或者nfs实现是比较简单的方法。然后使用squid缓存来降低访问的负载,提高磁盘性能和延长磁盘使用寿命。

20
echonow says:

September 8th, 2006 at 9:42 am
Quote
多谢楼主的耐心指导,我先研究下,用共享区来存储确实是个不错的想法!

21
Michael says:

September 8th, 2006 at 11:16 am
Quote
echonow on September 8, 2006 at 9:42 am said:

多谢楼主的耐心指导,我先研究下,用共享区来存储确实是个不错的想法!

不客气,欢迎常交流!


http://space.itpub.net/7311285/viewspace-97






1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:580574次
    • 积分:8540
    • 等级:
    • 排名:第2248名
    • 原创:312篇
    • 转载:63篇
    • 译文:0篇
    • 评论:11条
    文章分类
    最新评论