大型网站框架的演变

                        大型网站框架的演变
 
以前也有一些介绍大型网站架构演变的文章,例如 LiveJournal 的、 ebay 的,都是很是值得参考的,不过感受他们讲的更多的是每次演变的结果,而没有很详细的讲为何须要作这样的演变,再加上近来感受有很多同窗都很难明白为何一个网站须要那么复杂的技术,因而有了写这篇文章的想法,在这篇文章中 将阐述一个普通的网站发展成大型网站过程当中的一种较为典型的架构演变历程和所需掌握的知识体系,但愿能给想从事互联网行业的同窗一点初步的概念, :) ,文中的不对之处也请各位多给点建议,让本文真正起到抛砖引玉的效果。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
架构演变第一步:物理分离webserver和数据库
最开始,因为某些想法,因而在互联网上搭建了一个网站,这个时候甚至有可能主机都是租借的,但因为这篇文章咱们只关注架构的演变历程,所以就假设这个时候 已是托管了一台主机,而且有必定的带宽了,这个时候因为网站具有了必定的特点,吸引了部分人访问,逐渐你发现系统的压力愈来愈高,响应速度愈来愈慢,而这个时候比较明显的是数据库和应用互相影响,应用出问题了,数据库也很容易出现问题,而数据库出问题的时候,应用也容易出问题,因而进入了第一步演变阶段:将应用和数据库从物理上分离,变成了两台机器,这个时候技术上没有什么新的要求,但你发现确实起到效果了,系统又恢复到之前的响应速度了,而且支撑住了更高的流量,而且不会由于数据库和应用造成互相的影响。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
这一步架构演变对技术上的知识体系基本没有要求。
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
架构演变第二步:增长页面缓存
好景不长,随着访问的人愈来愈多,你发现响应速度又开始变慢了,查找缘由,发现是访问数据库的操做太多,致使数据链接竞争激烈,因此响应变慢,但数据库连 接又不能开太多,不然数据库机器压力会很高,所以考虑采用缓存机制来减小数据库链接资源的竞争和对数据库读的压力,这个时候首先也许会选择采用 squid 等相似的机制来将系统中相对静态的页面(例如一两天才会有更新的页面)进行缓存(固然,也能够采用将页面静态化的方案),这样程序上能够不作修改,就可以 很好的减小对 webserver 的压力以及减小数据库链接资源的竞争, OK ,因而开始采用 squid 来作相对静态的页面的缓存。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
前端页面缓存技术,例如 squid ,如想用好的话还得深刻掌握下 squid 的实现方式以及缓存的失效算法等。
 
架构演变第三步:增长页面片断缓存
增长了 squid 作缓存后,总体系统的速度确实是提高了, webserver 的压力也开始降低了,但随着访问量的增长,发现系统又开始变的有些慢了,在尝 到了 squid 之类的动态缓存带来的好处后,开始想能不能让如今那些动态页面里相对静态的部分也缓存起来呢,所以考虑采用相似 ESI 之类的页面片断缓存策略, OK ,因而开始采用 ESI 来作动态页面中相对静态的片断部分的缓存。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
页面片断缓存技术,例如 ESI 等,想用好的话一样须要掌握 ESI 的实现方式等;
 
架构演变第四步:数据缓存
在采用 ESI 之类的技术再次提升了系统的缓存效果后,系统的压力确实进一步下降了,但一样,随着访问量的增长,系统仍是开始变慢,通过查找,可能会发现系 统中存在一些重复获取数据信息的地方,像获取用户信息等,这个时候开始考虑是否是能够将这些数据信息也缓存起来呢,因而将这些数据缓存到本地内存,改变完毕后,彻底符合预期,系统的响应速度又恢复了,数据库的压力也再度下降了很多。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
缓存技术,包括像 Map 数据结构、缓存算法、所选用的框架自己的实现机制等。
 
架构演变第五步: 增长webserver
好景不长,发现随着系统访问量的再度增长, webserver 机器的压力在高峰期会上升到比较高,这个时候开始考虑增长一台 webserver ,这也是为了同时解决可用性的问题,避免单台的 webserver down 机的话就无法使用了,在作了这些考虑后,决定增长一台 webserver ,增长一台 webserver 时,会碰到一些问题,典型的有:
1
、如何让访问分配到这两台机器上,这个时候一般会考虑的方案是 Apache 自带的负载均衡方案,或 LVS 这类的软件负载均衡方案;
2
、如何保持状态信息的同步,例如用户 session 等,这个时候会考虑的方案有写入数据库、写入存储、 cookie 或同步 session 信息等机制等;
3
、如何保持数据缓存信息的同步,例如以前缓存的用户数据等,这个时候一般会考虑的机制有缓存同步或分布式缓存;
4
、如何让上传文件这些相似的功能继续正常,这个时候一般会考虑的机制是使用共享文件系统或存储等;
在解决了这些问题后,终因而把 webserver 增长为了两台,系统终因而又恢复到了以往的速度。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
负载均衡技术(包括但不限于硬件负载均衡、软件负载均衡、负载算法、 linux 转发协议、所选用的技术的实现细节等)、主备技术(包括但不限于 ARP 欺骗、 linux heart-beat 等)、状态信息或缓存同步技术(包括但不限于 Cookie 技术、 UDP 协议、状态信息广播、所选用的缓存同步技术的实现细节等)、共享文件技术(包括但不限于 NFS 等)、存储技术(包括但不限于存储设备等)。
 
架构演变第六步:分库
享受了一段时间的系统访问量高速增加的幸福后,发现系统又开始变慢了,此次又是什么情况呢,通过查找,发现数据库写入、更新的这些操做的部分数据库链接的 资源竞争很是激烈,致使了系统变慢,这下怎么办呢,此时可选的方案有数据库集群和分库策略,集群方面像有些数据库支持的并非很好,所以分库会成为比较广泛的策略,分库也就意味着要对原有程序进行修改,一通修改实现分库后,不错,目标达到了,系统恢复甚至速度比之前还快了。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
这一步更多的是须要从业务上作合理的划分,以实现分库,具体技术细节上没有其余的要求;
但同时随着数据量的增大和分库的进行,在数据库的设计、调优以及维护上须要作的更好,所以对这些方面的技术仍是提出了很高的要求的。
 
架构演变第七步:分表、DAL和分布式缓存
随着系统的不断运行,数据量开始大幅度增加,这个时候发现分库后查询仍然会有些慢,因而按照分库的思想开始作分表的工做,固然,这不可避免的会须要对程序 进行一些修改,也许在这个时候就会发现应用本身要关心分库分表的规则等,仍是有些复杂的,因而萌生可否增长一个通用的框架来实现分库分表的数据访问,这个在 ebay 的架构中对应的就是 DAL ,这个演变的过程相对而言须要花费较长的时间,固然,也有可能这个通用的框架会等到分表作完后才开始作,同时,在这个阶段可 能会发现以前的缓存同步方案出现问题,由于数据量太大,致使如今不太可能将缓存存在本地,而后同步的方式,须要采用分布式缓存方案了,因而,又是一通考察和折磨,终因而将大量的数据缓存转移到分布式缓存上了。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
分表更多的一样是业务上的划分,技术上涉及到的会有动态 hash 算法、 consistent hash 算法等;
DAL 涉及到比较多的复杂技术,例如数据库链接的管理(超时、异常)、数据库操做的控制(超时、异常)、分库分表规则的封装等;
 
架构演变第八步:增长更多的webserver
在作完分库分表这些工做后,数据库上的压力已经降到比较低了,又开始过着天天看着访问量暴增的幸福生活了,忽然有一天,发现系统的访问又开始有变慢的趋势 了,这个时候首先查看数据库,压力一切正常,以后查看 webserver ,发现 apache 阻塞了不少的请求,而应用服务器对每一个请求也是比较快的,看来 是请求数过高致使须要排队等待,响应速度变慢,这还好办,通常来讲,这个时候也会有些钱了,因而添加一些 webserver 服务器,在这个添加 webserver 服务器的过程,有可能会出现几种挑战:
1
Apache 的软负载或 LVS 软负载等没法承担巨大的 web 访问量(请求链接数、网络流量等)的调度了,这个时候若是经费容许的话,会采起的方案是购 买硬件负载,例如 F5 Netsclar Athelon 之类的,如经费不容许的话,会采起的方案是将应用从逻辑上作必定的分类,而后分散到不一样的软负载集群中;
2
、原有的一些状态信息同步、文件共享等方案可能会出现瓶颈,须要进行改进,也许这个时候会根据状况编写符合网站业务需求的分布式文件系统等;
在作完这些工做后,开始进入一个看似完美的无限伸缩的时代,当网站流量增长时,应对的解决方案就是不断的添加 webserver
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
到了这一步,随着机器数的不断增加、数据量的不断增加和对系统可用性的要求愈来愈高,这个时候要求对所采用的技术都要有更为深刻的理解,并须要根据网站的需求来作更加定制性质的产品。
 
架构演变第九步:数据读写分离和廉价存储方案
忽然有一天,发现这个完美的时代也要结束了,数据库的噩梦又一次出如今眼前了,因为添加的 webserver 太多了,致使数据库链接的资源仍是不够用,而这个时候又已经分库分表了,开始分析数据库的压力情况,可能会发现数据库的读写比很高,这个时候一般会想到数据读写分离的方案,固然,这个方案要实现并不 容易,另外,可能会发现一些数据存储在数据库上有些浪费,或者说过于占用数据库资源,所以在这个阶段可能会造成的架构演变是实现数据读写分离,同时编写一些更为廉价的存储方案,例如 BigTable 这种。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
数据读写分离要求对数据库的复制、 standby 等策略有深刻的掌握和理解,同时会要求具有自行实现的技术;
廉价存储方案要求对 OS 的文件存储有深刻的掌握和理解,同时要求对采用的语言在文件这块的实现有深刻的掌握。
 
架构演变第十步:进入大型分布式应用时代和廉价服务器群梦想时代
通过上面这个漫长而痛苦的过程,终因而再度迎来了完美的时代,不断的增长 webserver 就能够支撑愈来愈高的访问量了,对于大型网站而言,人气的重要毋 庸置疑,随着人气的愈来愈高,各类各样的功能需求也开始爆发性的增加,这个时候忽然发现,原来部署在 webserver 上的那个 web 应用已经很是庞大 了,当多个团队都开始对其进行改动时,可真是至关的不方便,复用性也至关糟糕,基本是每一个团队都作了或多或少重复的事情,并且部署和维护也是至关的麻烦, 由于庞大的应用包在 N 台机器上复制、启动都须要耗费很多的时间,出问题的时候也不是很好查,另一个更糟糕的情况是颇有可能会出现某个应用上的 bug 就导 致了全站都不可用,还有其余的像调优很差操做(由于机器上部署的应用什么都要作,根本就没法进行针对性的调优)等因素,根据这样的分析,开始痛下决心,将 系统根据职责进行拆分,因而一个大型的分布式应用就诞生了,一般,这个步骤须要耗费至关长的时间,由于会碰到不少的挑战:
1
、拆成分布式后须要提供一个高性能、稳定的通讯框架,而且须要支持多种不一样的通讯和远程调用方式;
2
、将一个庞大的应用拆分须要耗费很长的时间,须要进行业务的整理和系统依赖关系的控制等;
3
、如何运维(依赖管理、运行情况管理、错误追踪、调优、监控和报警等)好这个庞大的分布式应用。
通过这一步,差很少系统的架构进入相对稳定的阶段,同时也能开始采用大量的廉价机器来支撑着巨大的访问量和数据量,结合这套架构以及这么屡次演变过程吸收的经验来采用其余各类各样的方法来支撑着愈来愈高的访问量。
看看这一步完成后系统的图示:
<!--[if !vml]-->
<!--[endif]-->
这一步涉及到了这些知识体系:
这一步涉及的知识体系很是的多,要求对通讯、远程调用、消息机制等有深刻的理解和掌握,要求的都是从理论、硬件级、操做系统级以及所采用的语言的实现都有清楚的理解。
运维这块涉及的知识体系也很是的多,多数状况下须要掌握分布式并行计算、报表、监控技术以及规则策略等等。
提及来确实不怎么费力,整个网站架构的经典演变过程都和上面比较的相似,固然,每步采起的方案,演变的步骤有可能有不一样,另外,因为网站的业务不一样,会有不一样的专业技术的需求,这篇 blog 更多的是从架构的角度来说解演变的过程,固然,其中还有不少的技术也未在此说起,像数据库集群、数据挖掘、搜索等,但在真实的演变过程当中还会借助像提高硬件配置、网络环境、改造操做系统、 CDN 镜像等来支撑更大的流量,所以在真实的发展过程当中还会有不少的不一样,另一个大型网站要作到的远远不只仅上面这些,还有像安全、运维、运营、服务、存储等,要作好一个大型的网站真的很不容易,写这篇文章更多的是但愿可以引出更多大型网站架构演变的介绍, :)