Eric Liu(The Road to Architect)

有些人注定要生活在彼岸 可以亲近可以爱怜 甚至可以穷尽一生去思念 只是无法触及 有些距离 注定不能跨越 只能俩俩相望 就像有些爱只能养在心里 长在眼中 不要捧在手里 放在身边 注定只能邂逅 无法遭遇

刘如鸿ID:liuruhong
330612次访问,排名157好友0人,关注者3
liuruhong的文章
原创 48 篇
翻译 0 篇
转载 0 篇
评论 480 篇
刘如鸿(Eric Liu)的公告
    从最近开始,我会逐步写一些关键软件架构方面的话题,也是对于我过去几年以来技术的一个总结,不管对的还是错的,谨代表我个人在写作时期的观点.
最近评论
kuangheng10:学习了谢谢
a43350860:#hbqudeding 发表于2008-05-14 20:37:48 IP: 59.174.79.*
明摆着啊,.NET肯定比JAVA好啊

------------------------------------------------------
一般一个成熟的开发人员,不会丢出如此幼稚的话!
谁好,谁不好,不是我们说的算!
……
weiertzw:什么叫.net明摆着比java好呢?
zhujian888:最近用.net 做css + div做标准网站比较吃力。开发不见得快啊,还没有php快。.net大多控件生成table。还有些服务器控件在IE上生成是DIV在firefox上就是span,你说css怎么写。所以 这时候就不能用服务器控件。变成了用.net写asp感觉了。
yxred:请注意应用……
.net做的网站,明显比其它的要快些……
文章分类
收藏
    相册
    .NET four year
    Article Photos
    个人推荐
    嘿友,连接你我他
    坠落的淡蓝(个人BLOG)(RSS)
    榕树下
    技术站点
    Asp.Net
    WindowsForms
    博客堂
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 勇敢者的游戏收藏

    新一篇: SD 2.0 China:一场开发者狂欢的盛宴 | 旧一篇: 这个夏天,有些东西需要记忆

     
    勇敢者的游戏
    ——利用ASP.NET建立你的商业应用
    作者:刘如鸿
    原文发表于《程序员》杂志2006年第10期
     
    楔子
    严格地说,这不是一篇Web开发的最佳实践,至少不是纯粹的ASP.NET开发实践,就如标题所言,采用ASP.NET去构建商业应用是需要一些勇气的,你需要有一些勇气去说服别人,需要有一些勇气去判断你自己的技术决策。
    在这里我们不是去讨论所谓微软的霸权主义,所谓Windows vs Linux,所谓.NET vs Java,对于一些事情你的信心往往不是你自己的实践得来的,而是借他人之口让你形成潜意识的判断。在这点上,采用Windows本身就是需要一些勇气,毕竟太多的人会告诉你Linux比Windows稳定,大的商业网站没有采用Windows平台的。在过去的一段时间里,我们令人诧异地全线采用了Windows平台,当然也陪我们这个团队走过了一段战战兢兢的历程。而下面的文字是在抛开IT运营成本考虑的基础上去描述如何让你在ASP.NET这个平台上搭建出自己的商业应用。商业是商业,技术是技术,对于一个技术人员而言,我们更加重要的是解决问题,而不是谈论要不要。
    说英雄,谁是英雄
           如果在五年以前许多对LAMP(Linux+Apache+MySql+Php)嗤之以鼻的话,那么对于ASP.NET则是FUD(恐慌、不确定、怀疑),几乎所有的人都认定只有J2EE是所谓企业级应用(我不清楚这个词是否中国国情)的黄金之道。LAMP在小型应用的风风火火,但是在大型网站上没有太多作为,而ASP.NET给所有开发人员描绘的轮廓就显得更加模糊,除了创造性地概念和一路传承的“傻瓜式开发”,大多数人都是在捣鼓着“.NET”这个名词。
     
           时过境迁,随着第二波互联网热潮的回归,Web 2.0得到越来越多人的认同,技术人员也越来越“聪明”,“只选对的,不选贵的”,在一边炒作互联网概念(Web 2.0不是有许多炒作吗?)的同时,这一时代的技术人员更加注重技术本身给商业带来的回报,在以开发效率导向和系统可靠性方面每个人都形成了自己的尺,是的,越来越懂得根据自己在其间找到平衡。
          
           我们不是去比较Java,Php,ASP.NET不同的技术优势和劣势,每个技术人员都或多或少的有着完美主义倾向,这个也就是网上关于这三个平台的孰优孰劣的争论永不息止的原因。“存在就是合理”,既然每个平台在这个阶段能够大放异彩,必然是有着独特的优势的,包括日前如日中天的Ruby on Rails。
     
           凭心而论,从2000年以来微软在企业级领域所作的努力还是卓有成效的,虽然它的.NET战略并没有当初预计的如此顺利,但是不管如何还是缔造了一个新的企业级平台,ASP.NET在很多东西开创了Web应用的新模式,包括Web Form,包括简易的Web Service开发。选择ASP.NET的原因也很简单,对于一家新创立的网站,我们需要用最短的时间将产品推向市场,同时在日后业务增长的时候,有比较开放的架构能够保证其稳定性。方便的开发工具,容易上手和大量控件支持,这是选择ASP.NET的第一原因,当然了,其开放的设计也让你对于未来更加有把握。
          
    实践考虑
           事实上并没有一种技术是万能的,ASP.NET也如此,那么我们可以做的就是尽可能利用其优势,同时避开平台本身的一些劣势或者缺点。任何业务都会经历一个从小到大的过程,从一个注册用户发展到十万用户再到上百万乃至千万,每个阶段所考虑的策略重点也是不一样的,就以网站来说,50万,100万,500万是不同的槛(可能根据不同业务会有不同的指标),在50万用户之前更多的考虑是如何快速开发,50万到100万之前考虑的是如何逐步优化系统性能,以保证能够持续地提供服务,而超过100万之后更多的是考虑如何使用一个更加开放、可靠的架构去持续提供IT支撑。
     
           如上所述,我们可以简单地将Web开发分解成 “快速开发”、“应用调优”及其“大型网站设计”这三个阶段,每个阶段的着眼点不同,也就决定了不同的技术实现策略。下面是我个人在开发过程中的一些实践技巧,简单地处理成了建议和不建议,或者直接列举。
    快速开发
           建议
    1) 尽可能定义用户界面标准(UI Standard)。包括通常使用的CSS样式和常用的页面布局,也包括标准的页头和页脚,在样式定义时尽可能按照分类定义不同的CSS文件,以避免一个简单页面加载太多的样式单。
    2) 尽可能使用Web User Control,而不是在一个页面内完全实现。这样做的好处是能够将你的业务尽可能片断化,加之ASP.NET提供的缓存机制,只有在User Control下你才有可能提供更加灵活的机制,同时使用User Control有助于你对于代码片断的重用。
    3) 对于数据库的访问尽可能使用DAO或者代码生成,在简单业务的情况下,它能够帮你降低很多重复的数据库访问工作。你可以使用CodeSmith生成自己的Business Object,也可以利用一些O/R Mapping(如Nhibernate)框架来实现数据库访问,如果您对于采纳的O/R Mapping框架把握不是很足的情况下,建议采用代码生成,那样在日后出现一些问题的时候您能够对代码有更好的控制力。
    4) 对于常用的界面元素做一个抽象,那样能够帮助你省事许多。比如常用的分页、日历、导航及其列表等界面元素,适当的抽象能够让你在日后的开发中少做许多工作。
    5) 不要在你的Web工程中包含太多的业务代码,那样会让你在日后的运行中带来诸多问题,如重新部署之后的应用程序重起,如无法快速更新,业务代码尽可能包装到业务层上,一些比较通用的界面交互逻辑也包装到后端,如果不是关键的业务页面,同事存在频繁更改的可能,建议采用代码前置,那样有利于你的频繁部署。
     
    不建议
    1) 除非必要,尽可能不要使用Postback,更加不要在同一个页面中处理太多的业务和界面呈现,特别是通过控件的Visable属性来控制界面显示已否,一个方面这么做会让你的业务变得极其复杂,然后耗费太多的时间在处理复杂的界面呈现。在你的页面包含了太多业务呈现的时候(页面很大),使用Postback也不是一个最佳做法,那样会无谓地浪费你很多资源。
    2) 不要将太多的脚本写在当前页面上,而是应该尽可能抽象成脚本库。
    3) 如果不是必要,在网站应用中不要使用Datagrid,而是用Reapter替代。Datagrid是一个最强大当然也是最复杂的控件,如果你的业务应用不是绝对明确(只是需要数据显示和编辑)的时候,使用Datagrid会让你走入一个误区,那就是你更多的精力耗费在考虑如何使用Datagrid而不是享受它给你带来的好处了。
    4) 不要在Global.asax中放入你太多的业务处理。一个方面是每次改动都需要重新编译,另外一个方面是太多的业务集成会导致程序运行效率下降和不稳定因素的出现,建议采用HttpModule替代,那样一个方面能够实现业务的独立,另一方面有利于你快速诊断和降低不必要的负担(通过配置文件即可)。
    服务器设计
    这个问题比较大,我甚至在疑惑应该去解释服务器硬件还是软件抑或编程中的一些技巧,任何一个话题都是庞大的,甚至一本书都无法说明清楚,我们在这里关注的是在业务不断增长的过程中服务器资源的变化会对于开发编程产生什么样的影响,那些问题我们能够在一开始避免或者尽量避免。
    我们可以考虑服务器从一台、两台、三台再到四台或者更多,这样的一个发展过程也符合企业的发展过程,在这个不断的发展过程中,我个人有那么一些体会。
    建议:
    1)    在业务相对独立的情况下尽可能采用不同的域名,那样在业务压力比较大的情况下能够最快的进行分拆。同时因为客户端请求的一些限制,默认情况下浏览器对于同一个域名是开启两个连接进行请求的,在需要加载大量数据的情况下,比如将图片和固定文件(css,js)和动态页面分开有利于加快页面的加载速度。
    2)    在程序开发过程中如果有可能,尽量不使用Session,虽然ASP.NET也提供了多台机器的Session同步机制(数据库和ASP.NET状态服务),因为这样的依赖并不是最可靠的方式,在不使用Session的情况下你能够比较有效地进行站点的分布。
    3)    将一些需要大量资源(CPU或内存)的业务从ASP.NET中剥离出来,而不是让其宿主在IIS之上,从某个角度来说这个会增加跨应用程序边界的压力,但是在.NET下已经有很好的分布式架构如(Remoting,Enterprise Service, Web Services)等来解决。如果都是.NET下的应用,建议建议一个Windows Services宿主您的业务应用,然后提供.NET Remoting的访问通道,如果都在一个网络不需要穿越防火墙的时候,尽可能采用TCP通道,所谓性能的部分损失带来的是架构的可扩展性和灵活性,一切是值得的。
    4)    Windows下对于大内存是有一些限制的,在超过2G内存的机器尽可能使用 /3GB /PAE选项而确保大内存的使用。
     
    不建议:
    1) 不要将应用程序配置为同一个应用程序池,那样并无法享用IIS 6.0带来的好处,同时会增加你服务器诊断的难度,因为不同的应用程序池配置针对的场景是不一样的,太多的应用绑定到同一个应用程序池会增加服务器的不稳定。
    2) 不要为服务器启用太多的服务,相对于Linux的定制,Windows默认情况下启动了太多的服务,请检查你的业务,诸如不需要打印,请禁用其服务,不需要文件共享,就停止文件服务。
    3) 对于大量的用户上传资料(如图片、视频),请不要贸然地放在站点目录下,如$WebSite/Upload,如果有可能,默认用网上邻居的方式,这样子做的确会给你带来一些麻烦,但是带来的好处是值得的,在业务增长出现瓶颈(如磁盘空间不足或者I/O压力太大)的情况下,有助于你快速启用新的机器来解决。
    数据缓存
    考虑到这个问题的时候,我相信业务是已经到达了一定规模,所以你需要在不同的层次上去缓存您的数据,ASP.NET提供了一个非常好的缓存模型,也提供了非常灵活的API来实现缓存,那么一切是不是万事无忧了呢?
    1)              在一些相对静态或者可以通过参数化静态的页面片断(更多的是Web User Control)来实现缓存
    2)              对于静态内容页(不仅仅是html),诸如你用CMS发布的静态页面之类,尽可能的启用IIS 6.0和http.sys提供的kernal mode Cache,那样能够提高接近10倍的效率。
    3)              在编程中即便没有任何意图,都建议采用工厂方法如ObjectEntity.GetEntity(entitiID)这样的方式获取你的实体对象,而不是在业务层采用直接的new语句。
    4)              请记住“数据层缓存是王道”,任何页面级别的缓存能够给你的只是粗粒度的控制,从某些角度来说能够降低数据库访问的压力,但对于相对复杂的页面(特别是Web 2.0的兴起,更加强调用户个性化),就有点力不从心了,第三条的建议其实也是为此作准备的,它让你在需要对代码进行改动的时候,你用很小的改动就可以实现一些数据层的缓存,我们看下面的简单例子
    Public static User GetUser(int userId){
           Return new User(userId)
    }
     
    可以简单的修改成如下
    Public static User GetUser(int userId){
           string key="__User_"+ userID;
    User user=null;
    if(HttpContext.Current!=null){
           if (HttpContext.Current.Cache[key]==null){
                  user=new User(userID);
                  HttpContext.Current.Cache[key]=user;
           }
    }
    else{
           user=new User(userID);
    }
    return user;
    }
     
    请看看发生了什么?通过几行代码我们的程序就支持缓存,也就意味着如果User对象被频繁访问,同一个对象在一段时间内就只被创建一次的,这就是缓存就简单的应用,在应对大多场景下,其实这样的代码已经足够工作了。
    5)              请不要将缓存看成尚方宝剑,并不是任何对象都往内扔就可以了,ASP.NET提供了默认的缓存机制,对于内存大小和入口条目是有所限制的,如果对于此比较感兴趣,你可以查阅Machine.config相关的配置信息
    6)              如果你觉得上述的控制已经达不到你的要求,那么可以自己管理缓存,不过这是后一步的事情了。
     
    高可用性
           提到这个词,往往会觉得玄而空洞,对于大多数技术人员来说,也很难界定如何下手,简而言之,我们需要保证的就是在更大的访问量下如何24* 7持续提供服务,有很多硬件和软件来解决类似的问题,大多情况下是通过负载均衡和错误冗余这两种模式来解决的。
           负载均衡可以简单的理解成同时提供多台机器访问,在某一服务器出现问题的情况下,其他服务器能够持续提供服务,从而保持服务是持续的,硬件方面你可以通过F5或RADWARE来解决,也可以通过软件如Windows自带的NLB来实现网络的负载均衡。
           错误冗余更加好说一点,在某一台机器出现问题的情况下,另外一台机器能够自动接管其服务并持续运行,而这一切对于外界来说是透明的,这个场景在数据库应用里面会更多一点,Windows的MSCS和SQL Server配合,你就可以做出Active/Standby模式的错误冗余。
           我们在这里撇开硬件架构或服务器的服务部署不谈,为了保证高可用性,我们需要做哪些呢?
    1) 尽可能状态无关,我们上述谈到的Session也好,缓存也好,为了更加有效地支持高可用性,尽可能将数据持久化,比如ASP.NET的缓存服务,是无法提供跨进程的缓存同步,为了确保不会引发缓存同步的问题,要么你选择提供自己的缓存服务系统,要么不考虑在Web Server做缓存,而是通过数据库持久化的方式来实现状态同步。
    2) 不要在IIS上执行及其耗费资源的操作,如果确实必要,请尽量采用异步操作,在需要返回界面的场景中,可以考虑采用MSMQ这样的技术架构。
     
    数据库优化
    本来不应该在这里作为Web开发技巧来说数据库优化,加上有太多的文章讲述过,一切已经不是新鲜话题了,所以这里提到的一些技巧更多的是从数据库规划的角度来考虑的,而非开发技巧。一个合理的数据架构(请注意不是数据库设计)也许就决定了你有多少作为。
    1)              在业务独立的情况下尽可能采用多个数据库,而不是单一数据库,那样可以明显地降低数据库锁的几率。
    2)              针对不同的数据库情景,不要理所当然地将所有数据表放在同一个数据文件上,特别是一些关键数据表,如文章帖子,好的做法是使用单独的数据文件,将所有也放在单独的数据文件上,那样能够提高数据库的I/O性能,也减少死锁的可能。
    3)              如果经常涉及到跨数据库事务,请检查您是否有拆库的必要
    4)              分布式事务尽可能是在数据库级别上去做,那样能够降低跨越不同上下文边界而导致的性能负担。
    5)              学会使用SQL Profile和Read80Trace这样的性能调优工具
    6)              在需要的时候通过日志传送(log shipping)建立只读数据库,但不是越多越好,可以根据你的业务读写作一个权衡,一旦你用于日志传送的资源远远超过读的压力,就适得其反了,这个时候可以通过数据业务分区来解决。
    7)              如果你的数据库数据不是一次性读取,那么就没有理由使用SqlDataReader。
    今天你AJAX了吗?
           写到这里,终于回到流行的浪尖口上,我也忍不住时尚了一把,是的,因为Google的采纳这两年来所有Web技术人员无法抗拒的名词——AJAX。
           这是一个双刃,在给你带来所谓用户体验的同时,也不可避免的带来一切负面的影响,我们不是去讨论用或者不用的问题,也不是去讨论哪个AJAX框架好不好的问题,有兴趣的话你可以去了解prototype,了解RICO,了解Ajax.Net Pro,你也可以了解MagicAjax,当然了,也不应该忽略了atlas——微软出的产品。
           我这里,我没有答案,只有感觉。
    1) 如果你可以不用AJAX,那么就不用AJAX,虽然有很多框架宣称可以不用了解javascript也能够开发出非常优秀的ajax应用,但是Javascript是一切的基础,如果你的团队中没有比较资深的javascript开发人员,采纳ajax很多时候是噩梦的开始,你需要不断的和scripting error这样的错误信息战斗。
    2) 不用AJAX传递大内容的数据,脚本执行还是存在太多的“风险”,因为你永远无法控制它到底会不会报错。
    3) 如果你对你的Alexa排名很敏感的话,那么爱它也不要用它,原因很简单,从alexa统计上它无法给你带来流量
     
    小结
           写这样的开发实践技巧是很累的一件事情,因为你不会知道具体哪些实践对于开发人员来说是真正有益处的,而且更加难在技术、信仰和商业之间找到真正的平衡点,Windows也好,Linux也好,说英雄,谁是英雄?都是,都不是,就如前文提到的,每个人心目中都有一把尺,那么在我的心目中,就是——勇敢、保守、诚实、敏捷,对不起,我用了太多的矛盾词。
     

    发表于 @ 2006年10月10日 10:14:00|评论(loading...)|编辑

    新一篇: SD 2.0 China:一场开发者狂欢的盛宴 | 旧一篇: 这个夏天,有些东西需要记忆

    评论

    #fungchou 发表于2006-10-10 12:20:00  IP: 221.237.69.*
    谢谢,写得真好
    #xxrl 发表于2006-10-11 21:13:00  IP: 218.68.37.*
    很好!
    对于
    2) 对于静态内容页(不仅仅是html),诸如你用CMS发布的静态页面之类,尽可能的启用IIS 6.0和http.sys提供的kernal mode Cache,那样能够提高接近10倍的效率。
    不太理解,可否赐教?csdn.xxrl@163.com
    #Shawn 发表于2006-10-12 01:03:00  IP: 221.237.29.*
    下午才在<程序员>杂志上看到,写的很实际.
    #shanyou 发表于2006-10-14 11:20:00  IP: 61.141.229.*
    SqlDataReader,这个可以用Sql Server 2005的多数据结果集(Multiple Active Result Sets,简称MARS)-它允许在单个连接上执行多重的数据库查询或存储过程.
    文章写的非常好,虽然也存在一些错误的地方。
    #Hiker 发表于2006-11-28 00:22:00  IP: 58.41.4.*
    请教ERIC

    如果说想做一个
    小型一点的
    速度还不错的
    低硬件投入成本的交互式网站

    是不是用PHP更合适一些呢 ?
    #Eric 发表于2006-11-28 11:56:00  IP: 219.142.217.*
    其实很难界定大型或者小型,如果你的目标业务是小数据量的(比如不超过50万用户),并且初期增长速度不是特别快的话,php是非常不错的选择

    另外一个矛盾的地方是如果你的业务压力足够大,但是业务价值不大(比如提供相册服务),php是最佳的选择
    #Terry001 发表于2007-12-05 23:47:51  IP: 222.210.176.*
    我到现在才看到这篇文章,真是遗憾啊
    简单,质朴,经验,良药,建议,这些是我对这篇文章的评价.
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 刘如鸿(Eric Liu)