文心春萌

厌倦了城市的喧嚣,向往美丽的草原!

« DateDiff函数(asp) 17种正则表达式 »

让你的网站快100倍!


让网站快100倍,看这个题目,就知道我们在讲优化。没错,正是网站优化。

优化是银杏咨询的一块重要业务,也是我目前工作的重点之一。而优化这个东西是非常体现短板效应的,对知识的要求非常全面,而且要融会贯通,真正理解才能做得好。相关全面的资料很少,市面流传的东西谬误又颇多。所以我考虑把我这几年工作的经验,以及这半年来银杏咨询碰到的问题总结一下,写这个系列的文章,希望能对同行们有所帮助,抛砖引玉是最好不过的。

这系列文章里面,这第一章自然是说说大体的情况,说说常见的错误思想,统一了思想才好进行。
第二章我会讲解web应用程序的常见架构,然后分析哪里是薄弱环节,哪里有可能改进,哪里是关键点,形成一个总体认识。
第三章开始将一些实用技巧和工具,思想。
后面的还没想好写什么。且写且考虑吧。

这是第一部分,先统一思想。

1 这个时代,优化还有没有意义?

计算机芯片性能很低的时候,优化是万分重要的。性能就意味着产品质量。所以很多C程序员宁愿放弃程序的可读性,也要变态的追求性能。早期作游戏的家伙,甚至把乘法都写成加法,以期多获得几个指令周期的性能。

在这个计算能力无限廉价的时代,优化所代表的意义其实已经不同了。互联网服务是性能的压榨机。相对传统的企业应用,互联网服务的逻辑简单,结构扁平,而性能要求尤其突出。同样,这个时代多机集群,负载平衡,不再是奢侈的东西,已经变成了寻常物件了。常常听到的一个观点,就是性能糟糕不怕,与其浪费时间优化,不如去买更好的机器好了。反正硬件比程序员便宜的多。

这种极端的观点是害人的。在目前,硬件仍然是有极限的,硬件升级带来的性能提升最多只能达到几倍的程度。而集群技术,且不说对程序的要求更高,我们就说在可实现的情况下,如果我的应用比你的性能高100倍,就意味着我用1台服务器完成的工作,你需要用100台。硬件成本暂且不论,那么管理成本呢?用什么样的技术手段去管理100台服务器?用多少网管来管理100台服务器?所有规模快速上升的模式都会遇到这个问题,就是管理成本达到了极限。而任何东西一旦达到极限,就往往不能简单用钱解决了。

所以,为了避免达到极限,我们还是应该尽量去提高单机的负载能力。对于中小网站,这更是意义非常。或许长期可以用1,2台服务器解决问题,可能永远都不需要投入相对昂贵的集群技术。这对成本降低大大有利。


2 优化是相对长期工作

做优化过程中,我们最常见的就是“按下葫芦起了瓢”,解决了A点的性能问题,B点立刻成了主要矛盾。解决了B点,C点又来了。优化了很久,服务器的负载一点都没有降低。没错,因为产品特性,这种短板先漏水的现象非常常见。甚至可能做了一个月的优化工作,看起来完全没进展。比如,B点消耗系统50%的性能,但是因为消耗20%的A点造成的速度慢,用户从来不能打开B点所在的页面。这样解决掉A之后,反而暴露了B,性能反而还不如过去。

这种情况都可能碰上,所以要认定,优化是相对长期的工作,要花时间,认真细致的进行。

3 让数字说话

科学是不靠猜测的。所有工作开始和完成,都要用数字来衡量。数字最有说服力。眼睛和经验通常不可靠,甚至会让你做无用功。

4 优化是综合问题

优化不仅仅涉及到程序,数据库,还有系统架构,甚至产品设计。很多时候需要综合考虑,设计方案。这不是一个简单的问题,而是相互牵扯和影响的一系列问题。所以一定要细致的分析,不要想当然。设计方案要合理,力求用最简单的方式解决问题。

5 二八原则

二八原则同样适用于这里。80%的性能消耗是因为20%的问题引起。找到当前的主要矛盾是重要的。去研究代码,获取几毫秒的性能,不如去看看数据库,干掉一条执行超过1000毫秒的语句。

6 容忍缺陷,不要追求完美

比如,一个页面,实时计算需要耗费20%的性能,那么定时计算就明显节省了很多。当然效果上会有差异。这时候应该容忍缺陷。选择合理的折中方案。而技术人员也应该学会足够的沟通技能,让产品人员明白两者的差距。

而,通常一个看起来完美的架构,在实际应用中是不堪一击的。

7 记录是好习惯

无论是内部的文档系统,自己的blog,或是邮件列表,一定要记录下所做的改动。这样的资料对于以后的查错,升级,分享都很重要。

8 语言不是最重要的因素

总有人问,.net好还是java好,php快还是jsp快。在我们这个系列中,这不是重点问题。其实在真正的实践中,任何语言的差距都是相当有限的--只要你会用。优化本身是不在乎语言的。比语言造成的影响大得多的因素有的是。

当然,限于不同语言的特点,各有应用领域。而.net/java之类的语言确实在web开发上不如php那么舒服。不过这真的不是最需要解决的问题。


9 这系列文章会讲真正有用的东西吗?和银杏的业务是否冲突。

答案是,当然会讲真正有用的东西。虽然银杏咨询的业务也是这些,不过我们仍然愿意让大家多了解这些知识。理解了之后,你自然可以自己完成,但采用我们的咨询服务显然是更简单和稳妥的方案。所以这与我们的业务没有直接冲突,我将努力把我知道的东西写出来。如果有不完善和错误的地方,那一定是我水平有限,到时还请多指点。:D

原则目前就想到这些。我们会在以后的讲解过程中逐渐体会这些原则的意义。

最终,我们一定可以实现让网站快上100倍这个目标。
 

我面试程序员的时候,最爱问的一个问题是:“请描述一下一个php(或.net/jsp...)页面被用户访问后,服务器都做了什么。”

这个问题看似简单,但是很多熟手都说不清。这也就说明了很多程序员并不真正理解web程序是如何工作的。不懂这个,就分不出层次,自然也就无从下手优化。这次我们先要把这个问题说明白了。

静态内容当然是这样。


有程序的就这样



有数据库的就这样



多个数据库作了复制或是集群或是负载均衡的就这样。



多个web服务器作了负载均衡就是这样


类似的东西还有很多。不过本质是一样的。都是用户请求到webserver,经过相应的处理模块(静态直接返回,cgi运行程序,动态脚本运行,虚拟机执行字节码生成html代码),将结果返回,这个过程中如果需要数据库,程序会连接数据库处理,取回结果。这个简单的过程就是web程序的本质。

无论多么复杂的结构,都是这些过程的组合。通常顺序也不会发生变化。知道了这个,我们回头看后面几个架构,就会发现他们做的事情都一样,就是把负载分开。当然这里分散负载的方式有很多,但原理无非就是2种,一种是分散开的各节点内容一样,所谓集群或是分布。这种做法好处是可以有通用产品。因为模式是统一的,就是复制出来多个一样的节点而已。另外一种是拆分服务,把不同的服务拆开到不同的机器上。这样做的好处是效率提升更大,每个部分都可以再进行单独优化,比如把负载最重的部分复制多个节点出来分散压力等等。后面我们讲到架构设计的时候再细致讨论这些问题。这里只做常识介绍。

负载问题的解决,常用的也是两种办法,一是开源,二是节流(其实所有问题解决都是这两种办法,企业管理也好,个人财务也好)。放到我们这个特定问题中,所谓开源,就是提高单个部分运行效率,让该部分能负担更多的工作。比如优化一下程序,优化一下数据库,都属于此类。所谓节流,则指降低对高资源消耗部分的使用次数。通常采用缓存的方式来处理。

我们沿着一个web程序的运行过程来看看具体的东西。这时候,我们先忘掉所有的负载平衡,集群之类的东西,集中精力来解决一个最简单的应用过程中的性能问题。

整个层次用图表示就是这样的:

蓝色是必备的层次,绿色是后期可加入的缓存,黄色是可以进行优化的部分,黄色的比例是一般情况下优化能带来的效果比例。看起来很简单?但实际做起来也没那么容易。

1 用户访问:我们当然可以通过降低用户重复请求同样的内容的方法来提高用户浏览速度和降低压力。
两种办法。一种是利用浏览器缓存,正确的设置http header中相关设置,让浏览器不重复请求没变化的内容。一般来说图片倒是可以这样做。页面也可以作一些,不过考虑到pv就是广告费的问题,还是让用户多多直接访问页面吧:D
另外一种办法是利用js,将部分数据存放在js脚本里面(js会被浏览器缓存),或是存放在cookie里面,用js取回。由此降低用户访问次数。

虽然有一些效果,但这些办法解决不了太实际的问题。所以不放在最优先考虑位置。

2 http server
用户的请求到达了web server,在这个层面,可以去硬盘读取静态文件返回给用户,也可能交给cgi程序继续处理。我们注意到,无论哪种处理方式,返回给用户的都是一个已经完成的html页面(或文件)。换句话说,就算是动态脚本,也是把处理结果生成html文件返回用户。如果我们能不重复这个生成的过程,那么对后端所有模块的压力都降低了。这个办法就是反向代理缓存。在http server之前使用。

3 cgi/vm
应用程序请求到达了cgi程序。那么最直接的考虑就是提高程序运行效率。不过,程序运行效率的提升多在几个毫秒的级别。除非程序非常糟糕,否则提升余地不大。而我们通常所感觉到的“程序响应慢”的原因,其实往往是在数据库上。

当然,这个层面会有一些特定的解决方案,比如zend对php的那些加速方案。(其本质仍然是不同层面的缓存)

4 database

终于到达了数据库这层。脚本和cgi程序访问数据库,获得数据才能生成html页面返回。这层的负担很重。

数据库优化是有效的。设计的好的数据库结构,搭配正确的sql语句,可以比最糟糕的设计提高数百甚至上千毫秒的时间。访问量大的时候,这个累计效应非常明显。

数据库设计往往决定了性能。鉴于目前关系型数据库的普及,很多程序员就把数据库当作了唯一的存储解决方案,任何东西都存放在数据库里。这当然是不对的,存储要结合应用特点,数据库不是万能的,很多操作在数据库中耗费资源巨大而性能非常低。例如全文like的搜索就非常消耗资源,远不如采用倒排索引的查询方式。

除此之外,数据库层面也可以进行缓存,例如memcached,或是在程序中缓存部分数据等。

5 高级优化

这些做起来就有些难度了。当所有性能都压榨完,我们只能回到web server和cgi程序本身。所以大型网站往往使用自己开发的web server(自行定制apache等),采用裁剪过的php库。

在我们还没有解决完其他部分之前,暂且不考虑这个。


顺着这个流程看,最有效,最值得做得事情显然是2和4,这些都是对系统架构改变不大,但是效果明显的方案。因此,下一章我们就从反向代理的应用说起。


ps: 另请转载此文的,请连图转走,或是留下本文链接。以免影响别人阅读。谢谢。我不在乎这点流量,所以转也就转了,但是不能因为少了图让别人看不懂。


 

原文出处:http://blog.devep.net/virushuo/2007/07/16/optimize-2.html.html

  
  • 相关文章:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

本站采用创作共用版权协议, 要求署名、非商业用途和保持一致.

Auto Publisher Copyright Blog.cnxcn.net . All Rights Reserved.