大并发系统设计
| 架构设计 |
| 优化服务器配置。 |
| 负载均衡技术。 |
| Web容器采用线程池技术。 |
| 数据库连接采用连接池技术。 |
| 页面预编译技术。 |
| 缓存设计技术。 |
| 高度优化SQL(Select和Update)、索引、分页等。 |
| 数据流压缩技术。pasting |
| 优化服务器配置 |
| 加大内存。 |
| 加大并发数。 |
| 升级操作系统版本。 |
| 正确的磁盘分区技巧。 |
| 负载均衡技术 |
| DNS负载均衡技术。 |
| 优点:优点是经济简单易行 ,节点可以在任意位置。 |
| 缺点:更新慢,节点宕机后无法响应。 |
| 交换机负载均衡技术。 |
| 优点:能及时响应节点宕机,速度快。 |
| 缺点:对交换机有要求,节点必须在交换机中。 |
| Web容器采用线程池技术。 |
| 进程模式的请求响应非常慢。但是比较稳定,一个进程dead后不影响其它进程。 |
| 采用线程池技术的后响应速度非常快,数据可以在线程之间共享。缺点是有可能单个线程会影响其它线程,并且有可能会发生死锁。 |
| 数据库连接采用连接池技术 |
| 提高了响应时间,尤其是的SQL比较多的时候更应采用连接池技术。 |
| 注意:连接的释放。连接的事务处理。 |
| 页面预编译技术 |
| 编译后的代码执行速度要比脚本语言高出几个数量级。 |
| Jsp主要是第一次运行时编译,这样可以提高第二次响应请求的时间。 |
| 可以在部署后批量编译所有动态需要编译的文件。 |
| 缓存设计技术 |
| 缓存能大大减少数据量的压力。 |
| 页面全部缓存 |
| 优点:整个页面响应速度快。 |
| 缺点:更新不及时,无法单独刷新某一块。 |
| 单个组件缓存 |
| 优点:执行速度快,可以很细的控制需要缓存的部分,节省内存空间。 |
| 优秀的缓存方案 |
| 页面级缓存技术有:squid、OSCache的taglib技术等 |
| 组件级有:MEMCache、OSCache、ECache等 |
| 高度优化SQL、索引、分页 |
| 值采用?形式来复用SQL,如:insert into table(f1,f2) values (?,?)。数据库会缓存这些sql,不会再解析了。 |
| 关联表查询注意要使用到索引。最好通过他表的主键关联。 |
| 采用存贮过程技术。 |
| 时间存贮采用时间类型,数据库对date类型字段都做了优化。 |
| 经常要查询的字段必须建索引,使用到的索引上最好能排除全表的80%的记录。 |
| 如果不能做到,则需要建立联合索引。同样索引必须能排除80%以上的记录。 |
| 索引定期优化,重建。 |
| 查询排序最好通过主键来排序。 |
| 一张表上索引不要超过5个。 |
| 尽量不要Like查询大字段。 |
| 执行时间超过100ms的SQL基本上都有问题,要么是设计的问题,要么是SQL没有优化,要么是索引没有使用正确。 |
| 数据流压缩技术 |
| 数据流压缩主要用在web服务器和浏览器之间的数据传送。 |
| 现在的浏览器基本上都支持gzip和deflate压缩技术。 |
| 注意压缩比。 |
| 不要压缩jpg、rar、zip等已经压缩过的文件。否则性能会更低。 |
| 解决网站大流量问题的策略 |
| 个人博客由于访问量过大而引起服务器性能问题,这是很多人的烦恼,有人使用取消RSS的方法来解决问题,显然是下错药,那么对于网站大流量带来的问题,正确的解决方法应该是什么呢?下面是我个人总结的一些经验,供大家参考。 |
| 首先,确认服务器硬件是否足够支持当前的流量。 |
| 普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大,那么必须首先配置一台更高性能的专用服务器才能解决问题,否则怎么优化都不可能彻底解决性能问题。 |
| 其次,优化数据库访问。 |
| 前台实现完全的静态化当然最好,可以完全不用访问数据库,不过对于频繁更新的网站,静态化往往不能满足某些功能。 |
| 缓存技术就是另一个解决方案,就是将动态数据存储到缓存文件中,动态网页直接调用这些文件,而不必再访问数据库,WordPress和Z-Blog都大量使用这种缓存技术。我自己也写过一个Z-Blog的计数器插件,也是基于这样的原理。 |
| 如果确实无法避免对数据库的访问,那么可以尝试优化数据库的查询SQL.避免使用Select * from这样的语句,每次查询只返回自己需要的结果,避免短时间内的大量SQL查询。 |
| 第三,禁止外部的盗链。 |
| 外部网站的图片或者文件盗链往往会带来大量的负载压力,因此应该严格限制外部对于自身的图片或者文件盗链,好在目前可以简单地通过refer来控制盗链,Apache自己就可以通过配置来禁止盗链,IIS也有一些第三方的ISAPI可以实现同样的功能。当然,伪造refer也可以通过代码来实现盗链,不过目前蓄意伪造refer盗链的还不多,可以先不去考虑,或者使用非技术手段来解决,比如在图片上增加水印。 |
| 第四,控制大文件的下载。 |
| 大文件的下载会占用很大的流量,并且对于非SCSI硬盘来说,大量文件下载会消耗CPU,使得网站响应能力下降。因此,尽量不要提供超过2M的大文件下载,如果需要提供,建议将大文件放在另外一台服务器上。 |
| 第五,使用不同主机分流主要流量 |
| 将文件放在不同的主机上,提供不同的镜像供用户下载。比如如果觉得RSS文件占用流量大,那么使用FeedBurner或者FeedSky等服务将RSS输出放在其他主机上,这样别人访问的流量压力就大多集中在FeedBurner的主机上,RSS就不占用太多资源了。 |
| 第六,使用流量分析统计软件。 |
| 在网站上安装一个流量分析统计软件,可以即时知道哪些地方耗费了大量流量,哪些页面需要再进行优化,因此,解决流量问题还需要进行精确的统计分析才可以。我推荐使用的流量分析统计软件是GoogleAnalytics(Google分析)。我使用过程中感觉其效果非常不错,稍后我将详细介绍一下Google Analytics的一些使用常识和技巧。 |
| 一、分 |
| 我们知道,对于一个大型网站来说,可伸缩性是非常重要的,怎么样在纵向和横向有良好的可伸缩性,就需要在做架构设计的时候考虑到一个分的原则,我想在多个方面说一下怎么分: |
| 首先是横向的分: |
| 1. 大的网站化解为多个小网站:当我们一个网站有多个功能的时候,可以考虑把这个网站拆分成几个小模块,每一个模块可以是一个网站,这样的话我们到时候就可以很灵活地去把这些网站部署到不同的服务器上。 |
| 2. 静态动态分离:静态文件和动态文件最好分离开成2个网站,我们知道静态网站和动态网站对服务器来说压力的侧重不同,前者可能重IO后者重CPU,那么我们在选择硬件的时候也可以有侧重,而且静态和动态内容的缓存策略也不一样。典型的应用,我们一般会有独立的文件或图片服务器。 |
| 3. 按照功能来分:比如有一个模块是负责上传的,上传操作很消耗时间,如果和其它应用混在一起的话很可能,一点点访问就会使服务器瘫痪,这种特殊的模块应该分开。安全的不安全的也要分开,还需要考虑到以后SSL的购买。 |
| 4. 我们不一定要全部用自己的服务器,搜索、报表可以依靠别人的服务,比如google的搜索和报表服务,自己做的不一定比得过别人,服务器带宽都省了。 |
| 其次是纵向的分: |
| 1. 文件也相当于数据库,IO的流量可能比数据库还大,这也算是纵向级别的访问,上传的文件图片一定要和WEB服务器分开。当然,数据库和网站都放在一个服务器上的很少了,这是最基本的。 |
| 2. 对于涉及到数据库访问的动态程序来说,我们可以使用一个中间层(所谓的应用层或逻辑层)来访问数据库(部署在独立的服务器上),最大的好处就是缓存和灵活性。缓存的内存占用比较大,我们要把它和网站进程分开,而且这样做我们可以很方便的去改变一些数据访问的策略,即使到时候数据库有分布的话在这里可以做一个调配工作,这样灵活性就很大了。还有好处是中间层可以做电线网通桥梁,可能网通访问双线再访问电信会比网通直接访问电信服务器快。 |
| 有人说我不分,我可以做负载均衡,对,是可以的,但是如果分的话,同样的10台机器肯定比不分10台机器可以承受更多的访问量,而且对硬件的需求可能不会很高,因为知道需要哪个硬件特别好。争取让每一个服务期都不空闲,又都不是太忙,合理进行组合调整和扩充,这样的系统伸缩性就高了,能根据访问量来调整的前提就是之前有考虑到分,分的好处是灵活性、伸缩性、隔离性以及安全性。 |
| 对服务器来说,我们有几点是要长期观察的,任何一点都可能是瓶颈: |
| 1. CPU:动态文件的解析需要比较多的CPU,CPU出现瓶颈就要看是不是哪个功能过长时间占用线程,如果是就分出去。或者就是每一个请求处理时间不长,但是访问量很高,那么就加服务器。CPU是好东西,不能让他干等,不做事情。 |
| 2. 内存:缓存从IIS进程独立出去,一般对WEB服务器来说内存不够的情况不是很多。内存比磁盘快,要合理利用。 |
| 3. 磁盘IO:用性能监视器找到哪些文件IO特别大,找到了就分到独立的一组文件服务器上去,或者直接做CDN。磁盘慢,大规模读取数据的应用靠缓存,大规模写入数据的应用可以靠队列来降低突发的并发。 |
| 4. 网络:我们知道,网络的通讯是比较慢的,比磁盘还慢,如果是做分布式缓存,分布式计算的话,要考虑到物理服务器之间网络通讯的时间,当然,在流量大了以后,这可以提高系统的接纳能力一个等级。静态内容可以借助CSD分担一部分,在做服务器假设的时候还要考虑中国特色的电信网通情况以及防火墙。 |
| 对SQL SERVER数据库服务器来说[UPDATE]: |
| 其实还是水平分割和纵向分割,一个二维表,水平分割就是横过来切一刀,纵向分割就是竖直切一刀: |
| 1、纵向分割就是,我们不同的应用可以分到不同的DB中,不同的实例中,或者说把某个拥有很多字段的表拆分成小表。 |
| 2、横向分割就是,某些应用可能不负载,比如用户注册,但是用户表会非常大,可以把大表分开。可以采用表分区,数据存储在不同文件上,然后再部署到独立物理服务器增加IO吞吐以改善读写性能,土一点的做法就是自己定期把老的数据存档。表分区的另外一个优势可以增加数据查询速度,因为我们的页索引可以有多层了,就像一个文件夹中的文件不要太多,多分几层文件夹一样。 |
| 3、还可以通过数据库镜像、复制订阅、事物日志,把读写分开到不同的镜像物理数据库上,一般来说够用,如果还不行可以用硬件来实现数据库的负载均衡。当然,对于BI,我们可能还会有数据仓库。 |
| 架构上考虑到了这些之后,流量大了,就可以在这个的基础上再去调整或者做WEB服务器或者应用服务器的负载均衡。很多时候我们都是在重复发现问题-》找到瓶颈-》解决这个过程。 |
|
|
| 典型的架构如下: |
|
|
| 动态WEB服务器配好点的CPU,静态WEB服务器和文件服务器磁盘好点,应用服务器内存大点,缓存服务器也是,数据库服务器当然内存和CPU都要好 |
| 二、并 |
| 为什么要分?是因为我们希望通过分来提高系统的承载能力,那并又是并什么呢?我想了一下有几个方面可以并: |
| 1. 合并用户请求,最基本的就是合并CSS/图片/脚本,还可以合并页面。不过合并就可能产生流量的浪费,需要有一个平衡点。 |
| 2. 合并接口的粒度,如果做分布式应用的话,我们可能不会直接访问数据库而是调用应用层提供的接口,由于是网络调用,代价比较大,因此在设计的时候尽量提供粒度比较粗的接口,一次调用返回比较多的数据,而不是细化到添加删除修改的层次。 |
| 3. 合并接口的部署,对于频繁的跨机器调用可以考虑有一些数据冗余,把跨网络的服务编程进程间通讯,甚至转到客户端来做。比如论坛发贴时候脏词的过滤,直接调用应用层提供的接口(跨机器)是可以的,但是可能代价比较大,可以把这个接口使用IPC方式部署在本机。 |
| 三、换 |
| 时间换空间,空间换时间是常见的做法,具体一点说: |
| 1. 缓存。缓存的重要性早计算机的硬件中就有重要的体现。对于网站,有很多种缓存,可以是客户端资源的缓存,可以是页面输出缓存,也可以是应用层的数据缓存,目的都是一样的,或是减少了服务器请求次数,或是减少了请求的处理过程,或是减少了数据库的访问次数。当然,生成静态文件也可以算是一种缓存。不访问磁盘固然不可能,但是我们要极大限度降低磁盘访问的机会。 |
| 2. 有的时候为了获取极快的响应,我们还会不惜代价采用重复计算。比如,我们的某个操作很可能会由于网络问题等原因响应比较慢,在设计的时候可以有一个统一的处理接口,由这个接口分发到不同的服务器去异步实现这个操作,哪个服务器先返回了结果我们就用这个结果,然后杀死其他服务器的冗余操作。 |
| 3. 网站一般追求比较快的响应,一般不太会在比较高的层次用时间来换取空间,但是在一些用户独有数据的处理算法上可能还是会考虑到空间的节省问题。 |
| 4. 有的时候我们会用一些聚合表来存放聚合数据,也就是进行一些预计算提高复杂计算(比如报表)的性能。当然,对于数据分析,构建多维数据库也是一种不错的选择。 |
| 有很多网友留言说说的比较粗,没有什么具体的东西。我觉得架构这个东西很难去说具体怎么做,因为具体实施的时候要看情况去应用的,由于没有完美的东西,所以做架构通常是去做一个平衡,很可能某一个侧重不同会影响到架构的实施。希望我的这些文章能给大家一个提示的作用,看了之后如果你觉得“这点我倒没有考虑到,以后要注意”那或许就是最大的帮助了,下面我想说一些其它方面的问题,每一条都很零散,算是一个补充吧: |
| 1. 到底是采用已有的东西还是自己去做需要详细考虑的,采用别人的东西可能比较稳定,但是自己的控制少了一点,采用自己做的东西可以很灵活,但是可能会问题比较多。不管怎么样,我们在采用一个第三方框架的时候务必要进行缜密的调查,看到他的不足,否则项目很可能在后期被这个框架制约,反之,决定自己去做一个框架的时候也要看到自己需要什么其他框架不能提供的东西。 |
| 2. 数据传输的时候可以做压缩,但要考虑到压缩解压缩需要CPU资源,在IO(磁盘,带宽,传输能力)和CPU之间有一个平衡的考虑。 |
| 3. 理想的可伸缩性架构是可以自由增加或替换服务器,无需去停机维护或做很大的调整。在使用一个统一的调度中心来调度这些服务器,分配请求的时候,我们要考虑一下调度服务器能承受多少流量。 |
| 4. 使用大量的廉价服务器还是少量的高配服务器?如何根据需求来组合服务器发挥最大作用。 |
| 5. 对于分布式构架,我们尽量让每一个节点保持简单的逻辑,尽量减少同一层次节点之间的依赖,另外。需要有统一的地方来管理所有的节点。 |
| 6. 功能分解、使用异步进行整合、故障转移、失效保护。 |
| 7. 软件的架构升级和计算机硬件的架构升级很像,可能有一段时期,我们是在慢慢提高整体能力,2年也才提高了几倍,之后发现只有通过某种彻底的架构改变才能提高数十倍的能力,升级之后,我们或许又会遇到其他问题。就像CPU,是简单提高主频还是彻底更换架构。 |
| 8. 数据方面,读写分离、数据库分隔、功能划分、缓存、镜像。 |
| 9. 硬件网络上的架构很重要,但软件开发中的一些细节不可忽略,好的架构不意味着不需要代码审阅。 |
pasting

浙公网安备 33010602011771号