集群架构规划和设计只要是涉及到高并发高流量的项目,基本上都需要。
本文主要围绕两个方面,一个是IDC的规划和选择,另一个是CDN。
一、IDC的规划和选择
IDC的选择是网站上线前要做的最重要的事情之一。哪怕发展初期只有一台服务器,选择一个位置不错的机房托管,都会助益良多。
也许有人会问IDC是什么?
我引用百度百科来回答:
IDC为互联网内容提供商(ICP)、企业、媒体和各类网站提供大规模、高质量、安全可靠的专业化服务器托管、空间租用、网络批发带宽以及ASP、EC等业务。IDC是对入驻(Hosting)企业、商户或网站服务器群托管的场所;是各种模式电子商务赖以安全运作的基础设施,也是支持企业及其商业联盟(其分销商、供应商、客户等)实施价值链管理的平台。 名词解释(业务理解非演讲内容) ICP:互联网信息服务,比如新浪、搜狐、网易。互联网信息服务可分为经营性信息服务和非经营性信息服务两类。
IDC翻译过来的单词极速互联网数据中心。
1.网站性质决定基础面
首先,我们需要对网站的性质和情况又足够确定的信息。这不单单是说当前的情况,还包括对未来至少一年的预期。因为IDC合同至少要签一年。
网站性质,第一指网站用户的分布范围。区域性的网站必然选择本区域内的IDC服务,比如各省卫视的网站,甚至更小一些的各市信息港等;全国性质的网站,要考虑到北上广浙等经济发达地区才是主力消费人群的集聚地,提高这部分用户的访问体验,就需要尽量把IDC选择在这些区域内;全球性质的网站,比如外贸性质的,或者选择国内运营商主力外联节点位置,或者干脆选择海外IDC,像香港、美国、日本、新加坡和英国等。
其次考虑网站具体业务的性质。新闻门户类的网站,与娱乐游戏类的网站,在高峰时段、流量类型等方面的要求不一样。比如新闻门户,高峰在早9点上班前后;而娱乐游戏类,高峰在晚9点餐饮结束后,可以一直持续到次日凌晨2点,周末更是流量高峰的高峰;至于电子交易类,13点午餐后也有个高峰时段。
再次还有用户数量级。IDC需要应对的用户访问量是十万、百万还是千万,直接关系到对机柜和出口带宽的需求。而这也是考察IDC时很重要的一点。当然这个数据换算本身也涉及业务性质的区别。
2.IDC厂商服务质量
考察IDC厂商的服务质量,有如下几个参考指标?
(1)IDC出口总带宽
出口总带宽和剩余带宽几乎可以认为是最关键的指标。如果不了解这个问题,当业务飞速发展时会发现想扩展带宽都扩展不了,简直是致命的打击。
(2)连通性和稳定性
确定带宽可以满足以后,下一步就是确认网络质量,即IDC出口到各大节点或者其他IDC网络的连通性和稳定性。这方面建议自行测试一两天,如果业务类型对双休日要求比较严格,甚至可以测试一星期来确认其稳定性。
ping测试显然是最常用的,一般来说,万分之三以下的丢包率是完全可以接受的。但是不能只以ping测试决定,某些IDC会针对ICMP包进行专门的优先级设置,所以还需要进一步模拟业务流量的HTTP测试等。
(3)电力供应
需要了解电流上限,这涉及到机柜和主机的比例。另一个重要问题则是IDC的双路电力是哪双路,是否真的足以保证供电率。如果都没有双路,基本是不用考虑。
(4)空调散热和机柜密度
这个问题可能不太引起关注,但是温度对服务器寿命确实有影响。
(5)走线和环境管理
走线是比较能体现IDC工程师水准的一件事。通常根据这些小细节,可以推测出IDC的综合实力。类似的还有出入证件检查是否严格,是否提供鞋套、显示器、键盘、推车和板凳等。
(6)其他售后服务
包括是否协助上架、是否可以7x24小时接收重启服务电话、接电话到完成操作的响应速度、除值班电话以外是否还有应急联系人等。
3.BGP真伪的验证
在IDC规划和采购时,大家可能听的比较多的一句话就是“双线BGP接入”,甚至五线七线等。那么这些宣传的真伪如何?
其实我们可以通过其IP及AS好归属很简单对比出来。
BGP真伪验证可以参考这篇博文:https://hqidi.com/73.html
二、CDN规划
在集群规划中,有一句话叫“缓存为王”。这个思想,可以从操作系统底层设计开始,层层类推到网站集群的总体规划。
当然,这其中如CPU二级缓存、RAID卡缓存之类,我们通过对比测试发现其作用,并作出恰当的采购和维护即可。而在网络数据层面,诸如MySQL的query cache、InnoDB buffer pool,或者memcached、Redis等,多有赖于数据库管理人员和后端开发人员,运维人员以配合为主,这里不再赘述。从网页服务器之外,到用户浏览器这一段,才是运维的主要战场。这个战场,又分为两个部分:第一部分是浏览器缓存,前雅虎首席性能官史蒂夫.桑德斯针对网站性能有一句名言,叫做"最快的HTTP请求是没有产生请求",就是针对浏览器缓存来说的;第二部分是代理服务器缓存,在大规模网络环境下,这一部分可以扩展成为一个完整的内容分发网络(Content Delivery Network)。
关于CDN可以参考我的这篇文章:https://www.cnblogs.com/youcong/p/9607448.html
1.CDN原理
CDN的工作原理用一句话概括,就是将内容提供商的数据,以最快捷的方式分发到离用户尽可能近的地方与用户交互,以节省内容重复传输的时间。“互联网高速公路的最后一公里”,正是对CDN的形象描述。
上面这句话中,有三个关键字,分别代表CDN技术中的三个关键点。
(1)内容数据:在早期互联网环境中,80%以上的内容都是静态文本,CDN技术近乎特指静态内容加速。到如今,互联网上提供的内容,在静态文本和图片之外,还包括各种动态生成的页面、视频、视频码流等。
(2)分发方式:从内容提供商到离用户最近的CDN节点,数据流向可以由内容提供商主动发往CDN节点的,也可以是由CDN节点向内容提供商发请求下载。不同的分发方式,会导致CDN的效果、实现和管理方式,都大不相同。
(3)尽可能近:互联网上的距离与现实距离并不完全等同。尤其在国内的现实环境中,同城网民跨网访问都慢如蜗牛。这里,我们需要对用户的上网接入环境有所判断,找到真正“近”的CDN节点提供服务。
CDN工作原理图:
2.DNS原理
DNS是提高集群可用性的重要工具,也是CDN系统最常用的全局负载调度工具。掌握DNS的原理和管理,是网站运维人员的重要职责。
(1)DNS的由来
在网络刚刚出现的时候,只有IP地址。后来出现主机名的概念,于是NIC(NetWork Information Center,互联网信息中心)提供了一个文本文件供大家下载,文件名叫"hosts.txt",里面存储有整个网络中所有主机的主机名和对应的IP地址。每隔几天,NIC就收集一次全网主机的信息来更新这个文本,然后各主机的管理员们随后下载这个文本维护新的主机名映射。同时这也是Hosts文件的由来。
互联网的先行者们大大低估了这个“怪物”的成长速度。IPv4的故事大家已经熟知,hosts.txt则更早碰到了天花板-没人能维护这个飞速增长的主机名和IP地址映射关系。
所以为了规范互联网上百花齐放的主机名,同时也为了构建一个可管理的体现,最终形成了RFC1034,DNS就此诞生了(这段简要的概述,描绘了DNS的前世今生)。
(2)DNS的设计
DNS设计之初,提出了如下几个要求?
(1)能够指明网络地址、路由等信息。
(2)分布式存储(以确保数据正确性,在失败时可以使用缓存数据)。
(3)数据格式支持多协议传输,这里指的是应用层协议,即FTP、SSH、RSYNC、SMTP等。
(4)支持多协议访问,这里指的是网络层协议,即TCP和UDP协议。
可以说,DNS系统,是全世界最早、规模最大的分布式系统。
(3)DNS组成
一个完整的DNS系统,由下面的三个元素组成。
a.域名空间和资源记录
域名空间是一个树状结构。树状结构的每个节点都对应一个资源集(可能为空);每个节点的标记为0~63B;节点的域名由从节点到根的标记连接组成。
当域名的节点最多不超过127个,不过一般来说,实际软件实现中支持的域名长度不会超过255B。
资源记录是和名字相关的数据。
b.名字服务器
服务器端程序,用来保留域名空间和资源记录,并响应相关客户请求。一般名字服务器只保存域名空间的一个子集,以使子集成为这个子集的权威。一个子集内的信息又叫做一个区,其他信息通过其他名字服务器查询。
c.解析器
客户端程序,可以访问至少一个名字服务器,接收这个名字服务器返回的结果或者转向其他名字服务器查询。
(4)DNS查询过程
a.递归查询
递归查询可以用一句话来归纳:"请对方辩友正面回答!",也就是说,客户端请求必须得到名字服务器一个"yes or no"的响应结果,然后完成这次解析。
一般情况下,电脑客户端都会使用递归查询。
b.迭代查询
迭代查询可用医院咨询台做比喻。
进医院看病的人,先到咨询台问:“我牙疼找谁看?”
咨询台会说:"你挂牙科号,上三楼右拐牙科分诊台。”
也就是说:服务器端(咨询台)返回一个可能知道该域名(牙科)解析结果的名字服务器(分诊台),然后客户端重新去那台查询。
注意:迭代查询这个过程是可以累加的,因为本次获得的这个名字服务器,可能会继续返回一个"可能"知道该域名的名字服务器。就好像你到了三楼分诊台,按提示到了某诊室,里头还有好几个医生,然后你要再询问一次,才知道最后谁给你看病。
3.DNS查询结构实现
关于DNS查询结构实现涉及比较多东西,后期会详讲。
4.DNS调度
(1)DNS负载均衡
因为A记录可以返回多个,所以在LVS没有诞生的中古时代,人们使用DNS做负载均衡的。不过这种负载均衡有很多问题:没有健康检查、没有权重设置、没有哈希分布、没有故障转移等。最重要的是,DNS设计中的TTL时间会导致故障发生时,即便运维人员手动干预,依然无法让用户的访问路由立刻变更为最新状态。
所以,DNS负载均衡至今依然是一项重要的应用,但绝对不是可信赖的负载均衡应用。
(2)动态DNS
所谓动态DNS,即针对相同的DNS解析请求,可以根据实际情况的变化响应不同的解析结果。
一类动态DNS以F5的GTM为代表,从公开文档中可知其首选调度算法是RTT。但是我们注意到DNS首选协议是UDP的,只有在数据包大小大于512B和zone transfer的时候才采用TCP协议。而UDP协议并没有RTT概念。由此可知,GTM是采用被动RTT方式来更新自己内部的动态路由表的。其工作流程大致如下:
a.NS返回一台GTM的IP给LDNS,LDNS请求到IP;
b.GTM在就近路由表中查询并返回离LDNS最近的解析结果;
c.如果路由表中还没有LDNS所在网段,这台GTM会联合其他GTM共同对LDNS发起TCP请求,计算RTT并汇总RTT结果,从而更新路由表返回最近结果;
另一类动态DNS则是根据请求的IP地址对应的view做区分,几个主要的DNS服务软件如Bind9、TinyDNS、WINMyDNS都支持这种动态解析。这种动态解析的运维难点,在于如何收集足够准确的IP段地址归属信息,并保持定期更新。目前来看,主要来源有几个:每月MaxMind的GeoLite数据库、不定期更新的纯真数据库和自建DNS数据库的请求日志归类分析。
5.其他调度方法
除了最常见的DNS调度外,CDN中还有其他调度方式,近年来比较常见的,是针对特定场景下的IP调度方式。
(1)视频流调度
在之前对DNS原理的介绍中,我们已经知道采用DNS调度的最大问题,就是用户配置的DNS是不受网络运维控制,因此带来的解析偏差,会导致请求响应的跨网络长距离访问。对于图片或者页面文本,结果可能是由十几毫秒变成几十或上百毫秒。而文件越大,传输延迟效果会明显。这对于视频网站来说,是最不可忍受的事情。
视频播放与页面显示不同,它是一个长期运行的过程,追求的不是瞬间的响应速度,而是长期的码流稳定。一般的高清网络视频(720p),码流要求在4Mbps以上。如果服务器距离用户接入还要经过十多跳路由反复接力,那效果肯定不如人意。
所以视频网站,一般会使用IP调度来尽可能的解决这个问题,思路如下:
a.视频播放器发出请求到网站的调度服务器。这一步可以先通过DNS调度调度来降低后期运算和复杂度;
b.调度服务器根据HTTP请求的来源IP,确认用户接入的实际归属;
c.调度服务器查找实际归属地最近的视频服务器IP,处理原请求的文件路径部分,拼接形成实际的视频播放下载地址并返回302响应;
d.视频播放器根据得到的302响应,从视频服务器下载视频播放;
(2)动态生成页面元素链接
视频流调度说的方法看起来不错,但实际是有其局限性的,它意味着原本一次就能完成的请求,被拆成两次才完成。其中重新建连等时间是多出来的,在动辄上兆字节(MB)大小的视频请求中,TCP建连、Header解析等时间可以忽略不计,但是在一个页面上有上千个只有几千字节(KB)甚至几字节大小的小文件元素请求的条件下,这个时间累积起来就非常影响用户体验了。
不过在大规模网站实践中,对于页面元素,也有一些变通的方法,可以针对特定情况来实现IP调度。针对页面大量使用的某一类元素,比如用户头像、商品图片等。因为其流量较大,重要性较高,原本就配备了专用的服务集群。这些元素在发布端不需要域名来做发布路径的对应区分即可提供服务。这时,我们可以把调度计算的负载,从图片发布的集群转移到动态页面生成发布的服务器上。稍微改造之前提到的调度流程变成下面这个步骤。
a.浏览器发送页面请求到动态页面服务器,同样这一步使用DNS调度来降低复杂度;
b.动态页面服务器根据HTTP请求的来源IP,确认用户接入的实际归属;
c.动态页面服务器查找离实际归属地最近的图片服务器IP,替换动态页面模板的图片文件路径的主机名部分,拼接形成实际的图片下载地址;
d.模板编译成完整的页面内容后,响应返回给浏览器解析渲染;
e.浏览器直接根据图片元素中的地址发起请求;
(3)BGP和anycast
anycast是一种网络技术,最早是1998年在RFC1546中提出的,意思是"主机向一个任播地址发送数据报,网络负责尽力将数据报传递到至少一个,最好也只是一个,按任播地址接收数据的服务器上。其设计初衷是彻底简化在网络中寻找特定服务器的任务。
从基础概念上听起来有点像后来大家熟悉的LVS。事实上anycast的几个重要优势,比如负载均衡、集群冗余和攻击防护,也都是LVS提供的,不过anycast因为通常运行在路由器层面,所以它可以简便地确定来源主机与目的主机组中的哪台主机最近。目前,anycast技术最典型的运用就是公共DNS服务。比如我们所熟知的Google Public DNS,其地址为8.8.8.8.
在部署上,anycast对网络资源要求极高,一般需要有自己的自治域号,自治域内不同的路由器对应不同的上联自治域,并采用BGP协议广播相同地址,这个IP地址就是anycast地址。路由器后端,可以是直连服务器,也可以是通过负载均衡集群,或者仍然采用anycast方式联系服务器。
anycast地址只能作为目的地址,不能作为源地址。因为每次报传输的实际主机可能都是不一样的。这点,我们可以通过DNS解析测试验证:配置8.8.8.8后,实际在DNS服务器收到的localDNS地址并不是8.8.8.8.后来IPV6出现后,新的RFC2373中修改明确了anycast的定义。
6.动态加速概述
传统的CDN系统,都是运用在静态文件加速上的,即便是视频点播,也是flv文件通过关键帧信息技术切分成一个个小的静态文件。不过随着技术和业务需求的发展,CDN系统也确定在慢慢出现针对动态业务的改进和扩展
(1)动静元素分离
现在的互联网应用,大多是富媒体形式,页面中图片、样式、客户端脚本的数量和字节数,都远远超过页面载体HTML文件。而页面加速的根本目的,是为了给应用用户更好的体验。只有样式符合预期的页面,才是对用户友好的、合格的页面:只有页面元素完整显示,才是页面真正加载完毕。
元素的本质变化分为两个方面,一个是实时变化,一个是非实时变化。
一般请求下,实时变化的元素少数,非实时变化的占大多数。将缓存控制的范围从CDN扩展到浏览器端时,很多可以缓存几秒钟的元素,也可以归入非实时变化的范畴。那么,真正绝对不能缓存的元素就更少了。
现在,更详细地规划原有域名拆分计划,保证至少实时和非实时变化的元素不要在同一域名下发布。其次,让过期比较敏感的元素,和不敏感的元素甚至永不过期的元素也在不同域名下发布。
在缓存过期维度以外,域名拆分通常还有另一个维度,即平均文件大小的差异。通常1MB以下和1MB以上的文件,会拆分到不同域名,甚至可以更详细到以100KB为界。这通常有缓存性能方面的考虑。
这样,页面上的大多数元素,都可以通过普通的CDN技术完成加速。只剩下少量的HTML、JSON等数据,需要每次等待源站遥远的响应。
动静元素分离是至今为止加速动态网站访问最基础最有效的方法。
(2)动态页面局部更新
动态页面最早期的实现方法是这样的,在cgi中解析处理请求参数,通过数据库处理返回值,拼接字符串,然后返回最后的页面结果。
稍后的实现进化成这样:动态程序员解析处理请求参数,通过数据库处理返回值后传递给模板系统,替换对应模板中的变量,生成最后的页面结果并返回。
后面这个办法,因为开启了模板系统的本地缓存,所以发布服务器响应性能可以提高很多。但是对于全网CDN系统来说,这些响应都是实时变动的内容,都无法缓存。
a.SSI和ESI
动态页面继续发展,人们逐渐发现所谓的动态页面中很多内容其实还是不变的,没必要一次又一次地生成,于是,SSI在模板技术的基础上被发明出来。
使用SSI,动态页面服务器只需要生成变化内容的那部分页面代码,然后由静态页面发布服务器,在响应请求时,通过SSI技术解析加载全部内容。这样,动态服务器的负载降低了,服务响应相对也就是更快了。
b.分级校对
ESI对页面开发人员能力有一定要求,不太适合通用情况。在标准HTML代码的环境下,也可以通过一些办法来尽力节约动态页面的传输。
下面说下基于跨网高延迟条件的设计方案:
001.CDN系统分为边缘节点和中心节点两层;
002.边缘节点收到用户请求,发起回源请求到中心节点;
003.中心节点发起回源请求到实际的页面发布服务器,并接收最新结果;
004.中心节点本地比对最新结果和上一个版本,得到一个补丁版本;
005.中心节点返回补丁版本给边缘节点;
006.边缘节点应用补丁更新本地缓存文件到最新版本,并返回给用户;
(3)传输网络优化
Web2.0以来,用户与服务器端的交互比重逐渐增加,已经不再是一边倒的下载流量,上传流量的优化也成为了CDN系统需要关注的问题。
针对这一方面的问题,目前主要是对TCP/IP层做一些优化。TCP协议设计要求是针对普适场景,有以下三个特征:
a.慢启动
TCP初始滑动窗口较小,默认是3。然后在建连的往返过程中翻倍增加。
在互联网接入带宽动辄上10MB的今天,这么小的滑动窗口初始值,显然是一种浪费。
因为网页元素本身较小,国内最大的CDN厂商蓝汛曾经统计过其服务的全部客户流量的总统计数,其平台的平均文件大小,只有4KB左右。
自Google首先提出这个问题,并将此初始值提高到10之后,这个做法已经逐渐得到广泛认可。随后,Linux内核从2.6.34版本开始可以通过IP命令直接修改这个参数,从3.0版本开始默认设置也提高到了10。
当然了,这个设置也不是万能药。其主要适用的是短连接和小文件的场景。对自身业务是否会有较大地性能提升,还需要经过实际测试来判定。
b.以丢包判断链路拥塞
主要考虑的是可靠链路上的拥塞问题,也就是说如果发现链路堵塞了,就减少小滑动窗口,慢一点发包,等拥塞解除再恢复原先的传输速度。
而事实中,在移动互联网的环境下,更多的是移动网络本身的信道问题导致链路错误引起丢包,结果TCP的滑动窗口一直维持在比较小的状态,整个数据传输陷入越传越慢的恶性循环。从这个场景出发,对于移动网络,出现拥塞时更好的应对反而是尽快地重发数据报。
c.滑动窗口的加性增乘性减
在传输过程中,如果一切正常,滑动窗口会在每个RTT都加1,。但是如果发生拥塞时,滑动窗口直接减半。这种加减办法对视频播放等应用比较不利,一次瞬间的带宽抖动,需要多几倍的时间才能恢复到之前的传输状态。
目前有很多商业产品在做TCP优化相关的工作。从部署架构上,可以分为单边加速和双边加速。从协议原理上区分,采用的技术包括数据包快速重传、滑动窗口加速滑动、ACK复制、合并数据包统一校验等。
在TCP的拥塞控制算法方面,Linxu2.6.8到2.6.19版本之间使用BIC,之后默认使用CUBIC。FreeBSD使用New Reno。此外,还有Vegas、HSTCP、FAST TCP、TCP SACK等。它们各自针对之前提到的三个主要特征做了相应的修改,以适应其他环境。
比如Vegas和FAST TCP不再以丢包为链路拥塞的判断依据而是参考发包队列的长度;HSTCP则修改了滑动窗口的增减规则,当前窗口越大,增加速度相对标准TCP就越快而减少得也越慢;DataCenterTCP则通过带有ECN(显示拥塞通知)的ACK包的比例,动态确定滑动窗口的减少程度。
(4)SPDY简介
在应用层上,也有各种对于加速的尝试。比如HTML5协议中的WebSocket技术、HTTP协议1.1版本规定的Presisent connnection和pipelining技术、以及很可能成为HTTP协议2.0版本的SPDY技术。
现有的HTTP协议,存在几个严重不足?
a.一个HTTP连接在同一时刻智能获取一个资源,而且一旦当前请求耗时比较长,后续请求都会被阻塞;
b.浏览器与服务器之间只能是单向的,即浏览器主动向服务器发请求;
c.Header信息在每次HTTP请求中都要完整地发送一遍;
WebSocket和pipelining也可以解决一部分上述问题。但是这两种技术都要求对网页进行较大程度地改造甚至是重写。而SPDY目前则在HTTP协议前提下,通过SSL层的处理,实现了对原有页面代码的兼容。
主要来说,SPDY有如下特点:
a.采用多路复用技术,在一个连接上并发请求,而且细化到CSS等重要类型的文件可以优先请求;
b.服务器可以主动给浏览器推送数据以加强预加载的能力,最新的协议说明中,甚至列出服务器可以给浏览器推送DNS记录的待实现项;
c.在同一连接内,不用重复发送相同的Header信息,而且Header信息还是通过压缩方式传输的;
d.强制使用SSL以提高安全性。当然这个特点在社区讨论中还屡屡被抵制;
从2012年以来,Google、Twitter、FaceBook、Amazon等网站都支持SPDY;而浏览器方面,Chrome、Firefox、Opera、Silk也都支持SPDY;服务器方面,Google最早推出的是Apache的mod_spdy模块,F5公司随后在其负载均衡产品跟进,Jetty、Nginx等也逐步完成SPDY的支持工作。可以说,SPDY的大规模使用,只等IE6等陈旧浏览器淘汰即可。
最后还要说一下,本篇还要续篇,可以理解为下文,下文主要讲缓存和本地负载均衡。希望这篇文章能够给大家带来有益的启发和收获。