高并发高流量网站架构设计(参考)
目 录1引言91.1互联网的发展91.2互联网网站建设的新趋势91.3新浪播客的简介112网络层架构122.1镜像网站技术122.2 CDN内容分发网络132.3应用层分布式设计162.4网络层架构小
目 录
1引言9
1.1互联网的发展9
1.2互联网网站建设的新趋势9
1.3新浪播客的简介11
2网络层架构12
2.1镜像网站技术12
2.2 CDN内容分发网络13
2.3应用层分布式设计16
2.4网络层架构小结17
3交换层架构17
3.1第四层交换简介17
3.2硬件实现18
3.3软件实现18
4服务器优化19
4.1服务器整体性能考虑19
4.2 Socket优化19
4.3硬盘级缓存22
4.4内存级缓存24
4.5 CPU与IO 均衡26
4.6读写分离26
5应用程序层优化28
5.1网站服务器程序的选择28
5.2数据库选择29
5.3服务器端脚本解析器的选择30
5.4可配置性32
5.5封装和中间层思想33
6扩容、容错处理33
6.1扩容33
6.2容错34
7总结及展望35
7.1总结35
7.2展望36
高并发高流量网站架构
我也来说两句 查看全部评论 相关评论
,*
逆雪寒 (2007-12-17 11:55:26)
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 网络层架构
2.1 镜像网站技术
镜像网站是指将一个完全相同的站点放到几个服务器上,分别有自己的URL ,这些服务器上的网站互相称为镜像网站[13]。镜像网站和主站并没有太大差别,或者可以视为主站的拷贝。镜像网站的好处是:如果不能对主站作正常访问(如服务器故障,网络故障或者网速太慢等),仍能通过镜像服务器获得服务。不便之处是:更新网站内容的时候,需要同时更新多个服务器;需要用户记忆超过一个网址,或需要用户选择访问多个镜像网站中的一个,而用户选择的,不一定是最优的。在用户选择的过程中,缺乏必要的可控性。
在互联网发展的初期,互联网上的网站内容很少,而且大都是静态内容,更新频率底。但因为服务器运算能力低,带宽小,网速慢,热门网站的访问压力还是很大。镜像网站技术在这种情况下作为一种有效解决方案,被广泛采用。随着互联网的发展,越来越多的网站使用服务器端脚本动态生成内容,同步更新越来越困难,对可控性要求越来越高,镜像技术因为不能满足这类网站的需要,渐渐的淡出了人们的视线。但有一些大型的软件下载站,因为符合镜像网站的条件——下载的内容是静态的,更新频率较低,对带宽,速度要求又比较高,如国
,外的SourceForge ([url]http://www.SourceForge.net[/url],著名开源软件托管网站),Fedora ([url]http://fedoraproject.org[/url],RedHat 赞助的Linux 发行版),国内的华军软件园([url]http://www.onlinedown.net[/url]),天空软件站([url]http://www.skycn.com[/url])等,还在使用这项技术(图
1)。
图1 上图:天空软件站首页的镜像选择页面
下图:SourceForge 下载时的镜像选择页面
在网站建设的过程中,可以根据实际情况,将静态内容作一些镜像,以加快访问速度,提升用户体验。
2.2 CDN内容分发网络
CDN的全称是Content Delivery Network ,即内容分发网络。其目的是通过在现有的互联网中增加一层新的网络架构,将网站的内容发布到最接近用户的网络“边缘”,使用户可以就近取得所需的内容,分散服务器的压力,解决互联网拥挤的状况,提高用户访问网站的响应速度。从而解决由于网络带宽小、用户访问量大、网点分布不均等原因所造成的用户访问网站响应速度慢的问题[14]。
CDN与镜像网站技术的不同之处在于网站代替用户去选择最优的内容服务器,增强了可控制性。CDN 其实是夹在网页浏览者和被访问的服务器中间的一层镜像或者说缓存,浏览者访问时点击的还是服务器原来的URL 地址,但是看到的内容其实是对浏览者来说最优的一台镜像服务器上的页面缓存内容。这是通过调整服务器的域名解析来实现的。使用CDN 技术的域名解析服务器需要维护一个镜像服务器列表和一份来访IP 到镜像服务器的对应表。当一个用户的请求到来的时候,根据用户的IP ,查询对应表,得到最优的镜像服务器的IP 地址,返回给用户。这里的最优,需要综合考虑服务器的处理能力,带宽,离访问者的距离远近等因素。当某个地方的镜像网站流量过大,带宽消耗过快,或者出现服务器,网络等故障的时候,可以很方便的设置将用户的访问转到另外一个地方(图
2)。这样就增强了可控制性。
图2 CDN原理示意图
CDN网络加速技术也有它的局限性。首先,因为内容更新的时候,需要同步更新多台镜像服务器,所以它也只适用于内容更新不太频繁,或者对实时性要求不是很高的网站;其次,DNS 解析有缓存,当某一个镜像网站的访问需要
,转移时,主DNS 服务器更改了IP 解析结果,但各地的DNS 服务器缓存更新会滞后一段时间,这段时间内用户的访问仍然会指向该服务器,可控制性依然有不足。
目前,国内访问量较高的大型网站如新浪、网易等的资讯频道,均使用CDN 网络加速技术(图3),虽然网站的访问量巨大,但无论在什么地方访问,速度都会很快。但论坛,邮箱等更新频繁,实时性要求高的频道,则不适合使用这种技术。
图3 新浪网使用ChinaCache CDN服务。
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 服务器优化
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 的网络性能;测量最大带宽,并汇报延时和数据报的丢失情况。
*
逆雪寒 (2007-12-17 11:55:53)
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 分担了大部分连接,网站的承压能力就大大增强了。
图
4 某网站使用MRTG 工具检测到的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 均衡