May2

【转】软件架构师应该知道的97件事

Author: csdn  Click: 852   Comments: 0 Category: 架构  Tag: 架构师
      软件架构师是IT行业里独一无二的职业,既要精通软件开发技术,又要掌握业务知识,还要周旋于公司不同部门之间,协调各种予盾。做到这些绝非易事,博文视点即将翻译出版的新书《软件架构师应该知道的97件事》(97 Things Every Software Architect Should Know)探讨的就是这个主题。本书的编辑Richard Monson-Haefel是畅销书《Enterprise JavaBeans》和《Java消息服务》的作者。Richard邀请五十多位杰出的软件架构师分享工作经验和观点,帮助读者少走弯路。其中不乏大家熟悉的名字:《卓有成效的程序员》的作者Neal Ford,《企业集成模式》的作者Gregor Hohpe,Servlets和JSP专家组和W3C RDF工作组技术专家Bill de hÓra,《Web应用程序快速开发:使用TurboGears》的作者Mark Ramm,《Release It!》的作者Michael Nygard,《软件开发沉思录》的作者之一Rebecca Parsons博士,活跃于Perl社区的女架构师Allison Randal,《Java SOA Cookbook》的作者Eben Hewitt,等等。

下面内容摘自该书的标题,并给出了必要的补充说明, 由本书译者SeanBV(他的CSDN博客)整理,推荐给大家。
1.客户需求重于个人简历(Nitin Borwankar)客户需求至上。为了自己的简历更炫而采用新技术是沽名钓誉,往往事与愿违。
2.简化根本复杂性,消除偶发复杂性(Neal Ford)分析问题好比拨云见月、水落石出。
3.关键问题可能不是出在技术上(Mark Ramm)团队同心,其利断金。
4.以沟通为中心,坚持简明清晰的表达方式和开明的领导风格(Mark Richards)沟通应当言简意赅、详略得当,别拖泥 带水。
5.架构决定性能(Randy Stafford)种瓜得瓜,种豆得豆,架构设计也是一 样道理。
6.分析客户需求背后的意义(Einar Landre)抽丝剥茧,洞见症结。不要被表面需求 迷惑。
7.起立发言(Udi Dahan)起立发言效果更好。
8.故障终究会发生(Michael Nygard)应该提前设计预防措施,限制故障。
9.我们常常忽略了自己在谈判(Michael Nygard)工程师应该适时转换角色,学习谈判的 技巧。
10.量化需求(Keith Braithwaite)没有规矩,不成方圆。
11.一行代码比五百行架构说明更有价值(Allison Randal)可工作的代码才是目标,设计只是达成 目标手段。
12.不存在放之四海皆准的解决方案(Randy Stafford)软件世界没有万能钥匙。
13.提前关注性能问题(Rebecca Parsons)尽早展开性能测试。
14.架构设计要平衡兼顾多方需求(Randy Stafford)平衡兼顾项目的技术需求和相关各方的业务需求。
15.草率提交任务是不负责任的行为(Niclas Nilsson)要设法杜绝开发人员草率提交任务的念头。
16.不要在一棵树上吊死(Keith Braithwaite)为客户提供多样化的解决方案。
17.业务目标至上(Dave Muirhead)技术决策不能脱离业务目标和现实条件的约束。
18.先确保解决方案简单可用,再考虑通用性和复用性(Kevlin Henney
19.架构师应该亲历亲为(John Davies)身先士卒才能赢得同事的信任。
20.持续集成(David Bartlett)21.避免进度调整失误(Norman Carnovale)不惜一切代价拒绝调整项目进度的要求。
22.取舍的艺术(Mark Richards)架构不可能满足所有需求。
23.打造数据库堡垒(Dan Chak)一开始就要定义好数据模型。
24.重视不确定性(Kevlin Henney)推迟决策,建设性地利用不确定性。
25.不要轻易放过不起眼的问题(Dave Quick)别忘了温水煮青蛙的故事。
26.让大家学会复用(Jeremy Meyer)重复利用已有资源,首先要改变大家的观念。
27.架构里没有大写的“I”(Dave Quick)变让自己变成自大狂。
28.使用“一千英尺高”的视图(Erik Doernenburg)选择合适的架构视图。
29.先尝试后决策(Erik Doernenburg
30.掌握业务领域知识(Mark Richards
31.程序设计是一种设计(Einar Landre)软件开发也分成设计和生产两个阶段。
32.让开发人员自己做主(Philip Nelson)
33.时间改变一切(Philip Nelson)选择值得投入精力的工作,别跟以前的工作过不去。
34.设立软件架构专业为时尚早(Barry Hawkins)35.控制项目规模(Dave Quick)
36.架构师不是演员,是管家(Barry Hawkins)别忘了你的工作责任。
37.软件架构的道德责任(Michael Nygard)架构师的决定会影响许多人,务必慎重。
38.摩天大厦不可伸缩(Michael Nygard)但软件可以。
39.混合开发的时代已经来临(Edward Garson
40.性能至上(Craig Russell)
41.留意架构图里的空白区域(Michael Nygard)空白区域“充满”了各种软件和“硬件”。
42.学习软件专业的行话(Mark Richards)同行之间讲行话方便交流。
43.具体情境决定一切(Edward Garson
44.侏儒、精灵、巫师和国王(Evan Cofsky)开发团队不应该同质化。
45.向建筑师学习(Keith Braithwaite)借鉴建筑行业的经验。
46.避免重复(Niclas Nilsson
47.欢迎来到现实世界(Gregor Hohpe)现实世界比软件世界复杂。
48.仔细观察,别试图控制一切(Gregor Hohpe
49.架构师好比两面神(David Bartlett)架构师应该像两面神一样,眼观六路、耳听八方。
50.架构师应关注边界和接口(Einar Landre)寻找自然的边界,分而治之。
51.助力开发团队(Timothy High)优秀团队是成功的保障,要尽量助力开发团队。
52.记录决策理由(Timothy High)记录架构决策背后的理由,具有极高的投资回报价值。
53.挑战假设,尤其是你自己的(Timothy High)臆断是事情搞砸的主要根源。务必要确保软件基石坚实可靠。
54.分享知识和经验(Paul W. Homer)帮助周围的人不断改善,他们也会帮助我们发挥出全部的潜力。
55.模式病(Chad La Vigne)不要让一展设计模式功力的欲望,遮蔽了务实的真知。
56.不要滥用架构隐喻(David Ing)不要耽溺于系统隐喻之中,反让它拖了后腿。
57.关注应用程序的支持和维护(Mncedisi Kasper)应用程序的支持和维护,永远都不应该是事后才考虑的事情。
58.有舍才有得(Bill de hÓra)珍惜需要权衡的时机,远胜毫无约束和限制。
59.原则、公理和类比胜于个人意见和口味 (Michael Harmer
60.从“可行走骨架”开始开发应用 (Clint Shank)从“ 可行走骨架” 开始,增量培育系统成长。
61.数据是核心(Paul W. Homer)从“数据是核心”这个角度去认识系统,能大大降低理解复杂度。
62.确保简单问题有简单的解(Chad La Vigne)
63.架构师首先是开发人员(Mike Brown)碰到麻烦时,架构师可不能只会干吹烟圈却束手无策。
64.根据投资回报率(ROI)进行决策(George Malamidis
65.一切软件系统都是遗留系统(Dave Anderson)软件很快便会过时,修改维护无可避免。
66.起码要有两个可选解决方案(Timothy High
67.理解变化的影响 (Doug Crawford)清楚认识变化类型及其影响。
68.你不能不了解硬件(Kamal Wickramanayake)硬件容量规划,是和软件架构同等重要的事情。
69.现在走捷径,将来需付息(Scot Mcphee)及时还清技术债务。
70.不要追求“完美”,“足够好”就行(Greg Nyberg)避免过度设计。
71.小心“好主意” (Greg Nyberg)
72.内容为王(Zubin Wadia
73.对商业方,架构师要避免愤世嫉俗(Chad La Vigne)
74.拉伸关键维度,发现设计中的不足(Stephen Jones)
75.架构师要以自己的编程能力为依托(Mike Brown)
76.命名要恰如其分(Sam Gardiner)弄清楚要做的究竟是什么。
77.稳定的问题可以获得高质量的解决方案(Sam Gardiner)
78.天道酬勤(Brian Hart)真正做好那些看似简单的任务,坚守承诺。
79.对决策负责(Yi Zhou)
80.弃聪明,求质朴(Eben Hewitt
81.精心选择有效技术,绝不轻易抛弃(Chad La Vigne)
82.客户的客户才是你的客户!(Eben Hewitt
83.事物发展总会出人意料 (Peter Gillard-Moss)设计是在不断变化的世界中持续进行探索试验的过程。
84.选择彼此间能和谐共处的框架 (Eric Hawthorne)当心“无所不能”型的框架。
85.着重强调项目的商业价值(Yi Zhou)
86.不仅仅只控制代码,也要控制数据 (Chad La Vigne)
87.偿还技术债务 (Burkhardt Hufnagel)在速度和架构间进行权衡,保持平衡。
88.不要急于求解(Eben Hewitt)首先看看是否可以改变问题。
89.打造称手的系统(Keith Braithwaite
90.找到并留住富有激情的问题解决者 (Chad La Vigne)
91.软件并非真实的存在 (Chad La Vigne)虚拟世界中的软件是柔韧可变的。
92.学习新语言 (Burkhardt Hufnagel)防止沟通不畅和误解。
93.没有永不过时的解决方案(Richard Monson-Haefel
94.用户接受度问题(Norman Carnovale)减轻用户接受度问题带来的风险。
95.清汤的重要启示 (Eben Hewitt)软件架构设计需要不断的精炼浓缩。
96.对最终用户而言,界面就是系统 (Vinayak Hegde
97.优秀软件不是构建出来的,而是培育起来的(Bill de hÓra
May1

[转]sohu的核心架构,年代虽远,但依然受用

Author: 邹丹  Click: 1166   Comments: 0 Category: 架构  Tag: sohu,架构
bserv:
用于高负载,高读写速度的单点和集合数据。内核为BerkeleyDB,外壳为UDP线程池。接口为读写单点数据或者集合数据。单点数据就是Key->Value数据。集合数据就是有索引的数据,List->Keys->Values比如一个班级所有成员,一个主贴所有回帖等等。 DBDS性能很高,每秒读取>800个每秒,写>300个每秒(志强xeon:2G*272GscsiRam:2G配合java接口,目前应用在ChinaRen所有项目中(ChinaRen校内,校友录,社区等等)。是整个ChinaRen的核心数据服务,大概配备了50台服务器。特点:高速,高请求量。用于各种数据的低成本存储,解决数据库无法实现超高速读写的问题。门户级别的高速数据服务。

OnlineServer:
ChinaRen/SOHU
小纸条系统核心核心为3个小server系统:online2(在线系统业务逻辑)userv(用户资料系统)cserv(LRU缓存) 这三个子系统都是UDP+线程池结构,单进程+多线程。配备java接口,apache_modjsonxml接口。 online2包括了大部分业务逻辑,包括,上线,好友系统,纸条系统。 userv包括设置用户各种属性,信息。 cserv是个大的lru缓存,用于减小磁盘IO。可以放各种信息块,包括用户信息,好友,留言等。目前配备4台服务器(DL380xeon:3G*2SCSI:146G raidRam:2G),用户分布到4台服务器上,相互交互。服务器可以由1台到2台,到4台,到8台。底层存储为文件存储(无数据库),用reiserfs配套系统: mod_online,两个版本,apachelighttpd版本,用于页面上显示蜡烛人。请求量巨大,目前用lighttpd版本的mod_online放在sohusquid前端机器上,运行在8080,大概8台,每台请求量大概500-800个每秒。蜡烛人在所有ChinaRen页面有ID的地方显示用户是否在线。目前这套在线系统,作为SOHUIM的内核原型。准备开发WEBIM系统,用户所有SOHU矩阵用户的联络。


apache_mod

cserv:
高速LRU缓存系统。内核是UDP+线程池+LRU结构(hash+PQueue)。用于存放各种数据块,Key->Value结构。通过LRU方式提供给应用,可减小文件IO,磁盘IO等慢速操作。目前用于ChinaRen在线系统的用户资料缓存。特点:高速读写,低成本。

ddap:
UDP+
线程池,单进程,多线程的服务端程序原型,大部分程序由这个结构开始。性能为8000-10000个请求每秒。

eserv:
访问统计系统用于用户访问的次数和最后上线时间的存储和读写。用于ChinaRen校友录每个班级的访问记录。存储为文件存储,并有同时写入后备的bserv,用于备份和检索。目前性能,每台机器每秒50个记录,100个读每秒。能满足校友录巨大的用户登录记录的需要。特点:无数据库,纯文件存储,高速读写。低成本

logserver:
用于各种事件的日志记录核心为ddapUDP+线程池功能是分模块记录各种日志。ChinaRen所有用户服务,系统日志,都记录在logserver中。用于统计,查询。写入性能很好,每秒100个单台机器。特点:高速高效,低成本,海量。

SessionServ:
session
系统核心为ddapUDP+线程池用于在内存中存储临时数据。有get/put/del/inc等操作。广泛的用于固定时间窗口的小数据存储。比如过期,数据有效性检测,应用同步等等。由于是全内存操作,所以速度很快,存取速度应该>1000个每秒。目前广泛用与ChinaRen社区,校内,校友录等业务当中。特点:高速高效,低成本,应用广泛。

其他server:
MO_dispatcher
用于短信上行接口的的数据转发,使用TCP。能高速大流量根据业务号码分发到各个应用服务中。目前用于SOHU短信到ChinaRen各短信服务的转发。 sync用于静态前端同步,分客户端和服务端程序。客户端通过TCP链接和服务端获取需要同步的文件列表,并且通过TCP高速更新本地文件。此同步程序用于多客户端,单服务端。比如一台服务器生成静态文件,同步这些文件到若干客户前端去。特点:门户级静态内容服务器间同步,高效,高速,大流量。目前用于ChinaRen社区的静态帖子。

总结一下:
门户的核心服务,要求是高效率,高密度存取,海量数据,最好还是低成本。不要用数据库,不要用java,不要用mswin。用C,用内存,用文件,用linux就对了。

系列:
基于apache2的服务有很多,用于高请求量,快速显示的地方。 1.mod_gen_verifyimg2
用于显示验证码,使用GD2freetype。直接在apache端返回gif流,显示随机的字体,角度,颜色等等。用于ChinaRen各个需要验证码的页面,请求量很大。 2.mod_ip2loc
用于apache端的IP->物理地址转换,高速,高效。读取数据文件到内部数据树,高速检索,获得客户端ip的物理地址。用于需要IP自动定位的产品,还有就是数据统计等。比如ChinaRen校内,每个客户端请求都能获得物理地址,用于应用的逻辑处理。 3.mod_pvserver2
ChinaRen
社区帖子点击的记录和显示。根据URL,得到帖子ID,通过UDP数据包,统计到bserv系统。并且把结果通过Cookie返回到客户端。html直接用javascript显示点击数在帖子上。解决了点击数量高效记录,高效读取和非动态页面程序显示的问题。 4.mod_online
用于ChinaRen页面上的蜡烛人显示。和onlineserver通讯,得到用户在线状态和其他状态信息。请求量很大,每台前端大概500-800个请求。 5.其他mod 还有一些认证的,访问统计的,特种url过虑跳转的,页面key生成的,还有若干。特点:高速,密集超高请求量。前端分担应用服务器压力,高效。
Apr3

网站加速--Cache篇2【转自架构师杨建】

Author: 杨建  Click: 1112   Comments: 0 Category: 架构  Tag: cache,网站加速,系统架构
--提升性能的同时为你节约10倍以上成本
From: http://blog.sina.com.cn/iyangjian

一,Cache, 王道也
二,Cache 基本原理介绍
三,我划分的3个刷新级别
四,我对HTTP协议做的一点创新(?maxage=6000000)
五,Yslow优化网站性能的14条军规点评
六,上线了 !=  Finished
七,提速度同时节约成本方法汇总
-----------------------------------------------------------------------------------------

一,Cache,王道也

我觉得系统架构不应该仅仅是搭建一个强硬的能承受巨大并发压力的后台,前端页面也是需要架构的而且同等重要,不理解前台的的后台工程师是不合格的。中国人讲究钢柔相济,后台强硬只能说你内功深厚,前端用的巧,那叫四两拨千斤。

一般后台工程师很少关心前端如何使用自己的资源,而前端工程师,不知道自己的一个简单的用法会对后端造成多大影响。我会给出一些数据,来震撼下你的眼球。

二,Cache 基本原理介绍 (参考Caching Tutorial)

为什么使用Cache?
1,减少延迟,让你的网站更快,提高用户体验。
2,避免网络拥塞,减少请求量,减少输出带宽。
补充一个cache的原则:不更新的资源就不应该让它再次产生HTTP请求,如果强制产生了请求,那么就看看能否返回304。

Cache的种类?
浏览器Cache,代理Cache,网关Cache。
后端还有 disk cache ,server cache,php cache,不过不属于我们今天讨论范围。

Cache如何工作的?
1,如果响应头告诉cache别缓存它,cache不对它做缓存;
2,如果请求需要验证的或者是需要安全性的,它将不被缓存;
3,如果响应头里没有ETag或Last-Modifed header这类元素,而且也没有任何显式的信息告诉如何对数据保鲜,则它被认为不可缓存。
4,在下面情况下,一个缓存项被认为是新鲜的(即,不需到原server上检查就可直接发送给client):
    它设置了一个过期时间或age-controlling响应头,而且现在仍未过期。
    如果浏览器cache里有某个数据项,并且被被设置为每个会话(session)过程中只检查一次;
    如果一个代理cache里能找个某个数据项,并且它是在相对较长时间之前更新过的。
    以上情况会认为数据是新鲜的,就直接走cache,不再查询源server。
5,如果有一项过期了,它将会让原server去更新它,或者告诉cache这个拷贝是否还是可用的。

怎么控制你的Cache?
Meta tags :在html页面中指定,这个方法只被少数浏览器支持,Proxy一般不会读你html的具体内容然后再做cache决策的。

Pragma: no-cache : 一般被大家误用在http响应头中,这不会产生任何效果。而实际它仅仅应该用在请求头中。不过google的Server: GFE/1.3 响应中却这样用,难道人家也误用了呢。

Date: 当前主机GMT时间。

Last-Modified : 文件更新GMT时间,我在响应头中带上这个元素的时候,通常浏览器在cache时间内再发请求都会稍带上If-Modified-Since,让我们判断需要重新传输文件内容,还是仅仅返回个304告诉浏览器资源还没更新,需要缓存策略的服务器肯定都得支持的。有了这个请求,head请求在基本没太多用处了,除非在telnet上调试还能用上。

If-Modified-Since :  用在请求头里,见Last-Modified 。

Etag: 标识资源是否发生变化,etag的生成算法各是各样,通常是用文件的inode+size+LastModified进行Hash后得到的,可以根据应用选择适合自己的。Last-Modified 只能精确到秒的更新,如果一秒内做了多次更新,etag就能派上用场。貌似大家很少有这样精确的需求,浪费了http header的字节数,建议不要使用。
更正:Etag 其实在某种情况下可以很好的减少数据传输。在stonehuang的提醒下我才恍然大悟,转眼好几个月了也一直忘记更新。Etag应用场景。比如,数据为php的动态输出。每次请求把上一次Etag带来,跟本次计算的Etag进行比较,相等就可以避免一次数据传输。(最后修改时间 2009.12.07)

Expires :  指定缓存到期GMT的绝对时间,这个是http 1.0里就有的。这个元素有些缺点,一,服务器和浏览器端时间不一致时会有问题。二,一旦失效后如果忘记重新设置新的过期时间会导致cache失效。三,服务器端需要根据当前Date时间 + 应该cache的相对时间去计算这个值,需要cpu开销。 我不推荐使用。

Cache-Control:
这个是http 1.1中为了弥补 Expires 缺陷新加入的,现在不支持http 1.1的浏览器已经很少了。
max-age: 指定缓存过期的相对时间秒数,max-ag=0或者是负值,浏览器会在对应的缓存中把Expires设置为1970-01-01 08:00:00 ,虽然语义不够透明,但却是我最推荐使用的。
s-maxage: 类似于max-age,只用在共享缓存上,比如proxy.
public: 通常情况下需要http身份验证的情况,响应是不可cahce的,加上public可以使它被cache。
no-cache: 强制浏览器在使用cache拷贝之前先提交一个http请求到源服务器进行确认。这对身份验证来说是非常有用的,能比较好的遵守 (可以结合public进行考虑)。它对维持一个资源总是最新的也很有用,与此同时还不完全丧失cache带来的好处,因为它在本地是有拷贝的,但是在用之前都进行了确认,这样http请求并未减少,但可能会减少一个响应体。
no-store:  告诉浏览器在任何情况下都不要进行cache,不在本地保留拷贝。
must-revalidate: 强制浏览器严格遵守你设置的cache规则。
proxy-revalidate: 强制proxy严格遵守你设置的cache规则。
用法举例:  Cache-Control: max-age=3600, must-revalidate

其他一些使用cache需要注意的东西,不要使用post,不要使用ssl,因为他们不可被cache,另外保持url一致。只在必要的地方,通常是动态页面使用cookie,因为coolie很难cache。至于apache如何支持cache和php怎么用header函数设置cache,暂不做介绍,网上资料比较多。

如何设置合理的cache时间 ?
http://image2.sinajs.cn/newchart/min/n/sz000609.gif?1230015976759
拿我分时图举例,我们需要的更新频率是1分钟。但为了每次都拿到最新的资源,我们在后面加了个随机数,这个数在同一秒内的多次刷新都会变化。我们的js虽然能够很好的控制,一分钟只请求一次,但是如果用户点了刷新按纽呢?这样的调用是完全cache无关的,连返回304的机会都没有。

试想,如果很多人通过同一个代理出去的,那么所有的请求都会穿透代理,弄不好被网管封掉了。如果我们做只做一秒的cache,对直接访问源服务器的用户没太多影响,但对于代理服务器来说,他的请求可能会从10000 req/min 减少为 60 req/min ,这是160倍。

对于我们行情图片这样的情况,刷新频率为1分钟,比较好的做法是把后面的随机数(num)修改为 num=t-t%60 其中t是当前时间戳,这样你一分钟内刷这个url是不变的,下一分钟会增加1,会再次产生一个新请求。而我的max-age设置为默认59秒,即使设置120秒其实也没什么影响。可能你会说万一赶上临界点可能拿不到最新的数据,其实对用户来说,用那个多变的随即数和我这个分钟级的随即数,看到的效果是相同的下面我给你分析一下:如果用户打开了我们的分时间页面,当前随即数对他来说是新的,所以他会拿到一个当前最新的图片,然后他点了刷新按纽,用户会产生http请求,即使url没变,服务器有最新图片也一定会返回,否则返回304,一分钟后js刷新图片,分钟数加了1,会得到全新资源。这和那个随时变化的随即数效果有区别吗?都拿到了最新的数据,但是却另外收益了cache带来的好处,对后端减少很多压力。

三,我划分的3个刷新级别

名词解释 全新请求: url产生了变化,浏览器会把他当一个新的资源(发起新的请求中不带If-Modified-Since)。

更正:在firefox后来的版本中对此做了改进,倾向于更多的使用cache,曾经访问过的都会尽量捎带If-Modified-Since头。这些表现和IE一致。修改部分用红色标出。(最后修改时间 2009.12.07)

注: sports.sinajs.cn 在IE下的表现存在一个小bug,由于不是使用的strncpy,导致IE下难以返回304,
需要修改一行代码,把比较字符串长度设置为29即可解决。不过目前本人已不在职,难以修改。
情况一 FF 捎带的头: If-Modified-Since    Mon, 07 Dec 2009 10:54:43 GMT
情况二 IE 捎带的头: If-Modified-Since    Mon, 07 Dec 2009 10:54:43 GMT; length=6

1,在地址栏中输入http://sports.sinajs.cn/today.js?maxage=11地址按回车。重复n次,直到cache时间11秒过去后,才发起请求,这个请求会带If-Modified-Since

2,按F5刷新.  在你发起一个全新的请求以后,然后多次按F5都会产生一个带If-Modified-Since的请求。

3, ctrl+F5 ,总会发起一个全新的请求。

下面是按F5刷新的例子演示: http://sports.sinajs.cn/today.js?maxage=11
( 如果这个值大于浏览器最大cache时间maxage,将以浏览器最大cache为准)

----------------------------------------------------------发起一个全新请求
GET /today.js?maxage=11 HTTP/1.1
Host: sports.sinajs.cn
Connection: keep-alive

HTTP/1.x 200 OK
Server: Cloudia
Last-Modified: Mon, 24 Nov 2008 11:03:02 GMT
Cache-Control: max-age=11    (浏览器会cache这个页面内容,然后将cache过期时间设置为当前时间+11秒)
Content-Length: 312
Connection: Keep-Alive
---------------------------------------------------------- 按F5刷新
GET /today.js?maxage=11 HTTP/1.1
Host: sports.sinajs.cn
Connection: keep-alive
If-Modified-Since: Mon, 24 Nov 2008 11:03:02 GMT   (按F5刷新,If-Modified-Since将上次服务器传过来的Last-Modified时间带过来)
Cache-Control: max-age=0

HTTP/1.x 304 Not Modified   
Server: Cloudia
Connection: Keep-Alive
Cache-Control: max-age=11   (这个max-age有些多余,浏览器发现Not Modified,将使用本地cache数据,但不会重新设置本地过期时间)
----------------------------------------------------------
继续按F5刷新n次.......

这11秒内未产生http请求.直到11秒过去了...............
----------------------------------------------------------按F5刷新
GET /today.js?maxage=11 HTTP/1.1
Host: sports.sinajs.cn
Connection: keep-alive
If-Modified-Since: Mon, 24 Nov 2008 11:03:02 GMT (多次按F5都会产生一个带If-Modified-Since的请求)
Cache-Control: max-age=0

HTTP/1.x 304 Not Modified
Server: Cloudia
Connection: Keep-Alive
Cache-Control: max-age=11
----------------------------------------------------------按F5刷新
GET /today.js?maxage=11 HTTP/1.1
Host: sports.sinajs.cn
Connection: keep-alive
If-Modified-Since: Mon, 24 Nov 2008 11:03:02 GMT  (同上 ...)
Cache-Control: max-age=0

HTTP/1.x 304 Not Modified
Server: Cloudia
Connection: Keep-Alive
Cache-Control: max-age=11
----------------------------------------------------------


四,我对HTTP协议做的一点创新(?maxage=6000000)

上面看到了url后面有  ?maxage=xx  这样的用法,这不是一个普通的参数,作用也不仅仅是看起来那么简单。他至少有以下几个好处:

1,可以控制HTTP header的的 max-age 值。
2, 让用户为每个资源灵活定制精确的cache时间长度。
3, 可以代表资源版本号。

首先谈论对后端的影响:
服务器实现那块,不用再load类似mod_expires,mod_headers 这样额外的module,也不用去加载那些规则去比较,它属于什么目录,或者什么文件类型,应该cache多少时间,这样的操作是需要开销的。

再说说对前端的影响:
比如同一个分时行情图片,我们的分时页中需要1分钟更新,而某些首页中3分钟更新好。不用js控制的话,那我cache应该设置多少呢?   有了maxage就能满足这种个性化定制需求。

另一种情况是,我们为了cache,把某个图片设置了一个永久cache,但是由于需求,我必须更新这个图片,那怎么让用户访问到这个更新了的图片呢?从yahoo的资料和目前所有能找到的资料中都描述了同一种方法,更改文件名字,然后引用新的资源。 我觉得这方法太土, 改名后,老的还不能删除,可能还有地方在用,同一资源可能要存两份,再修改,又得改个名,存3份,不要不把inode当资源。我就不那样做,只需要把maxage=6000000 修改成 maxage=6000001 ,问题就解决了。

maxage=6000000 所产生的威力 (内存块消耗减少了250倍  ,请求数减少了37倍) :
体育那边要上一个新功能,一开始动态获取那些数据,我觉得那样太浪费动态池资源,就让他们把xml文件到转移到我的js池上来,为了方便,他们把那个84k的flash文件也放在了一起,而且是每个用户必须访问的。说实在的,我不欢迎这种大块头,因为它不可压缩,按正常来说,它应该代表一个3M的文件。我的服务器只这样设计的,如果一次发送不完的就暂存在内存里,每个内存块10k,如果不带参数默认maxage=120 。 我发现,由于这个文件,10w connections的时候,我消耗了10000个内存块。我自己写的申请连续内存的算法也是消耗cpu地,一个84k的文件,发送一次后,剩余的64k就应该能装的下,于是我把最小内存块大小改为64K。 这样消耗10w conn的时候消耗1500个左右内存快,虽然内存消耗总量没怎么变小,但是它能更快的拿到64K的连续内存资源,cpu也节约下来了。接下来我让meijun把所应用的flash资源后面加上maxage=6000000 (大概=79天,浏览器端最长cache能达到着个就不错了), 10w connections的时候,只消耗了不到40个内存块,也就是说内存块消耗减少了250倍  ,请求数减少了37倍。  35w+ connections, 5.67w req/s的时候也就消耗100块左右,比线性增加要少很多。也就是这点发现让我有了做这个技术分享的冲动,其他都是顺便讲讲。


五,Yslow优化网站性能的14条军规点评

其中黑色部分,跟后端是紧密相连的,在我们的内容中都已经涉及到了,而且做了更深入的讨论。兰色部分,5,6,7是相关页面执行速度的,构建前端页面的人应该注意的。 11属于避免使用的方法。 红色部分我着重说一下:

gzip 我不推荐使用,因为有些早期IE支持的不好,它的表现为直接用IE访问没问题,用js嵌进去,就不能正常解压。这样的用户占比应该在2%左右。这个问题我跟踪了近一个月,差点放弃使用压缩。后来发现我以前用deflate压缩的文件却能正常访问。 改用deflate问题解决。apache 1.x使用mod_gzip ,到了 2.x 改用cmod_deflate,不知道是否跟这个原因有关。 另外对于小文件压缩来说,deflate 可比 gzip 省不少字节。

减少 DNS 查询: 这里也是有个取舍的,一般浏览器最多只为一个域名创建两个连接通道。 如果我一个页面嵌了 image.xx.com 的很多图片,你就会发现,图片从上往下一张张显示出来这个过程。这造成了浏览器端的排队。 我们可以通过增加域名提高并发度,例如 image0.xx.com ,image1.xx.com ,image2.xx.com,image3.xx.com 这样并发度就提上去了,但是会造成很多cache失效,那很简单,假如我们对文件名相加,对4取mod,就能保证,某个图片只能通过某个域名进行访问。不过,我也很反对一页面请求了数十个域名,很多域名下只有一到两个资源的做法,这样的时间开销是不划算的。

另外,我在这里再添一个第15条:错开资源请求时间,避免浏览器端排队。
随着ajax的广泛使用,动态刷新无处不在,体育直播里有个页面调用了我一个域名下的6个文件,3个js,3个xml。刷新频率大致是两个10秒的,两个30秒的,两个一次性载入的。观察发现正常响应时间都在7ms,但是每过一会就会出现一次在100ms以上的,我就很奇怪,服务器负载很轻呢。meijun帮我把刷新时间错开,11秒的,9秒的,31秒的,这样响应在100ms以上的概率减少了好几倍,这就是所谓的细节决定成败吧。

1. 尽可能的减少 HTTP 的请求数     [content]
2. 使用 CDN(Content Delivery Network)     [server]
3. 添加 Expires 头(或者 Cache-control )     [server]
4. Gzip 组件     [server]
5. 将 CSS 样式放在页面的上方     [css]
6. 将脚本移动到底部(包括内联的)     [javascript]
7. 避免使用 CSS 中的 expression_r_r_r_rs     [css]
8. 将 JavaScript 和 CSS 独立成外部文件     [javascript] [css]
9. 减少 DNS 查询     [content]
10. 压缩 JavaScript 和 CSS (包括内联的)     [javascript] [css]
11. 避免重定向     [server]
12. 移除重复的脚本     [javascript]
13. 配置实体标签(ETags)     [css]
14. 使 AJAX 缓存    

六,上线了 !=  Finished

奥运期间我按1500w~2000w connections在线,设计了一套备用系统,现在看来,如果用户真达到了这个数目我会很危险,因为有部分服务器引入了32bit的centos 5未经实际线上检验,而我当时简单的认为它应该和centos 4表现出一样的特性。所以现在未经过完全测试的lib库和新版本,我都很谨慎的使用。没在真实环境中检验过,不能轻易下结论。

很多项目组好象不停的忙,做新项目,上线后又继续下个新项目,然后时不时的转过头去修理以前的bug。如果一个项目上线后,用户量持续上升,就应该考虑优化了,一个人访问,和100w人访问,微小的修改对后端影响是不能比较的,不该请求的资源就让它cache在用户的硬盘上,用户访问块了,你也省资源。上线仅仅代表可以交差了而已,对于技术人员来说持续的对一个重要项目进行跟踪和优化是必要的。


七,提速度同时节约成本方法汇总

1,编写节约的HTTP服务器 (高负载下速度明显提升,节约5~10倍服务器)
对一些重要的服务器量身定做。或者选用比较高效的开源软件进行优化。

2,不同服务混合使用  (节约1~2倍服务器)
如果我们一台服务器只支持30w conn的话,那么剩余的75% cpu资源,95%的内存资源,和几乎所有的磁盘资源都可以部署动态池系统,我觉得DB对网卡中断的消耗还是有限的,我也不用新买网卡了。

3,对于纯数据部分启用新的域名(速度有提升,上行带宽节约1倍以上)
比如我们另外购买了sinajs.cn 来做数据服务,以避免cookie,节约带宽. Cookie不但会浪费服务器端处理能力,而且它要上行数据,而通常情况上行比下行慢。

4, 使用长连接 (速度明显提升,节约带宽2倍以上,减少网络拥塞3~无数倍)
对于一次性请求多个资源,或在比较短的间隔内会有后续请求的应用,使用长连接能明显提升用户体验,减少网络拥塞,减少后端服务器建立新连接的开销。

5,数据和呈现分离,静态数据和动态数据分离 (速度明显提升,同时节约3倍带宽)
div+css 数据和呈现分离以后,据说文件大小能降到以前的1/3。
把页面中引用的js文件分离出来,把动态部分和静态部分也分离开来。

6,使用deflate压缩算法 (速度明显提升,节约3.33倍带宽)
一般来说压缩过的文件大小不到以前的30% 。
将上面分离出来的数据进行压缩(累计节约带宽10倍)。

7, 让用户尽可能多的Cache你的资源 (速度明显提升,节约3~50倍服务器资源和带宽资源)
将上面分离出来的css和不经常变动的js数据部分cache住合适的时间。(理想情况,累计节约带宽30~500倍) 。

以上改进可以让速度大幅度提升的同时,服务器资源节约 5~20 倍 ,减少网络拥塞3~无数倍, 上行带宽节约1倍以上,下行带宽节约30~500倍,甚至更多。
Apr3

网站加速--系统架构篇【转自架构师杨建】

Author: 杨建  Click: 2052   Comments: 2 Category: 架构  Tag: 系统架构,网站加速
--提升性能的同时为你节约10倍以上成本
From: http://blog.sina.com.cn/iyangjian

一,系统部署(高并发,可扩展)
二,负载均衡LVS(高可用,低成本)
三,IDC分布,DNS解析(快速)
-----------------------------------------------------------------------------------------

一,系统部署(高并发,可扩展)

本来想画在手稿上然后扫描上去的,貌似方法太土,在朋友的帮助下费了n个小时用Visio画了个,感觉很好看 ^-^ 。这一篇将主要围绕这个图来讲述。


首先从数据源说起,所谓狡兔三窟,我们数据源也是按三路设计,以保证IDC内部和不同IDC之间实现灾备。源头转发机A,B,C拥有往集群中任何一台服务器同步数据的权限,所以他们三个有一个活着,数据就可以同步更新,而且可以自动切换。从源头转发机到其他各IDC的数据都是双路的,然后每个IDC的前两台服务器具备转发功能,往IDC内部其他服务器分发数据,同一IDC内部的主备转发机可以自动切换。这样就实现了数据同步更新的高可用性。

介绍下这个集群里的角色,备机A来自行情系统,兼任源头转发的异地备份。系统内的另外两个备机属于轻负荷服务器,80端口空出来,必要时候只要一启动,就会立即自动加入到LVS后面服役。除了A以外所有具备转发功能的机器同时也是集群内的普通成员,需要提访问供服务的。各IDC的LVS本身也是有主备的,可以实现自动切换。

整个系统增减服务器非常方便,用户根本感觉不到,备机的启用更快,也就3~5秒,具备很好的扩展性。

我们的数据从源头上就是使用我编写的myzip压缩好了的,后缀名用"*.mz" ,比如 a.js.mz ,一直到用户的浏览器端才解压。数据传输量小,速度快。源头转发机上同时运行一个checkchange的程序,确保内容实际更新过的文件才往其他IDC转发,这样能有效的减少传输文件数量,以达到更快的更新速度。

另外,跨IDC系统部署,很重要的一点是,内网连通,路由选择,这影响数据传输速度的关键。北京的各机房间一般都有比较好的专线连通,只需要把路由打通就ok了。跨IDC的,一般都使用vpn来做内网传输,有条件的使用专线,这个比较昂贵,省着点用。另外跨网通,电信,和移动机房的一般都从双线机房路由,或者说,从到不同信息服务商连通性都比较好的机房路由。总之跨IDC数据传输,要做到各IDC之间的传输速度心中有数。

最后,请稍微注意下系统的安全性,包括数据传输的安全性,和网络安全性,避免遭受攻击。


二,负载均衡LVS(高可用,低成本)

LVS 有三种模式,NAT,TUN,DR,其中DR是最高效的,下面我将主要介绍DR的应用。更多LVS资料参见 LVS项目中文文档 目前我们公司的LVS应用规模在国内应该至少可以排前三,更多技术细节请咨询我们的LVS大牛xiaodong2.

下面是DR单臂模式的系统结构图:


下面引用一下官网的介绍: 在VS/DR 中,调度器根据各个服务器的负载情况,动态地选择一台服务器,不修改也不封装IP报文,而是将数据帧的MAC地址改为选出服务器的MAC地址,再将修改后的数据帧在与服务器组的局域网上发送。因为数据帧的MAC地址是选出的服务器,所以服务器肯定可以收到这个数据帧,从中可以获得该IP报文。当服务器发现报文的目标地址VIP是在本地的网络设备上,服务器处理这个报文,然后根据路由表将响应报文直接返回给客户。

我在财经时要使用LVS的初衷只是为了解决负载的均衡性,因为DNA轮询各前端服务器上连接数有不小的差距,那时候我们老大阿图对于这个项目给予了很大支持,还亲自组织过几次会议。话说恰巧yingyuan做了个新技术讲座,我从中发现LVS/DR后想让它帮忙修改负载均衡算法,后来部署上以后发现,不用修改,均衡的很,再后来xiaodong2接手后对性能和稳定性做了很大的提升,我们使用两年来没出过问题。另外lvs还额外带来了两个好处,高可用性,和可伸缩性。是可以随时把lvs后面的一台服务器下掉,扛走,用户是不知道的。服务器坏了也不用着急修,也不用修改DNS(另外DNS的层层cache影响不是一时半会就能消除的)。新增加一台服务器也是同理,最绝的就是备机的启用可以用秒来衡量(这些F5都能实现,代价不菲)。财经应用对公司内lvs的项目推动有不可磨灭的贡献 ,xiaodong2也这么说地 :) 。


三,IDC分布,DNS解析(快速)


这里思路跟CDN是一致的,尽量减少主干线路上的拥塞,让用户就近访问,以达到最快的数据传输速率。
我们要做的就是了解自己应用的用户分布情况,然后再结合现有资源以及各地网络出口特征,信息服务商的特征来部署我们的服务。

1,各省市网络用户分布依次排名(数据来自cnnic2007年的统计):
广东 13.4%
山东 8.2%
江苏 7.5
浙江
四川
河北
河南
福建
上海
辽宁
北京
湖南
山西
黑龙江

2,运营商的网络分布特点:
网通:以北京为超核心的放射性结构。山东应该是网通最大的用户,但它的网络存在瓶颈,会有丢包,造成外面访问它慢,它访问别人也慢。对此我们没有必要浪费珍贵的主干带宽,在济南布个点,同步一份数据过去就,让他们在自己省内访问,访问速度会立刻提升n倍。

电信:以几大省市为核心的环状结构,省市内部也是大环套小环。其中以广东用户最多,必须要部点的地方。记得很久以前我拿到一份数据说,上海人访问本IDC的数据,不如访问广东的速度快,不晓得现在是否还存在这种情况。电信有7个主要核心,分布在广州,上海,江苏,西安,成都,武汉,北京。

教育网:以国内主要的八个结点为核心。这八个结点分布在北京,西安,成都,广州,武汉,南京,上海,和沈阳。

3,DNS解析时候需要权衡的:
现在了解了这些信息,那我们开始讨论如何部署我们的服务。要考虑两个问题:一,要部署在哪几个IDC。二,每个IDC部署的服务器数量。三,DNS如何按区域划片。

要部署在哪几个IDC ?
其实这里还涉及到规模化应用的好处,一个小应用就部署了N多个IDC显然不划算。如果我的应用上了规模,我可以在每个省都部署上,那样用户体验将非常好,而且规模化以后会有专业人员对应用进行优化。所以公司里有动态池,和静态池这样的公用平台是好事(也许将来还会有我的js池)。如果我们的服务还没有上升到公司级别的规模,那就得考虑下取舍。

网通:东北三省,可以在沈阳和哈尔滨选择一个部署,有条件可以都部署。沈阳到北京的速率比哈尔滨到北京的速率快一倍,而哈尔滨到沈阳的速率,还不如到北京的快。北京,如果只让我在网通部署一个点的话,毫无疑问我会选择北京,其他所有结点到它的速率都比较快,但是北京的带宽比较昂贵。天津,这个点重要性仅次于北京,可以辐射河北,河南,江苏,离北京也比较近,价钱便宜。太原,可以辐射到西北一带。山东,前面已经说过,最好要部署的。

电信:那七个核心结点上部署了,速度就有保证。具体覆盖范围。广州覆盖周边几省,上海覆盖本地,江浙一带。武汉覆盖华中一带,西安可以覆盖西北5省,成都覆盖西南5省。

每个IDC部署的服务器数量?
这要根据具体应用来决定。比如财经用户网通,电信比例:3:4 而体育是 1:2 。教育网用户一般占1/30左右。这里还不能单纯考虑用户分布,还要考虑IDC内部灾备和IDC间灾备,是要有个取舍的。拿咱们的某个具体项目来说,教育网,够不上一台服务器,但是不得不部,因为它访问外界实在太慢了,我就住在学校里,也为了方便自己。我把北京作为主要结点部署了3台,天津,其实一台就够了,山东一台有点多。但是考虑到北京IDC一旦倒了,实力相当的IDC可以灾备,同时考虑到,天津,和山东只有一台,idc内部,都无法实现灾自动切换。所以,我选择天津两台,山东不部署,以性能换安全。

DNS如何按区域划片?
原则,就近分片,以达到最快传输速率。其次,考虑到各IDC间快速切换比较容易,DNS解析文件要写的简洁一些。另外,DNS解析有有个缺陷,每个单独域名里写在最前面的那个ip,它被轮询到的概率要比同组的服务器高10%,而且随着同组服务器的增多,这个差距会变大。所以最解析时候,每个IDC我都把硬件性能最好的服务器ip放在最前面。

另外:
做系统架构不提数据库,有点过不去。这块问题可以请教我们的DBA大牛zongwen同学。数据库是我将来一年的学习重点,争取一年后在DB方面能达到我们DBA六层功力。

分类

标签

归档

最新评论

the5fire的博客在12:44:23评论了
【原创】beautifulsoup解析中文网页乱码解决
python在12:10:14评论了
【原创】beautifulsoup解析中文网页乱码解决
vls在18:02:38评论了
【原创】使用STL来构造字符串split 和join方法
john在10:43:23评论了
【原创】php中ajax异步阻塞解决
Fang在08:51:00评论了
java was started but returned exit code=1问题解决小记

我看过的书

链接

其他

访问本站种子 本站平均热度:1414 c° 本站链接数:55 个 本站标签数:264 个 本站被评论次数:40 次