鄙人先后在CERNET做过拨号接入,在Yahoo&3721搞过搜索前端,在猫扑处理过mop.com的架构升级,在6.cn视频网站从事开发工作,还在多年的工作中接触和开发过不少大中型网站的模块,因此在大型网站应对高负载和并发的解决方案上有一些积累和经验,希望和大家一起探讨。
一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求,已经不是原来简单的html静态网站所能比拟的。
大型网站,比如门户网站。在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面,还没法根本解决大型网站面临的高负载和高并发问题。
上面提供的几个解决思路在一定程度上也意味着更大的投入,并且这样的解决思路具备瓶颈,没有很好的扩展性,下面我从低成本、高性能和高扩展性的角度来说说我的一些经验。
1、HTML静态化
其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。目前很多博客也都实现了静态化,我使用的这个Blog程序WordPress还没有静态化,所以如果面对高负载访问,www.toplee.com一定不能承受
同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储在数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。
在进行html静态化的时候可以使用一种折中的方法,就是前端使用动态实现,在一定的策略下进行定时静态化和定时判断调用,这个能实现很多灵活性的操作,我开发的台球网站故人居(www.8zone.cn)就是使用了这样的方法,我通过设定一些html静态化的时间间隔来对动态网站内容进行缓存,达到分担大部分的压力到静态页面上,可以应用于中小型网站的架构上。故人居网站的地址:http://www.8zone.cn,顺便提一下,有喜欢台球的朋友多多支持我这个免费网站:)
2、图片服务器分离
大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃。
在应用服务器和图片服务器上,可以进行不同的配置优化,比如Apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗和执行效率。
我的台球网站故人居8zone.cn也使用了图片服务器架构上的分离,目前是仅仅是架构上分离,物理上没有分离,由于没有钱买更多的服务器:),大家可以看到故人居上的图片连接都是类似img.9tmd.com或者img1.9tmd.com的URL。
另外,在处理静态页面或者图片、js等访问方面,可以考虑使用lighttpd代替Apache,它提供了更轻量级和更高效的处理能力。
3、数据库集群和库表散列
大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。
上面提到的数据库集群由于在架构、成本、扩展性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块以此将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行数据库和表的散列,最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。
4、缓存
缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。
架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的mod_proxy缓存模块,也可以使用外加的Squid进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。
网站程序开发方面的缓存,Linux上提供的Memcached是常用的缓存方案,不少web编程语言都提供memcache访问接口,php、perl、c和java都有,可以在web开发中使用,可以实时或者Cron的把数据、对象等内容进行缓存,策略非常灵活。一些大型社区使用了这样的架构。
另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块和eAccelerator加速和Cache模块,还要知名的Apc、XCache(国人开发的,支持!)php缓存模块,Java就更多了,.net不是很熟悉,相信也肯定有。
5、镜像
镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等工具。
6、负载均衡
负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。
负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,我个人接触过一些解决方法,其中有两个架构可以给大家做参考。另外有关初级的负载均衡DNS轮循和较专业的CDN架构就不多说了。
6.1 硬件四层交换
第四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。第四层交换功能就象是虚IP,指向物理服务器。它传输的业务服从的协议多种多样,有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上,需要复杂的载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。
在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。
6.2 软件四层交换
大家知道了硬件四层交换机的原理后,基于OSI模型来实现的软件四层交换也就应运而生,这样的解决方案实现的原理一致,不过性能稍差。但是满足一定量的压力还是游刃有余的,有人说软件实现方式其实更灵活,处理能力完全看你配置的熟悉能力。
软件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满足多种应用需求,这对于分布式的系统来说必不可少。
一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。
6.3 七层交换
大家都知道TCP/IP的七层协议,四层交换是基于传输层的,在这一层只能处理连接的管理,但是无法和业务关联起来,通常只能针对tcp、udp的连接来进行处理,而真正的业务逻辑需要后面的服务器群自己来处理,随着技术的发展,今天,我们在很多高级的应用中出现了七层交换。
七层交换是基于TCP/IP的第七层应用层来实现的,在这一层上,首先我们可以区分出具体的应用,比如HTTP、TELNET、FTP、DNS等等,还能根据应用中传送的内容来进行策略的管理,比如我们有这么两个网站的路径 a.com/music/… 和a.com/photo/… 原来基于四层交换只能把这两个url的请求都分发到后面一组服务器上,但是七层交换可以判断访问的是music/还是photo/路径,然后分别分发到不通的服务器群上,从而实现更灵活的系统架构设计。
当然,七层交换也分硬件和软件的实现方式,在这里我不细说了,硬件有著名的F5、Nortel等,软件有Haproxy等,当然,七层交换的软件目前还是在性能上要远远差别于硬件实现的,要知道,这些硬件都价格不菲
总结:
对于大型网站来说,前面提到的每个方法可能都会被同时使用到,我(Michael)这里介绍得比较浅显,具体实现过程中很多细节还需要大家慢慢熟悉和体会,有时一个很小的squid参数或者apache参数设置,对于系统性能的影响就会很大,希望大家一起讨论,达到抛砖引玉之效。
下面是讨论:
(1)各模块间或者进程间的通信普遍异步化队列化也相当重要,可以兼顾轻载重载时的响应性能和系统压力,数据库压力可以通过file cache分解到文件系统,文件系统io压力再通过mem cache分解,效果很不错。
(2)“大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的”,你以为是在内存中动态生成图片啊。无论是什么文件,在容器输出时只是读文件,输出给response而已,和是什么文件有什么关系。关键是静态文件和动态页面之间应该采用不同策略,如静态文件应该尽量缓存,因为无论你请求多少次输出内容都是相同的,如果用户页面中有二十个就没有必要请求二十次,而应该使用缓存。而动态页面每次请求输出都不相同(否则就应该是静态的),所以不应该缓存。所以即使在同一服务器上也可以对静态和动态资源做不同优化,专门的图片服务器那是为了资源管理的方便,和你说的性能没有关系。
动态的缓存案例估计楼上朋友没有遇到过,在处理inktomi的搜索结果的案例中,我们使用的全部是面对动态的缓存,对于同样的关键词和查询条件来说,这样的缓存是非常重要的,对于动态的内容缓存,编程时使用合理的header参数可以方便的管理缓存的策略,比如失效时间等。
(3)Michael 您好,这篇文章我看几次了,有一个问题,您的文章中提到了如下一段:
“对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。”
对于大型的站点来说,他的数据库和 Web Server 一般都是分布式的,在多个区域都有部署,当某个地区的用户访问时会对应到一个节点上,如果是对社区内的帖子实时静态化,有更新时再重新静态化,那么在节点之间如何立刻同步呢?数据库端如何实现呢?如果用户看不到的话会以为发帖失败?造成重复发了,那么如何将用户锁定在一个节点上呢,这些怎么解决?谢谢。
对于将一个用户锁定在某个节点上是通过四层交换来实现的,一般情况下是这样,如果应用比较小的可以通过程序代码来实现。大型的应用一般通过类似LVS和硬件四层交换来管理用户连接,可以制定策略来使用户的连接在生命期内保持在某个节点上。
静态化和同步的策略比较多,一般采用的方法是集中或者分布存储,但是静态化却是通过集中存储来实现的,然后使用前端的proxy群来实现缓存和分担压力。
交互如果非常多,可以考虑使用集群加Memory Cache的方式,把不断变化而且需要同步的数据放入Memory Cache里面进行读取,具体的方案还得需要结合具体的情况来分析。
(5)请问,如果一个网站处于技术发展期,那么这些优化手段应该先实施哪些后实施哪些呢?或者说从成本(技术、人力和财力成本)方面,哪些先实施能够取得最大效果呢?
先从服务器性能优化、代码性能优化方面入手,包括webserver、dbserver的优化配置、html静态化等容易入手的开始,这些环节争取先榨取到最大化的利用率,然后再考虑从架构上增加投入,比如集群、负载均衡等方面,这些都需要在有一定的发展积累之后再做考虑比较恰当。
(6)赞一个先,是一篇很不错的文章,不过要真正掌握里面的东西恐怕还是需要时间和实践!先问一下关于图片服务器的问题了!我的台球网站故人居9tmd.com也使用了图片服务器架构上的分离,目前是仅仅是架构上分离,物理上没有分离,由于没有钱买更多的服务器:),大家可以看到故人居上的图片连接都是类似img.9tmd.com或者img1.9tmd.com的URL。这个,楼主这个img.9tmd.com是虚拟主机吧,也就是说是一个apache提供的服务吧,这样的话对于性能的提高也很有意义吗?还是只是铺垫,为了方便以后的物理分离呢?
这位朋友说得很对,因为目前只有一台服务器,所以从物理上无法实现真正的分离,暂时使用虚拟主机来实现,是为了程序设计和网站架构上的灵活,如果有了一台新的服务器,我只需要把图片镜像过去或者同步过去,然后把img.9tmd.com的dns解析到新的服务器上就自然实现了分离,如果现在不从架构和程序上实现,今后这样的分离就会比较痛苦:)
谢谢lz的回复,现在主要实现问题是如何能在素材上传时直接传到图片服务器上呢,总不至于每次先传到web,然后再同步到图片服务器吧。
通过samba或者nfs实现是比较简单的方法。然后使用squid缓存来降低访问的负载,提高磁盘性能和延长磁盘使用寿命。
多谢楼主的耐心指导,我先研究下,用共享区来存储确实是个不错的想法!
(7)Michael,谢谢你的好文章。仔细看了,包括回复,受益匪浅。尤其这个部分很是有用,因为我也正在建一个电子商务类的网站,由于是前期阶段,费用的问题毕竟有所影响,所以暂且只用了一台服务器囊括过了整个网站。除去前面所说的图片服务器分离,还有什么办法能在网站建设初期尽可能的为后期的发展做好优化(性能优化,系统合理构架,前面说的websever、dbserver优化,后期譬如硬件等扩展尽可能不要过于烦琐等等)? 也就是所谓的未雨绸缪了,尽可能在先期考虑到后期如果发展壮大的需求,预先做好系统规划,并且在前期资金不足的情况下尽量做到网站以最优异的性能在运行。关于达到这两个要求,您可以给我一些稍稍详细一点的建议和技术参考吗?谢谢!看了你的文章,知道你主要关注*nix系统架构的,我的是.net和win2003的,不过我觉得这个影响也不大。主要关注点放在外围的网站优化上。谢谢!希望能得到您的一些好建议。
关于如何在网站的前期尽可能低成本的投入,做到性能最大化利用,同时做好后期系统架构的规划,这个问题可以说已经放大到超出技术范畴,不过和技术相关的部分还是有不少需要考虑的。
一个网站的规划关键的就是对阶段性目标的规划,比如预测几个月后达到什么用户级别、存储级别、并发请求数,然后再过几个月又将什么情况,这些预测必须根据具体业务和市场情况来进行预估和不断调整的,有了这些预测数据作为参考,就能进行技术架构的规划,否则技术上是无法合理进行架构设计的。
在网站发展规划基础上,考虑今后要提供什么样的应用?有些什么样的域名关系?各个应用之间的业务逻辑和关联是什么?面对什么地域分布的用户提供服务?等等。。。
上面这些问题有助于规划网站服务器和设备投入,同时从技术上可以及早预测到未来将会是一个什么架构,在满足这个架构下的每个节点将需要满足什么条件,就是初期架构的要求。
总的来说,不结合具体业务的技术规划是没有意义的,所以首先是业务规划,也就是产品设计,然后才是技术规划。
(8)很好的文章,楼主说的方法非常适用,目前我们公司的网站也是按照楼主所说的方法进行设计的,效果比较好,利于以后的扩展,另外我再补充一点,其实楼主也说了,网站的域名也需要提前考虑和规划,比如网站的图片内容比较多,可以按应用图片的类型可以根据不同的业务需求采用不同的域名img1~imgN等,便于日后的扩展和移至,希望楼主能够多发一些这样的好文章。
(9)图片服务器与主数据分离的问题。图片是存储在硬盘里好还是存储在数据库里好?
请您分硬盘和数据库两种情况解释下面的疑问。当存放图片的服务器容量不能满足要求时如何办?当存放图片的服务器负载不能满足要求时如何办?谢谢。
肯定是存储在硬盘里面,出现存储在数据库里面的说法实际上是出自一些虚拟主机或者租用空间的个人网站和企业网站,因为网站数据量小,也为了备份方便,从大型商业网站来说,没有图片存储在数据库里面的大型应用。数据库容量和效率都会是极大的瓶颈。
你提到的后面两个问题。容量和负载基本上是同时要考虑的问题,容量方面,大部分的解决方案都是使用海量存储,比如专业的盘阵,入门级的磁盘柜或者高级的光纤盘阵、局域网盘阵等,这些都是主要的解决方案。记得我原来说过,如果是考虑低成本,一定要自己使用便宜单台服务器来存储,那就需要从程序逻辑上去控制,比如你可以多台同样的服务器来存储,分别提供NFS的分区给前端应用使用,在前端应用的程序逻辑中自己去控制存储在哪一台服务器的NFS分区上,比如根据Userid或者图片id、或者别的逻辑去进行散列,这个和我们规划大型数据库存储散列分表或者分库存储的逻辑类似。
基本上图片负载高的解决办法有两种,前端squid缓存和镜像,通过对存储设备(服务器或者盘阵)使用镜像,可以分布到多台服务器上对外提供图片服务,然后再配合squid缓存实现负载的降低和提高用户访问速度。
希望能回答了您的问题。
(10)刚才一位朋友把你的 BLOG 发给我看,问我是否认识你,所以我就仔细看了一下你的 BLOG,发现这篇文章。
很不错的一篇文章,基本上一个大型网站需要做的事情都已经提及了。我自己也曾任职于三大门户之一,管理超过 100 台的 SQUID 服务器等,希望可以也分享一下我的经验和看法。
1、图片服务器分离
这个观点是我一直以来都非常支持的。特别是如果程序与图片都放在同一个 APAHCE 的服务器下,每一个图片的请求都有可能导致一个 HTTPD 进程的调用,而 HTTPD 如果包含有 PHP 模块的的时候,就会占用过多的内存,而这个是没有任何必要的。
使用独立的图片服务器不但可以避免以上这个情况,更可以对不同的使用性质的图片设置不同的过期时间,以便同一个用户在不同页面访问相同图片时不会再次从服务器(基于是缓存服务器)取数据,不但快速,而且还省了带宽。还有就是,对于缓存的时间上,亦可以做调节。
在我过往所管理的图片服务器中,不但将图片与应用及页面中分离出来,还会为不同性质的图片启用不同的域名。以缓解不同性质图片带来的压力。例如 photo.img.domain.com 这个域名是为了摄影服务的,平时使用 5 台 CACHE,但到了 5.1 长假期后,就有可能需要独立为他增加至 10 台。而增加的这 5 台可以从其他负载较低的图片服务器中调动过来临时使用。
2、数据库集群
一套 ORACLE RAC 的集群布置大概在 40W 左右,这个价格对于一般公司来说,是没有必要的。因为 WEB 的应用逻辑相对较简单,而 ORACLE 这些大型数据库的价值在于数据挖掘,而不在于简单的存储。所以选择 MySQL 或 PostgreSQL 会实际一些。
简单的 MySQL 复制就可以实现较好的效果。读的时候从 SLAVE 读,写的时候才到 MASTER 上更新。实际的情况下,MySQL 的复制性能非常好,基本上不会带来太高的更新延时。使用 balance (http://www.inlab.de/balance.html)这个软件,在本地(127.0.0.1)监听 3306 端口,再映射多个 SLAVE 数据库,可以实现读取的负载均衡。
3、图片保存于磁盘还是数据库?
对于这个问题,我亦有认真地考虑过。如果是在 ext3 的文件系统下,建 3W 个目录就到极限了,而使用 xfs 的话就没有这个限制。图片的存储,如果需要是大量的保存,必须要分隔成很多个小目录,否则就会有 ext3 只能建 3W 目录的限制,而且文件数及目录数太多会影响磁盘性能。还没有算上空间占用浪费等问题。
更更重要的是,对于一个大量小文件的数据备份,要占用极大的资源和非常长的时间。在这些问题前面,可能将图片保存在数据库是个另外的选择。
可以尝试将图片保存到数据库,前端用 PHP 程序返回实际的图片,再在前端放置一个 SQUID 的服务器,可以避免性能问题。那么图片的备份问题,亦可以利用 MySQL 的数据复制机制来实现。这个问题就可以得到较好的解决了。
4、页面的静态化我就不说了,我自己做的 wordpress 就完全实现了静态化,同时能很好地兼顾动态数据的生成。
5、缓存
我自己之前也提出过使用 memcached,但实际使用中不是非常特别的理想。当然,各个应用环境不一致会有不一致的使用结果,这个并不重要。只要自己觉得好用就用。
6、软件四层交换
LVS 的性能非常好,我有朋友的网站使用了 LVS 来做负责均衡的调度器,数据量非常大都可以轻松支撑。当然是使用了 DR 的方式。
其实我自己还想过可以用 LVS 来做 CDN 的调度。例如北京的 BGP 机房接受用户的请求,然后通过 LVS 的 TUN 方式,将请求调度到电信或网通机房的实际物理服务器上,直接向用户返回数据。
这种是 WAN 的调度,F5 这些硬件设备也应用这样的技术。不过使用 LVS 来实现费用就大大降低。
以上都只属个人观点,能力有限,希望对大家有帮助。 :)
(11)了解联合数据库服务器
为达到最大型网站所需的高性能级别,多层系统一般在多个服务器之间平衡每一层的处理负荷。SQL Server 2005 通过对 SQL Server 数据库中的数据进行水平分区,在一组服务器之间分摊数据库处理负荷。这些服务器独立管理,但协作处理应用程序的数据库请求;这样一组协作服务器称为“联合体”。
只有在应用程序将每个 SQL 语句发送到包含该语句所需的大部分数据的成员服务器时,联合数据库层才能达到非常高的性能级别。这称为使用语句所需的数据来配置 SQL 语句。使用所需的数据来配置 SQL 语句不是联合服务器所特有的要求。群集系统也有此要求。
虽然服务器联合体与单个数据库服务器对应用程序来说是一样的,但在实现数据库服务层的方式上存在内部差异。
(12)关于MySpace是否使用了3Par的SAN,并且起到多大的关键作用,我也无法考证,也许可以通过在MySpace工作的朋友可以了解到,但是从各种数据和一些案例来看,3Par的确可以改善成本过高和存储I/O性能问题,但是实际应用中,除非电信、银行或者真的类似MySpace这样规模的站点,的确很少遇到存储连SAN都无法满足的情况,另外,对于数据库方面,据我知道,凡电信、金融和互联网上电子商务关键数据应用,基本上Oracle才是最终的解决方案。 包括我曾经工作的Yahoo,他们全球超过70%以上应用使用MySQL,但是和钱相关的或者丢失数据会承担责任的应用,都是使用Oracle。在UDB方面,我相信Yahoo的用户数一定超过MySpace的几千万。
事实上,国内最值得研究的案例应该是腾讯,腾讯目前的数据量一定是惊人的,在和周小旻的一次短暂对话中知道腾讯的架构专家自己实现了大部分的技术,细节我无法得知。
如果要说3Par的光纤存储局域网技术细节,我无法给您太多解释,我对他们的产品没有接触也没有了解,不过从SAN的概念上是可以知道大概框架的,它也是一种基于光纤通道的存储局域网,可以支持远距离传输和较高的系统扩展性,传统的SAN使用专门的FC光通道SCSI磁盘阵列,从你提供的内容来看,3Par这个东西建立在低成本的SATA或FATA磁盘阵列基础上,这一方面能降低成本,同时估计3Par在技术上有创新和改进,从而提供了廉价的高性能存储应用。
这个东西细节只有他们自己知道,我就知道这是个商业的SAN (存储局域网,说白了也是盘阵,只是通过光纤通道独立于系统外的)。
(14)关于两位老大讨论的:图片保存于磁盘还是数据库。个人觉得数据库存文件的话,查询速度可能快点,但数据量很大的时候要加上索引,这样添加记录的速度就慢了。mysql对大数据量的处理能力还不是很强,上千万条记录时,性能也会下降。数据库另外一个瓶颈问题就是连接。用数据库,就要调用后台程序(JSP/JAVA, PHP等)连接数据库,而数据库的连接连接、传输数据都要耗费系统资源。数据库的连接数也是个瓶颈问题。曾经写过一个很烂的程序,每秒访问3到5次的数据库,结果一天下来要连接20多万次数据库,把对方的mysql数据库搞瘫痪了。
(15)看到大家都推荐图片分离,我也知道这样很好,但页面里的图片的绝对网址是开发的时候就写进去的,还是最终执行的时候替换的呢?如果是开发原始网页就写进去的,那本地调试的时候又是怎么显示的呢?如果是最终执行的时候替换的话,是用的什么方法呢?
都可以,写到配置文件里面就可以,或者用全局变量定义,方法很多也都能实现,哪怕写死了在开发的时候把本地调试也都配好图片server,在hosts文件里面指定一下ip到本地就可以了。假设用最终执行时候的替换,就配置你的apache或者别的server上的mod_rewrite模块来实现,具体的参照相关文档。
先谢谢博主的回复,一直在找一种方便的方法将图片分离。看来是最终替换法比较灵活,但我知道mod_rewrite是用来将用户提交的网址转换成服务器上的真实网址。
看了博主的回复好像它还有把网页执行的结果进行替换后再返回给浏览器的功能,是这样吗?
不是,只转换用户请求,对url进行rewrite,进行重定向到新的url上,规则很灵活,建议仔细看看lighttpd或者apache的mod_rewrite文档,当然IIS也有类似的模块。
我知道了,如果要让客户浏览的网页代码里的图片地址是绝对地址,只能在开发时就写死了(对于静态页面)或用变量替换(对于动态页面更灵活些),是这样吗?
我以为有更简单的方法呢,谢博主指点了。
(16)请教楼主:我正在搞一个医学教育视频资源在线预览的网站,只提供几分钟的视频预览,用swf格式,会员收看预览后线下可购买DVD光碟。系统架构打算使用三台服务器:网页服务器、数据库服务器、视频服务器。网页使用全部静态,数据库用SQL Server 2000,CMS是用ASP开发的。会员数按十万级设计,不使用库表散列技术,请楼主给个建议,看看我的方案可行不?
这个数量级的应用好好配置优化一下服务器和代码,三台服务器完全没有问题,关键不是看整体会员数有多少,而是看同时在线的并发数有多少,并发不多就完全没有问题了,并发多的话,三台的这种架构还是有些问题的。
(17)有人说图片没必要分离,那是错的。虽然我没有做web,但是图片一般都是一些小文件,读的时候,非常占用io的,比起http建立所耗的时候更恐怖。一个磁盘的io数必定是非常有限的,我开发过一个文件服务器,所以很明白。
(18)非常不错, 唯一的不足就是还是比较粗。 更细一些更好。还有很多问题希望能得到解答: 如果更好的控制权限。 我们知道静态页面的好处是快,而没有动态语言加载在里面,我们对文件控制就成了问题。 好比我们有一个图库网站, 我们如何控制不同用户的权限? 如果在用户可能猜出所有图片编码规则的前提下,很难控制。用户数目继续增加时如何管理数据库,它的读取锁定,如何保持高效。 前提是数据库已经分散到了多个。 他们之间如何建立更强的逻辑的结构?和脏数据的问题?
图片的权限有两种方法,一种方法是通过前端动态程序读取后端图片,然后通过程序往外输出图片数据,这样可以实现任何复杂逻辑,不过性能不是很好,对于商业图片之类的领域,是好的实现方式。 另一种就是通过判断referer之类的参数来进行图片服务器的设置,这个其实是可以通过web server的配置来得到的,如果使用Lighttpd做图片web server,可以结合 lua 语言来得到更复杂一些的逻辑处理,不过这种方法最大的优势是性能,在复杂逻辑方面还是无法满足需求的,理论上,编码规则是可以做到不可被猜到的,比如做成不可逆再加上针对每个id的一个干扰随机salt值,然后再加以运算,相信是无法根据id猜到的。
更多的情况下,图片服务器对于除了防止非法引用外的需求外,其他的复杂逻辑是大部分的互联网产品遇不到的。
对于相当大的用户数据,建议使用LDAP取代普通的数据库存储,如果使用收费的商业的类似ORACLE一类的解决方案,另当别说。
如果一定使用普通的数据库分表或者分库,需要建立一个核心的索引表(库),存储分库或者分表的逻辑对应数据信息,通过这个索引数据达到逻辑结构的维护。
知道的大概就是这些,更深的内容我也谈不上太熟悉。
(19)您好,看了您的文章,受益匪浅。我现在在开发一个php的社区程序,关于是否应该使用静态生成的问题,我曾经问过一些人,他们的答案大多认为这样做是不划算的。论坛程序是频繁更新的,在每次回复都需要再次生成静态,生成静态本身是有开销的。这之间的权衡一直困扰着我。我想问您,如果10个浏览着中创造一个回复,那么我生成静态是否划算呢?
说句实在话,除非你有非常好的逻辑便于实现静态话,比如更新用户在线状态、积分、广告投放、模板统一更新等。 否则我不建议论坛生成静态页面,如今因为smarty等模板引擎的缓存功能,配合各种各样的PHP缓存模块,加上硬件处理能力和硬件成本的降低,完全可以用动态语言来直接提供用户访问请求。
确实啊,使用静态对于日后的管理会造成麻烦。您的意思是推荐使用smarty等模板引擎的缓存功能来降低数据库的查询吗?事实上我总觉得用模板技术反而会加大程序的运算量,所以一直在考虑是否引入模板。也许smarty会好一些,但是对于内容频繁更新的网页还合适吗?
建议结合APC、Xcache之类的PHP缓存技术提高PHP处理性能,然后结合类似Discuz的文件缓存进一步提高性能(也可以使用一些开源的文件缓存代码),最后还可以参照Vbb的使用Memcached内存缓存的方法提高性能,在上述优化基础上,合理结合Smarty的缓存对一些静态块进行缓存(事实也是文件缓存),这样基本上就能处理大型应用了。
我曾经也有过类似的疑问,但是对于论坛来说,如果是想产品化并支持多样的皮肤、风格,那模板技术显然也是不可避免的需要采用。假设不需要这些,当然,PHP和HTML的混排一定是最高效的。另外,模板技术的采用,对于如今的cpu处理运算能力来说,基本上消耗可以忽略不计,一个系统的性能往往是卡在IO操作、数据库、Socket连接等环节。
(20)入门级问题:请问要实现图片服务器的架构,在具体程序中应该怎么做?包括文件服务器。Baidu、Google上都不好搜。期待楼主告知相关的一些文章或网站的链接:)
图片服务器,考虑好下面几个方面:
1. 使用最轻量级的web server,配置web server支持功能简单、单一。
2. 存储时合理的目录散列策略,保证散列均匀、初期设计足够长期使用。
3. 备份、同步等需要考虑,如果你需要考虑CDN负载均衡之类的。
4. 合理的CDN配合squid缓存分布,这是图片服务器必须考虑的,否则无法满足各地用户对图片的快速访问。
5. 防盗链,如果需要的话(通过配置web server来实现)
6. 成本,大量图片带来的存储、带宽之类的消耗问题
其他可能一时我也没有想到的。
(21)高兴能看到这么经典的文章,感觉受益非浅!我们现在也大量采用缓存、模块分离等方法来提高性能,同时降低系统的耦合性。但是还是没有考虑到图片对WEB性能的消耗,图片分离将作为我们接下来的重点,谢谢您的指导。我们程序是基于PHP模板技术的,准备将模板缓存起来以降低系统的IO消耗,不知道这样对系统性能是否有促进作用。另,对开发一个行业网站群,也就是一套程序适合多套模板和风格,从而生成多个不同的行业网站,对于这样架构的网站,楼主可否提供好的建议,再次拜谢!
对于PHP的模板IO性能提高,可以通过Xcache、APC这样的PHP扩展模块来实现,比别的方式效果都要好。一套程序对应多套模板和风格,这样的应用其实很多,比如blog、bbs之类的,还有一些网站的个人空间都是这样的策略,也没有什么特别需要注意的,这样的网站最大的问题就是可能要注意设计一个合理的底层架构,比如用户系统、cookie使用、子域名等方面都要考虑合理。更多的问题就需要落实到细节的时候才能针对性的来说。
(22)看了你的文章好是受益匪浅,最近碰到一个难题,求经不顺。特意来向你请教。还是图片服务器的问题,我有两台服务器,一台web,一台image,而且图片有60w张之多(接近20G),如果我要在web服务器上传图片,在image服务器浏览图片,该怎么做?先谢过!
我想可以在images服务器上使用squid作加速缓存,图片地址都使用images服务器的,图片上传到web后,访问时再缓存到images上。
(23)首先感谢博主有这么好的帖。我有点困惑:smarty是不是很好呢?最近在搞个政府类的门户网站,目前是将各类服务分开的:2台WEB、1台数据库、1台文件(含一些上传的image)+后台管理,采用的是php+html混排方式,目前速度并不是很理想,这也许和我配置的Linux服务器有关,呵呵,我配Linux还不是拿手。我想将程序采用smarty编写,不知道和纯静态相比有什么好处。
Smarty 有个缓存功能,减少动态运算,降低服务器消耗。除此外最大的好处就是MVC结构的改善,让代码逻辑和界面展示的开发以及逻辑上可以分离。关键的,如果代码效率高,服务器配置好,那种开发方式都不应该是瓶颈。 不过混排还是建议尽快改掉,太原始和不科学了。
(24)嘿嘿,不错,说的还是比较全。不过貌似缺乏一定的条理。图片服务器的分离存储被单独作为一大条了。个人感觉这只是根据文件类型分离存储的一部分,目的是为了减少浏览器和服务器的请求交互时间。这点上还有很多可以做的,比如合理安排 html 结构,让浏览器优先载入部分资源以尽快把页面显示给用户。这方面相关的东西 Oreilly 出了一本叫 High Performance Web Sites 上说的比较多。另外,Cache 那块似乎缺点什么,尤其是内存 Cache ,可以蔓延到数据库、静态页面甚至说的图片等其他静态文件,甚至 xcache 等一般是把动态程序编译(加速一次)后 Cache 到内存(再次加速)里。有些东西好象确实很难理清。
(25)很开心能找到这个博客。本人也是个SA(网站架构师?)。.既然作为SA,不可避免的就是面对越来越庞大的pv数值,以及需要对应的解决方案。在国内的网络环境来说,做大以后CDN必不可少,或者至少是双线机房。如果使用PHP的话,我建议大家使用FASTCGI方式,前端使用lighthttpd(会有内存泄漏问题),或者使用ngnix(从sina博客SA的BLOG处获知)。ngnix+fastcgi我做过简单的压力测试,确实比apache好不止1,2倍,推荐大家使用。
其实架构方面的东西最后都会比较趋于同化:Squid(或者更好的varnish)+ lighthttpd(或者更好的ngnix)+ PHP(fastcgi)+ memcached + Mysql(CLUSTER加上M/S模式或者加上实验性的MYSQL PROXY将读/写分开)。最最往后的,可能还是得看DBA和网站程序员的本事了。
很多东西讲到后面就会越说越细了,最后被支枝蔓蔓缠住吧,呵呵。其实架构这方面很多和程序有关,只是纯从物理结构以及服务器结构来说,没有程序配合还是不行的。比如数据库分片,或者数据库读写分离等等,甚至上传图片的路径和存放方式,都是程序端的东西。很多时候SA对这块东西挺无奈,而网站程序可能对一些系统性的东西又不是很了解。例如图片什么方法存储系统会响应的更好一些。所以一个好的SA必然需要会编程,而且要善于调试程序,理解系统瓶颈。谁说SA会比程序员轻松的,呵呵。
(26)我感觉查询是不是很消耗网站服务器的资源?
不同的网站有不同类型的瓶颈。例如交易型网站,则插入数据可能会是瓶颈。因为需要做事务来保证操作的不可分割性。对于其他绝大多数类网站,查询一般来说是最消耗数据库服务器资源的操作。至于网页服务器,则需要根据流量分析来判断了。因为即便有一块程序效率十分低下,但是调用次数非常少的话,也不会成为整体网站的瓶颈。而只有10来行的语句,如果每个页面都要调用,也会成为整个网站的瓶颈。
(27)楼主,向您请教个问题。我是用.net做的CS业务应用软件,也遇到了伸缩性和并发性的类似问题。我采用的做法是:
1、在应用服务层,用分布式事务处理器,协调事务。
2、通过配置组件的连接字符串或程序设置来来决定(当前是通过配置文件),该组件的数据到底是保存在哪个数据库里的。
3、多个数据库的数据在应用服务器(层)进行数据组装,对客户端提供透明数据。
4、当单表数据量过大的时候,就再用数据分区处理。
5、对于一些变化不频繁的数据,再以Cache缓存。
在我进行的测试中暂时还没有出现过什么问题。向楼主请教一下,这样处理方式会不会带来什么问题,可能什么地方会形成瓶颈?
昨晚在QQ上和您交流过了,半个老乡 。今后保持联络,相互学习。
(28)想问下多大并发才算是高负载,像6.cn这样的站最大并发多少?
可以从alexa上得到一个网站一天的pv数量,然后再一除就大概知道并发多少了。视频网站和传统的网站pv还有较大差别,比如新浪的一个pv就是看一个页面或者新闻,但是视频网站一个pv可能是几十分钟的一个片子。
(29)Blog主您好,看了您的文章有一些问题想要请教一下,首先是目前我这边的情况,前端负载均衡使用netscale,然后分布到多个Squids,最后面是IIS的WebSite,数据是html静态页面+xml存储在SAN上,存储时按ID号和类型区别分布在3套Cluster的20个映射驱动器上,目前遇到的问题如下:
1、前台UI在保存xml(非html,静态页面完全由后台程序生成,前台页面只是写数据库和xml然后发送MSMQ,最后由后台程序生成静态页面)时偶尔会报写缓存失败导致保存用户信息的xml无法生成,目前看来应该是大量并发的原因,不知道有什么建议?
2、由于目前我没有找到任何资料显示Squids可以一对多台后端服务器,所以现在使用的的是netscale–>Squids(多台)–>netscale(2个VIP分组)–>每个分组中包含的IIS服务器,这样一来所有的网络流量在负载设备基本上就翻了一翻,所以想请教一下有没有什么好的办法可以解决这个。
3、netscale的负载均衡策略可以选择最小连接数优先和最小响应时间优先以及平均分配,不知道使用哪一个会比较合理一些。
先谢谢了,我的msn是pollux_sky#hotmail.com(#换成@),希望能有更多的机会交流。
回答:
1、大量并发导致写文件失败是很常见的情况,基本上也很难避免,减小并发写操作是追求的目标,这要从产品层面来考虑。
2、从你的信息来看,你目前的架构是因为按照id分组的文件太多导致,不过我没有理解,既然是squid,为什么后端需要那么多的web服务器? 理论上 Load balance->squids->web servers 就ok了,这方面我估计需要了解你的细节。
3、netscale我没有用过,也是第一次听说,不过从你现在的情况来看,我建议使用别的7层交换设备或者软件来替换,这样可以根据你描述的文件的id来进行划分到不同的squid群,当然,如果继续使用netscale,由于大部分是静态页面,还是建议最小连接数的策略更高效。
感谢Michael深夜回复,还是要多多注意身体啊。关于我的第2个问题,目前是这样子的,因为netscale设备的缓存机制是使用内存,非常小,所以主要是用它作负载均衡这块的,而Squid才是用来做缓存代理服务的,缓存代理的对象就是后端的Web服务器的内容,但由于访问量相当大,现在的状况就是后端的Web服务器比Squid服务器数量多出很多,而Squid因为是改hosts来实现指向某一台后端服务器,没有办法一对多,所以Squid只好再指回负载均衡设备netscale,由它再一对多到后端的Web Server上面。
多台squid指向同一个web服务器,这是通常的做法,访问量大是增加squid,而不是增加web服务器,你尝试这样调整一下。
采购squid服务器的预算被枪毙了,主要是要实现squid服务器和web服务器1对1增加的服务器不在少数,而且网站现在动态的东西也不少,squid服务器并不能拦下来所有的访问请求,现有的web服务器平均iis并发连接都在30左右,个别二级域的站点服务器iis并发峰值都在100以上,所以web服务器已经不能再减少了,想请问一下Michael,挪一些web服器换成squid服务器以达到1:1的比例,不知道会不会比现在这种web服务器多于squid服务器要好呢?
如果你们的技术架构是你负责,你就应该要坚持你的观点,通常来说,web服务器一般都是部署在某个核心机房,各地的squid群起到负载均衡的作用,如果各地的点比较多,squid必然会比web服务器多很多,这是常规的做法,如果你要想让web服务器也分布太多点,这样架构会很复杂,没有太成熟的做法。假如你的站点主要集中在一个点上,那你说的那种比例没有什么问题。另外,你们的并发连接那个数量级,其实很小,因为你的内容主要还是静态的,虽然有动态的部分,实际上,动态的内容,有些情况下还是可以缓存的,需要更细致的去挖掘。
谢谢Michael,因为这个架构我也是接手在做,而关于这块的架构我目前只有建议的权限,决定权还是在高管层,squid也不是如您说的那样分布在各地,而是同web server一样,在同一机房,用于解决各地的访问的缓存是通过购买CDN服务实现的。关于动态的一些缓存,目前只是做到了数据库级,即对一些可能系统开销比较大,查询结果更改又不是太频繁的数据做了session database,不知道还有什么需要注意的地方。
从架构上来说,有多少资源用多少资源也是原则,不能为了追求架构而不考虑投入也是不可取的,你目前的情况来看,代码、服务器本身的配置优化看来应该有空间可改进,这个需要根据你具体的产品和代码来判断了。有关数据库的缓存,又回到我文章里面谈的一些观点了,大概就是这些方法,万变不离其宗。
(30)我看到zhang 说到了myspace中提到“MySpace开始将它的用户按每百万一组分割,然后将各组的全部数据分别存入独立的SQL Server实例”。这种方式虽然可行,但是MySpace是高度交互的,MySpace上的用户之间的关系呈网状的。如果这样的话,那么这100万组中的用户希望访问另一个100万组中的用户,并且发表评论,加为好友等等,是不是又存在不独立了?这种情况怎么解决呢?
数据库只是解决了数据的固态存储问题,并不是解决网站业务逻辑的,你说的问题不能混起来理解,对于大型网站前端的业务逻辑,数据之间都是通过中间的数据缓存和专门的引擎来实现的,比如自己开发的内存索引等,不要停留在功能和数据库的必然关系上。
(31)你好,Michael。你的这篇文章写得很好,我是一名小程序员,最近遇到设计一个高并发访问的网站需要我来架构,主要是用户浏览,交互比较少,所以准备采用freemarker生成全站静态html,然后在前端架nginx做负载均衡,后端三到四台web服务器,但是在图片服务器分离这一块我不知道该怎么弄,想搞两台图片服务器,但是不知道该如何配置,因为静态页面里面的图片服务器地址是配在配置文件里,写死的,我准备这样做,但是不知道合理不合理。四台web服务器:服务器1,服务器2 用图片服务器1,服务器3,服务器4用图片服务器2,我们网站访问量大概1天有600-700W pv,这是峰值,请您给我一点意见,非常感谢!
(32)全都是经验之谈,架构这种东西就是跟着业务走的,从简单到复杂,由小到大,哪里需要就修改哪里,技术就是为业务服务的,作为工程师就应该了解从基础的产品到架构再到程序。
本文转自:http://www.toplee.com/blog/71.html
我们说到有关图片影响性能的问题,一般来说都是出自于我们的大部分访问页面中图片往往比html代码占用的流量大,在同等网络带宽的情况下,图片传输需要的时间更长,由于传输需要花很大开销在建立连接上,这会延长用户client端与server端的http连接时长,这对于apache来说,并发性能肯定会下降,除非你的返回全部是静态的,那就可以把 httpd.conf 中的 KeepAlives 为 off ,这样可以减小连接处理时间,但是如果图片过多会导致建立的连接次数增多,同样消耗性能。
另外我们提到的理论更多的是针对大型集群的案例,在这样的环境下,图片的分离能有效的改进架构,进而影响到性能的提升,要知道我们为什么要谈架构?架构可能为了安全、为了资源分配、也为了更科学的开发和管理,但是终极目都是为了性能。
另外在RFC1945的HTTP协议文档中很容易找到有关Mime Type和Content length部分的说明,这样对于理解图片对性能影响是很容易的。