千万级 PV 规模高性能高并发网站架构

高并发web网站架构设计
高并发访问的核心原则其实就一句话“把所有的用户访问请求都尽量往前推”。
如果把来访用户比作来犯的"敌人",我们一定要把他们挡在 800 里地以外,即不能让他们的
请求一下打到我们的指挥部(指挥部就是数据库及分布式存储)。
如:能缓存在用户电脑本地的,就不要让他去访问 CDN/cache。能缓存 CDN/cache 服务器上
的,就不要让 CDN/cache 去访问源(静态 web 服务器)了。能访问静态 web 服务器的,就
不要去访问动态服务器。以此类推:能不访问数据库和存储就一定不要去访问数据库和存储。
高性能高并发高可扩展网站架构访问的几个层次:
第一层:首先在用户浏览器端,使用 Apache 的 mod_deflate 压缩传输,再比如: expires 功
能,deflate 和 expires 功能利用的好,就会大大提升用户体验效果及减少网站带宽,减少后端
服务器的压力。
提示:有关压缩传输及 expires 功能 nginx/lighttpd 等软件同样也有。
第二层: 静态页面内容缓存,如图片/js/css 等或静态数据 html,这个层面是网页缓存层,比
如 CDN(效果比公司自己部署 squid/nginx/varnish 要好,他们更专业,价格低廉,比如快网
/CC 等,而且覆盖的城市节点更多)。 自己架设 squid/nginx/varnish 来做小型 CDN 是次选(超大
规模的公司可能会考虑风险问题实行自建加购买服务结合),为前端的 CDN 提供数据源服务,
以减轻后端我们的服务器数据及存储压力,而不是直接提供 cache 服务给最终用户。 淘宝的
CDN曾经因为一部分图片的尺寸大而导致CDN压力大的情况,甚至对图片尺寸大的来改小,
以达到降低流量及带宽的作用。
提示:我们也可以自己架设一层 cache 层,对我们购买的 CDN 提供数据源服务,可用的软
件有 varnish/nginx/squid 等 cache,以减轻第三层静态数据层的压力。在这层的前端我们也
可以架设 DNS 服务器,来达到跨机房业务拓展及智能解析的目的。
第三层:静态服务器层一般为图片服务器,视频服务器,静态 HTML 服务器。这一层是前面
缓存层和后面动态服务器层的连接纽带。
第四层:动态服务器层: php,java 等,只有通过了前面 3 层后的访问请求才会到这个层,才
可能会访问数据库及存储设备。经过前三层的访问过滤能到这层访问请求一般来说已非常少
了,一般都是新发布的内容和新发布内容第一次浏览如;博文(包括微博等), BBS 帖子。
特别提示:此层可以在程序上多做文章,比如向下访问 cache 层, memcache,redis,mysql,oracle,
在程序级别实现分布式访问,分布式读写分离,而程序级别分布式访问的每个 db cache 节
点,又可以是一组业务或者一组业务拆分开来的多台服务器的负载均衡。这样的架构会为后
面的数据库和存储层大大的减少压力,那么这里呢,相当于指挥部的外层了。
第五层:数据库 cache 层,比如: memcache,redis 等等。
根据不同的业务需求,选择适合具体业务的数据库。对于 memcache、 redis,可以在第四层
通过程序来实现对本层实现分布式访问,每个分布式访问的节点都可能是一组负载均衡(数
数据库缓存memcache/redisPHP/JAVA 动态内容NFS/HADOOP等十台机器)。
第六层:数据库层,一般的不是超大站点都会用 mysql 主从结构,程序层做分布式数据库读
写分离,一主(或双主)多从的方式,访问大了, 可以做级连的主从及环状的多主多从,然
后,实现多组负载均衡,供前端的分布式程序调用, 如果访问量再大, 就需要拆业务了,比
如: 分司把 www 服务,blog 服务, bbs 服务都放一个服务器上,然后做主从。这种情况,当
业务访问量大了,可以简单的把 www,blog,bbs 服务分别各用一组服务器拆分开。当然访问
量再大了,可以继续针对某一个服务拆分如: www 库拆分,每个库做一组负载均衡,还可
以对库里的表拆分。需要高可用可以通过 MHA 等工具做成高可用方式。对于写大的,可以
做主主或多主的 MYSQL REP 方式。
像百度等巨型公司除了会采用常规的 mysql 及 oracle 数据库库外,会在性能要求更高的领
域,大量的使用 nosql 数据库(非关系型的数据库),然后前端在加 DNS,负载均衡,分布
式的读写分离,最后依然是拆业务,拆库,。。。逐步细化,然后每个点又可以是一组或多组
机器。
特别提示:数据库层的硬件好坏也会决定访问量的多少,尤其是要考虑磁盘 IO 的问题,大
公司往往在性价比上做文章,比如核心业务采用硬件 netapp/emc 及 san 光纤架构,对于资
源数据存储,如图片视频,会采用 sas 或固态 ssd 盘,如果数据超大,可以采取热点分取分
存的方法:如:最常访问的 10-20%使用 ssd 存储,中间的 20-30%采用 sas 盘,最后的 40-50%
可以采用廉价的 sata。
第七层:千万级 PV 的站如果设计的合理一些, 1, 2 个 NFS SERVER 就足够了。当然可以做
成 drbd+heartbeat+nfs+a/a 的方式。
以上 1-7 层,如果都搭好了,这样漏网到第四层动态服务器层的访问,就不多了。一般的中
等站点,绝对不会对数据库造成太大的压力。程序层的分布式访问是从千万及 PV 向亿级 PV
的发展,当然特殊的业务还需要特殊架构,来合理利用数据库和存储。
扩展知识点 1: CDN 的全称是 Content Delivery Network,即内容分发网络。其基本思路是尽
可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更
稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网
络, CDN 系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应
时间等综合信息将用户的请求重新导向离用户最近的服务节点上。 其目的是使用户可就近取
得所需内容,解决 Internet 网络拥挤的状况,提高用户访问网站的响应速度。
举个通俗的例子:
谈到 CDN 的作用,可以用早些年买火车票来比喻: 在没有火车票代售点和 12306.cn 之前。
那时候火车票还只能在火车站的售票大厅购买,而小县城并不通火车,火车票都要去市里的
火车站购买,而从县城到市里,来回就得 n 个小时车程。
到后来,小县城里出现了火车票代售点,可以直接在代售点购买火车,方便了不少,人们再
也不用在一个点排队买票了。
CDN 就可以理解为分布在每个县城的火车票代售点,用户在浏览网站的时候, CDN 会选择
一个离用户最近的 CDN 节点来响应用户的请求,这样海南移动用户的请求就不会千里迢迢
跑到北京电信机房的服务器(假设源站部署在北京电信机房)上了。
CDN 的基本原理为反向代理,反向代理(Reverse Proxy)方式是指以代理服务器来接受 internet
上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给
internet 上请求连接的客户端,此时代理服务器对外就表现为一个节点服务器。通过部署更
多的反向代理服务器,来达到实现多节点 CDN 的效果。
首先, 让我们先看传统的未加缓存服务的访问过程,以便了解 CDN 缓存访问方式与未加缓存访问方式的差别:
高并发web网站架构设计_第1张图片
用户提交域名→浏览器对域名进行解析→得到目的主机的 IP 地址→根据 IP 地址访问发出请
求→得到请求数据并回复
由上可见,用户访问未使用 CDN 缓存网站的过程为:
1)、用户向浏览器提供要访问的域名;
2)、浏览器调用域名解析函数库对域名进行解析,以得到此域名对应的 IP 地址;
3)、浏览器使用所得到的 IP 地址,向域名的服务主机发出数据访问请求;
4)、浏览器根据域名主机返回的数据显示网页的内容。
通过以上四个步骤,浏览器完成从用户处接收用户要访问的域名到从域名服务主机处获取数
据的整个过程。 CDN 网络是在用户和服务器之间增加 Cache 层
高并发web网站架构设计_第2张图片
如何将用户的请求引导到 Cache 上获得源服务器的数据,主要是通过接管 DNS 实现,下面
让我们看看访问使用 CDN 缓存后的网站的过程:
高并发web网站架构设计_第3张图片
通过上图,我们可以了解到,使用了 CDN 缓存后的网站的访问过程变为:1)、用户向浏览器提供要访问的域名;
2)、浏览器调用域名解析库对域名进行解析,由于 CDN 对域名解析过程进行了调整,所以解
析函数库一般得到的是该域名对应的 CNAME 记录,为了得到实际 IP 地址,浏览器需要再次
对获得的 CNAME 域名进行解析以得到实际的 IP 地址;在此过程中,使用的全局负载均衡 DNS
解析,如根据地理位置信息解析对应的 IP 地址,使得用户能就近访问。
3)、此次解析得到 CDN 缓存服务器的 IP 地址,浏览器在得到实际的 IP 地址以后,向缓存服
务器发出访问请求;
4)、缓存服务器根据浏览器提供的要访问的域名,通过 Cache 内部专用 DNS 解析得到此域名
的实际 IP 地址,再由缓存服务器向此实际 IP 地址提交访问请求;
5)、缓存服务器从实际 IP 地址得得到内容以后,一方面在本地进行保存,以备以后使用,
另一方面把获取的数据返回给客户端,完成数据服务过程;
6)、客户端得到由缓存服务器返回的数据以后显示出来并完成整个浏览的数据请求过程。
通过以上的分析我们可以得到,为了实现既要对普通用户透明(即加入缓存以 后用户客户端
无需进行任何设置,直接使用被加速网站原有的域名即可访问,只要修改整个访问过程中的
域名解析部分,以实现透明的加速服务。
下面是 CDN 网络实现的具体操作过程。
使用了 CDN 服务后,用户的访问流程如下图所示:
高并发web网站架构设计_第4张图片
1.用户向浏览器输入 www.web.com 这个域名,浏览器第一次发现本地没有 dns 缓存,则向
网站的 DNS 服务器请求;
2.网站的 DNS 域名解析器设置了 CNAME,指向了 www.web.51cdn.com,请求指向了 CDN 网络
中的智能 DNS 负载均衡系统;
3.智能 DNS 负载均衡系统解析域名,把对用户响应速度最快的 IP 节点返回给用户;
4.用户向该 IP 节点(CDN 服务器)发出请求;
5.由于是第一次访问, CDN 服务器会向原 web 站点请求,并缓存内容;
6.请求结果发给用户。
CDN 网络是在用户和服务器之间增加 Cache 层,如何将用户的请求引导到 Cache 上获得源服
务器的数据,主要是通过接管 DNS 实现,这就是 CDN 的最基本的原理,当然很多细节没有
涉及到,比如第 1 步,首先向本地的 DNS 服务器请求。第 5 步,内容淘汰机制(根据 TTL)
等。但原理大体如此。
当用户访问加入CDN服务的网站时,域名解析请求将最终交给全局负载均衡DNS进行处理。
全局负载均衡DNS通过一组预先定义好的策略,将当时最接近用户的节点地址提供给用户,使用户能够得到快速的服务。同时,它还与分布在世界各地的所有 CDNC 节点保持通信,搜
集各节点的通信状态,确保不将用户的请求分配到不可用的 CDN 节点上,实际上是通过 DNS
做全局负载均衡。
对于普通的 Internet 用户来讲,每个 CDN 节点就相当于一个放置在它周围的 WEB。通过全
局负载均衡 DNS 的控制,用户的请求被透明地指向离他最近的节点,节点中 CDN 服务器会
像网站的原始服务器一样,响应用户的请求。由于它离用户更近,因而响应时间必然更快。
每个 CDN 节点由两部分组成:负载均衡设备和高速缓存服务器
负载均衡设备负责每个节点中各个 Cache 的负载均衡,保证节点的工作效率;同时,负载均
衡设备还负责收集节点与周围环境的信息,保持与全局负载 DNS 的通信,实现整个系统的
负载均衡。 CDN 的管理系统是整个系统能够正常运转的保证。它不仅能对系统中的各个子系
统和设备进行实时监控,对各种故障产生相应的告警,还可以实时监测到系统中总的流量和
各节点的流量,并保存在系统的数据库中,使网管人员能够方便地进行进一步分析。通过完
善的网管系统,用户可以对系统配置进行修改。
理论上,最简单的 CDN 网络有一个负责全局负载均衡的 DNS 和各节点一台 Cache,即可运
行。 DNS 支持根据用户源 IP 地址解析不同的 IP,实现就近访问。为了保证高可用性等,需
要监视各节点的流量、健康状况等。一个节点的单台 Cache 承载数量不够时,才需要多台
Cache,多台 Cache 同时工作,才需要负载均衡器,使 Cache 群协同工作。
CDN 的典型拓扑图如下:
高并发web网站架构设计_第5张图片
CDN 和反向代理的基本原理都是缓存数据,区别就在于 CDN 部署在网络提供商的机房,使
用户在请求网站服务时,可以从距离自己最近的网络提供商机房获取数据。
CDN 对网络的优化作用:
CDN 系统通过在网络各处放置节点服务器,从而将网站的内容放置到离用户最近的地方,避
免了影响互联网传输性能的“第一公里”和“网间互联瓶颈”等各个环节,为改善互联网环境、
解决网站的服务质量和提高用户的上网速度提供了有效的解决方案。
CDN 对网络的优化作用主要体现在如下几个方面:
解决服务器端的“第一公里”问题缓解甚至消除了不同运营商之间互联的瓶颈造成的影响
减轻了各省的出口带宽压力
缓解了骨干网的压力
提起 CDN,一般人都会望而止步,因为 CDN 太贵,都是大企业才能用得起的贵族式服务,而
如今面对中小企业的 CDN 技术开发已经实现,并进入市场开始运营。
现在市面上 CDN 提供商计费方式多样,有按每月最低消费的,有按带宽收费的,有按请求数
收费的,有包月包季包年限制的,还有些大多人看不懂的技术指标收费的,总之比较复杂,
CDN 服务在所有计费方式中,中小企业一致认为按流量收费最为合理,另外大多按流量计费
方式中会有时间限制,规定时间内用不完就会全部作废,对于流量把握不好的中小企业,存
在相当一部分浪费。 所以企业自已也可以使用 squid/varnish/nginx 等构建缓存服务器。
扩展知识点 2: pvuvip
PV(page view): 即页面浏览量,或点击量, PV 是网站分析的一个术语,用以衡量网站用户
访问的网页的数量。一般来说, PV 与来访者的数量成正比,但是 PV 并不直接决定页面的真
实来访者数量,如同一个来访者通过不断的刷新页面,也可以制造出非常高的 PV。
UV(unique visitor)即独立访客数: 指访问某个站点或点击某个网页的不同 IP 地址的人数。
在同一天内, UV 只记录第一次进入网站的具有独立 IP 的访问者,在同一天内再次访问该网
站则不计数。 UV 提供了一定时间内不同观众数量的统计指标,而没有反应出网站的全面活
动。
通过 cookie 是判断 UV 值的方式:
用 Cookie 分析 UV 值: 当客户端第一次访问某个网站服务器的时候,网站服务器会给这个客
户端的电脑发出一个 Cookie,通常放在这个客户端电脑的 C 盘当中。在这个 Cookie 中会分
配一个独一无二的编号,这其中会记录一些访问服务器的信息,如访问时间,访问了哪些页
面等等。当你下次再访问这个服务器的时候,服务器就可以直接从你的电脑中找到上一次放
进去的 Cookie 文件,并且对其进行一些更新,但那个独一无二的编号是不会变的。 所以当
客户端再次使用 cookie 访问网站时,会附带此 Cookie,那么此时服务器就会认为是同一个
客户端,那么只会记录一次的 UV
使用 Cookie 方法比分析客户端 HTTP 请求头部信息更为精准,但是会有缺点,那就是用户可
能会关闭了 Cookie 功能。或者自动删除了 cookie 等操作,所以获取的指标也不能说是完全
准确。
IP 即独立 IP 数:
IP 可以理解为独立 IP 的访问用户,指 1 天内使用不同 IP 地址的用户访问网站的数量,同一
IP 无论访问了几个页面,独立 IP 数均为 1。但是假如说两台机器访问而使用的是同一个 IP,
那么只能算是一个 IP 的访问。
IP 和 UV 之间的数据不会有太大的差异,通常 UV 量和比 IP 量高出一点,每个 UV 相对于每
个 IP 更准确地对应一个实际的浏览者。
①UV 大于 IP
这种情况就是在网吧、学校、公司等,公用相同 IP 的场所中不同的用户,或者多种不同浏
览器访问您网站,那么 UV 数会大于 IP 数。
②UV 小于 IP
在家庭中大多数电脑使用 ADSL 拨号上网,所以同一个用户在家里不同时间访问您网站时,
IP 可能会不同,因为它会根据时间变动 IP,即动态的 IP 地址,但是实际访客数唯一,便会
出现 UV 数小于 IP 数。PV 和 UV 是衡量一个网站流量好坏的一个重要指标,对于网站的 PV 和 UV 的统计,可使用
第三方统计工具进行统计,只需要将第三方统计工具的 JS 代码放置于网站需要统计 PV 和
UV 的页面即可,然后登录统计工具后台查询网站的 PV 和 UV 量(如可使用的第三方统计工
具为百度统计);
查询方法
1. 使用 alexa 统计
英文站: http://www.alexa.com/
中文站: http://alexa.chinaz.com/
2. 一般大型网站都有自己的一套流量统计系统,可以到自己的后台查看。
3. 如果没有的话,可以借助 GoogleAnalytics、 cnzz、 51.la 等统计平台查看数据。
IP、 PV、 UV 的计算
对 IP 计算
1.分析网站的访问日志,去除相同的 IP 地址
2.使用第三方统计工具
3.在网页后添加多一个程序代码统计字段,然后使用日志分析工具对程序代码字
段进行统计。
对 PV 的计算
1.分析网站的访问日志,计算 HTML 及动态语言等网页的数量
2.使用第三方统计工具
3.在网页后添加多一个程序代码统计字段,然后使用日志分析工具对程序代码字
段进行统计。
对 UV 的计算
1.分析客户端的 HTTP 请求报文,将客户端特有的信息记录下来进行分析。若能
满足共同的特征将会被认为是同一个客户端,那么此时将记录为一个 UV。
2.通过 cookie
当客户端访问一个网站时,服务器会向该客户端发送一个 Cookie, Cookie 具有独
一性,所以当客户端再次使用 cookie 访问网站时,会附带此 Cookie,那么此时
服务器就会认为是同一个客户端,那么只会记录一次的 UV
缺点:使用 Cookie 方法比分析客户端 HTTP 请求头部信息更为精准,但是会有缺
点,那就是用户可能会关闭了 Cookie 功能。或者自动删除了 cookie 等操作,所
以获取的指标也不能说是完全准确。
每秒并发数预估:

  1. 假如每天的 pv 为 6000 万;
  2. 集中访问量: 240.2=4.8 小时, 会有 6000 万0.8=4800 万(二八原则);
  3. 每分并发量: 4.8*60=288 分钟,每分钟访问 4800/288=16.7 万(约等于);
  4. 每秒并发量: 16.7 万/60=2780(约等于);
  5. 假设:高峰期为平常值的二到三倍,则每秒的并发数可以达到 5560~8340 次。

    6. 千万 PV 级别 WEB 站点架构设计

    高并发web网站架构设计_第6张图片
    1、 代理层可以使用 Haproxy 或 nginx, Haproxy/nginx 是非常优秀的反向代理软件,十
    分高效、稳定。 可以考虑用 F5-LTM 或成熟的开源解决方案 LVS 实现代理层负载均衡方案。
    2、 缓存层可以使用 Squid 或 Varnish, 缓存服务器作为网页服务器的前置 cache 服务器,
    可以代理用户向 web 服务器请求数据并进行缓存。
    3、静态 web 服务器( apache/nginx) 提供静态内容访问,实现静动分离; 通过相关工具
    (lvs/haproxy/nginx)做负载均衡(Load Balancer)
    4、动态内容服务器(php/java) 通过相关工具如 xcache 缓存解析过的动态内容。
    5、数据库缓存(memcache/redis) 作为数据库缓存都非常理想。
    6、 数据库层主流开源解决方案 Mysql 是首选,主从复制(一主对多从或多主多从)是目前
    比较靠谱的模式。
    7、存储层作为数据的存储可以考虑 nfs、分布式文件系统(如 mfs)、 hadoop(hadoop
    适合海量数据的存储与处理,如做网站日志分析、用户数据挖掘等)
    当用户请求的是静态资源(图片/视频/html 等),不需要计算处理时,在 CDN 或缓存层就结束了,
    当缓存不能命中时,就会去 web server 中取相应的数据。只有当用户请求动态资源时,才会
    到动态内容服务器。 动态内容服务器可以从数据库缓存或者 MySQL 中获得数据。
    此外,如果前端的程序和数据的存取不同步,是需要异步访问的。这就需要使用一些消息队
    列,如 rabbitmq,这在后面 openstack 相关学习做进一步的讲解。同时 Apache 的开源项目
    中的 activemq 也能提供相关的功能。
    注: 消息队列可以解决子系统/模块之间的耦合,实现异步,高可用,高性能的系统。是分
    布式系统的标准配置。
    例如消息队列在购物,配送环节的应用。
    用户下单后,写入消息队列,后直接返回客户端;
    库存子系统:读取消息队列信息,完成减库存;
    配送子系统:读取消息队列信息,进行配送;
    高并发web网站架构设计_第7张图片