大势所趋话开源——中国开源现状分析

随着计算机技术的发展,尤其是互联网技术和相关企业的兴起,开源软件在操作系统、编译工具链、数据库、Web服务器、移动操作系统等各方面已成为主流。而且许多企业利用开源软件形成了独特的商业模式。比如Google的Android操作系统,从2007年开源发布第一个版本起,到今天已经发展到4.1版本,占据了智能手机操作系统一半以上的市场份额,Google也通过Android操作系统在移动互联网这一新兴行业中占据了领先和主导地位。以前一直和开源软件做斗争的微软公司,为顺应潮流,也开始拥抱开源,比如向Samba项目贡献代码,放弃自己研发多年的大数据项目而选择Hadoop为其大数据的核心等。

显然,纵观IT行业这20多年的发展,开源项目已形成一股推进计算机及相关行业不停进步的巨大力量。本文将重点讲述国内的开源项目及社区的现状,以及发展过程中面临的困难和问题。


国内开源项目的发展及社区现状

国内开源软件的发展简史

国内开源项目的发展始于1997年前后。那时,中国第一个(局部)互联网(CERNET)刚建立不久,1995年在清华大学建立的著名的水木清华BBS就是开源项目。之后,Linux内核以及GNU项目中的成百上千个开源项目逐渐展现在国人的面前。

随后,中国也逐渐出现了一些开源项目。最初由国人开发的开源项目,主要解决的是Linux系统的汉化问题,流传最为广泛的应该是可以显示和输入中文的伪终端应用程序CCE。在1998年之后的两三年内,出现了以下三个开源项目。

  • LVSLinux Virtual Server)是由章文嵩博士开发的,后来被Linux内核收录,成为使用Linux操作系统搭建集群服务器的重要核心软件组件。
  • Smart Boot Manager是当时的清华大学博士生苏哲开发的,它是一个引导管理器,类似现在流行的GRUB,主要解决引导多种操作系统的问题。苏哲后来主持开发的SCIM系统,被各种流行的Linux发行版收录,成为Linux操作系统上提供多语种输入法支持的标准框架。
  • MiniGUI是由我开发的,后来由我创立的北京飞漫软件技术有限公司维护和发展,在功能手机、数码相框、工业控制系统和工业仪表中得到了广泛应用。

上述三个开源软件是中国开源软件早期的代表作,在国际上具有较强的影响力。

之后,国内开源项目的发展长期处于停滞状态,这与2000年左右互联网泡沫的破裂有一定关系。互联网泡沫的破裂,让许多梦想通过开源项目来创造商业奇迹的Linux发行版厂商很受伤。我曾供职的蓝点软件,在NASDAQ OTCBB板借壳上市,半年之内股价从20多美元跌到0.2美元,后于2001年贱卖。


2005年起,开源项目的发展逐渐走出低谷。在此期间,国内也出现了为数不多的开源项目,其中以清华大学陈渝副教授主持的SkyEye最具代表性。该项目旨在提供一个面向嵌入式软件开发和调试的ARM或其他架构的纯软件仿真器(虚拟机)。该项目持续活跃长达7年时间,吸引了许多海外高手参与,是为数不多的具有国际影响力且充分体现了国际化协作、分享的开源项目。


在参与开源项目的企业当中,最为活跃的是淘宝,接下来是新浪、百度、腾讯和华为等。同时,随着“开源中国”等社区的兴起,个人主持或者参与的开源项目逐渐多了起来。根据“开源中国”收录的开源软件,当前已经有一千多个由国人开发或者主持的开源软件。这和十年前相比,有了非常大的进步。有兴趣的读者可访问http://www.oschina.net。以下开源项目非常值得一提。

  • TFS是一款由淘宝开发的分布式对象存储系统,于20109月开源,存储了淘宝的几百亿张图片和交易快照。目前新浪微博已在生产系统中使用TFS作图片等对象的存储。
  • RT-Thread。这是一个由国人主持开发的开源实时操作系统,曾获得“第六届中日韩开源软件竞赛”的技术优胜奖(其他两个技术优胜奖获得者为淘宝的OceanBase和红旗的Qomo Linux)。RT-Thread 目前也获得了诸多商业应用。
  • Linux Deepin是近几年发展起来的面向桌面的中文Linux发行版,由一群来自武汉的Linux高手发起并维护。
  • ucore。从2010年暑假开始,陈渝博士组织清华大学学生开展教学用开源操作系统ucore的设计与实现,并直接用于清华大学的操作系统课程,学生可参考实验文档和ucore源码通过实践逐步深入掌握操作系统。这相对国内操作系统旧有的教学方法有较大改变,获得了国内外操作系统教学领域专家的认可,并将在教育部的支持下进行更大范围的推广。

国内开源软件的特点和问题

国内开源项目存在很多问题,如缺乏重量级项目、缺乏持续维护和更新、质量一般、用户不多等。另外,正如开源中国创始人所言,国人所开发的这些开源项目,和国际主流开源项目脱节严重,绝大多数处于单打独斗的状态。

例如,淘宝主导或参与的开源软件,大多数和互联网服务器后台、云计算相关,这些项目的主要用户是淘宝自己。因为门户之见,这些软件很难被其他的互联网企业所使用,大家不停地“造轮子”而忽视了开源软件发展必须具备的“共享”、“协作”精神。不过,现在这种情况正在改变,上面提到的淘宝TFS系统已被其他互联网企业使用,ucore项目也得到了诸多国内外大学积极的响应和支持。


我希望国内的开源项目能够和国际主流的开源项目步伐保持一致,要么加入国际化的开源软件,要么将自己主持的开源软件逐步国际化。这样,我们的开源项目才能得到源源不断的前进动力,也才能在国际化舞台上扮演更加重要的角色。

新的力量

无论如何,国内大型IT企业参与开源项目就是一个良好的开端,将为中国开源项目的发展起到非常大的促进作用。与此同时,各种开源社区活动也越来越活跃,例如具有政府背景的“开源软件高峰论坛”和草根性质的“我们的开源项目”巡回展演等。这表明,开源软件即将在国内引起新一轮的发展浪潮。

开源我的软件?

在高物价、高房价的今天,大部分人对此问题的第一反应是:“我就是一刚解决温饱的码农,我开源,谁养我?”这几乎与我们在十年前推广开源项目理念时遇到的问题一样。但这已大大落后于时代了!我们不仅可以通过使用其他人的开源项目赚钱,还可以通过开源自己的项目来赚钱。

如何靠开源项目赚钱?

在证明上述论点之前,我们先看看别人是如何利用开源项目赚钱的。靠开源项目赚钱的方式(经过验证的)无外乎有如下几种。

  • 双许可证模式。在采取严格的开源软件许可证的同时(通常选择GPL),给商业用户提供非GPL许可方式。这本质上是一种贩卖软件许可的行为,但开源软件带给开发者一个很大的好处,即传播迅速、快速迭代。我主持的MiniGUI项目就采用这种模式,在过去的五年当中,获得了几千万元的软件许可收费。当然,使用这个模式最成功的当属MySQL
  • 基础软件采用宽松许可证,同时向基础软件的商业用户贩卖增值服务或者增强组件、开发工具等的许可。这种模式可用于类似RT-Thread这类的基础性软件上,RT-Thread本身可以是开源且可无偿商用的,但其上的各种增值组件,如网络、文件系统、图形系统等,可以是商业软件。国外采用这种模式的以各类CMS系统为主。例如DrupalConcrete系统,其基本系统是开源且免费的,但其上的许多插件、主题、模版等是收费的。有兴趣的读者可访问 http://www.concrete5.org网站,其中还有“Marketplace(市场)”频道。
  • 混合模式,既贩卖工具等软件的许可,同时还向用户提供付费服务的模式。比如Ubuntu Linux发行版。
  • 成为平台型项目,并承载自己的互联网业务。这种模式在大型互联网企业中应用广泛。例如Google开发并开源Chrome浏览器,短短几年抢占了微软的很多市场份额,通过在Chrome中默认使用Google搜索引擎而获得极大的收入;再比如Google开源Android,一方面为了遏制苹果iOS的增长势头,另一方面通过预置Google搜索而获得了大量来自移动互联网的流量收入。

显然,有了先驱们的成功案例,作为开源软件参与者,不论是企业还是个人,都可能名利双收。

IT企业为何要参与开源项目?

作为企业,参与或者主导一个开源项目,其最为明显的动力应该是上述的第四个商业模式,即打造一个平台型项目。但就中国的IT企业来讲,我尚未看到有此种实力,或者此种抱负的企业存在,毕竟,打造一个平台需要长期的投入,一般情况需要五年或更长时间。貌似中国没有一个企业有这个耐心来投入五年这么长的时间在一个项目上。

那为什么企业还要参与到开源软件的开发中呢?我认为,谋不了大利就谋点小利,企业主导或参与开源软件,至少有以下几个好处。

  • 提高企业的美誉度。在利用开源项目的同时,也参与到开源项目中,企业的美誉度会得到很大提升。
  • 员工更有激情。因为自己的作品能够公之于众,虽然著作权本质上属于企业,但作为实际的编码者,可以通过开源自己的作品来获得额外的成就感和满足感。这对于稳定开发团队、提高开发人员的积极性会有很大的帮助。

当然,也许过不了几年,中国也能出现实践第四种商业模式的大型IT企业,让我们拭目以待吧!


个人开发者如何利用开源项目获益?

如果你是一名开源软件的开发者,打算利用自己的软件开创一家软件公司,该如何做?第一,我们要确定好自己的商业模式;第二,为自己的开源软件选择恰当的许可证。

如果决定选择双许可证模式,应选择GPL这样较为严格的许可证,它是这种商业模式能够成功的基础。当然,选择双许可证会阻碍产品在商业用户中的推广。尤其是对初生的开源项目来讲,显然是一种两难的境地。MiniGUI之所以可以采用双许可证模式,是因为在成立公司之前和最初的一段时间内,MiniGUI采取的是LGPL许可证,之后在软件足够成熟时才改为GPL许可证。另外,MiniGUI用于功能手机等系统中时,因为这种设备一般使用实时操作系统,缺乏应用LGPL/GPL许可证的技术条件,所以面向这种设备收取许可费也是天经地义的事情。MySQL采用双许可证模式得以成功的原因在于,MySQL AB公司并不会对仅仅用于Web服务器的MySQL商用行为收费,因为这种情况下,商业用户并不会发布MySQL的副本—它只是在服务器上运行而已。

因此,看起来上面提到的第二种、第三种商业模式是最适合个人开发者或者初创公司的商业模式,能够很快地速度推广和迭代软件本身,还能够确保有足够的收入来保证下一步的发展。在这种模式下,应该选择较为宽松的许可证。但大部分开源软件作者,由于并不真正理解开源软件的许可证,所以采取了错误的许可证(指在法律上是错误的)。例如RT-Thread,一方面采用GPL V2许可证,另一方面又承诺不会对商业使用收费。这其实没有解决根本的法律问题,即使用RT-Thread开发的衍生作品,到底要不要遵循GPL?这个问题和是否收费没有直接关系。要解决这个问题很简单,采用类似ApacheBSD或者MIT许可证即可。有读者会问,那为什么不能采用LGPL许可证?就RT-Thread这样的软件来讲,采用LGPLGPL没有本质的区别,因为RT-Thread的应用场合下一般不支持函数库的动态链接,这导致失去了适用LGPL许可证的技术条件。

上面提到的最后一种模式,是否适用于个人开发者或者初创公司呢?我的答案是,这种模式是大公司的玩法,小团队或小公司没法做这类事情。

大专院校应该成为开源软件的主力军

一个有趣的现象是,很多开源项目其实是作者在大专院校或者研究机构工作或学习时发起的,比如本文提到的三个国内早期的开源项目。甚至某些开源项目由特定的大学主持和维护,如BSD操作系统、PostgreSQL关系数据库、Minix操作系统等。

从国际视角看,开源软件的发展离不开一些知名大学的参与,BSDMIT许可证分别由加州大学伯克利分校和麻省理工学院定义,并由两所大学在其众多开源软件中使用,也被其他开源软件广泛应用。值得一提的是,苹果公司Mac操作系统和iOS操作系统,均使用了加州大学伯克利分校开发的BSD操作系统内核。

从现实情况看,在职的程序员,除非因为供职单位支持,否则很难独立发起和维护一个大型的开源项目,但在大专院校和科研机构工作的老师和学生,则有得天独厚的条件(主要是有大量的时间,并可能与科研课题和教学任务相结合)来发起和持续维护一个开源项目。清华大学陈渝副教授主持的SkyEyeucore两个开源项目就是典型的案例。笔者希望国内有更多的大专院校和科研单位(尤其是教师)能够积极参与到开源项目的发展当中,并成为国内开源项目的主力军。



政府和开源社区应该做什么?

在促进开源项目的发展中,政府要做的就是制定公平、合理的规则,促进相关法律法规的完善。如果知识产权保护力度不够,不仅会阻碍软件产业的发展,也会阻碍开源项目的发展。此外,需要政府支持建立以支持开源项目为己任的非营利性基金会组织。

加大知识产权的保护力度,一方面可以让商业软件在传统贩卖软件使用许可的商业模式下得到良性发展的机会,另一方面可以促使一部分人使用免费的开源软件,进而促进开源软件的发展。

就现阶段而言,如果政府能设立一些奖励基金等奖项,给开源项目的作者以一些奖励,也是不错的支持途径。

开源项目应该以松散、自组织的形式开发和发展,开源社区的存在,为开源软件开发者和使用者提供赖以生存的土壤。开源社区可以是网站、论坛,也可以是松散的交流、展演等。当然,开源社区第一步要解决的问题就是自己的生存问题。

我的建议是,开源社区应该尝试在现有法律框架下,以有限责任公司的形式来做国外开源基金会所做的工作。通过这种方式,可以有效避免无法注册NGO组织的问题,然后从企业(尤其是那些大型互联网企业)当中募集捐款,通过赞助一些开源项目,逐步推进开源软件社区的良性发展。

另外,国内开源社区还需要从使用者社区转向开发者社区,为开发者参与开源软件提供便利,如建立类似GitHub/SourceForge那样的开源软件托管站点,为开源软件项目提供邮件列表、论坛、博客服务等。



结语

将开源项目和商业结合,不管是在自己的项目中使用开源项目,还是靠自己的开源项目来赚钱,都无可厚非。关键是,我们需要尊重开源软件著作权的拥有者,按照开源软件所采纳的许可证办事,只有这样,开源软件才能得到长足发展。合法使用开源软件的前提,就是遵守开源软件的许可证规定的各种义务。

当然,更有积极意义的参与开源项目的方式是,将使用开源软件中遇到的问题或者修正、增强代码提交给开源软件的作者,帮助其改善作品。其实,这是任何使用开源项目的企业和个人都能做到的。

从技术到管理:思维转变是关键

IT公司研发部门的管理人员大多是从公司内部的技术人员中提拔的。在快速发展的公司里,这样的机会更多。然而这种“半路出家”的转型也给我们带来了很多挑战,其中最关键的部分在于思维方式的转变。

从个人成就到团队成就。无论是做管理还是做技术,成就导向意识是优秀员工的基本素质。只有具备很强的成就导向意识,才能把事情做得超预期,才能追求卓越。


刚刚上任的管理人员的思维方式往往还处于个人成就导向阶段,他们希望向外界发出一个明确的信号,团队之所以取得这样的成绩或者解决某个难题,是因为我的组织和领导。然而这种信号被团队成员多次接到后,会产生功劳都被领导拿走的感觉,从而导致团队的向心力下降。

这 时,比较好的做法是:要保护团队成员的成就导向,并且进行鼓励,从而刺激大家的积极性。例如,与某个团队成员共同解决了某个难题后,要弱化自己,重点表扬 这个团队成员对问题的贡献。这样再遇到某个难题时,这个团队成员才能保持一样或更高的激情。只有将自己的成就感定位在团队成就上,才能站得更高,避免和团 队成员产生直接竞争,从而有效地领导自己的团队。

上下同欲的氛围。兵法有云:“上下同欲者胜”。一个团队能够健康运作的基础就是“上下同欲”的氛围。要想拥有这种氛围,必须处理好两件事情:发言权和信息透明。

发言权:每个人都希望发表自己对某件事情的看法,尤其是比较关键的事情,并获得聆听。如果管理人员屏蔽这些,所表达的就是一种不尊重。当然不是所有的意见都要被采纳,需要需要合理的决策,但要让大家有发言的机会。

信息透明:这里的信息包括一切可以公开的信息,如上级期望和项目进展等。保持这些信息的透明度,能够提高团队成员对团队绩效的关注度和荣辱感。当大家都站在团队的高度上思考问题时,能够省去很多协调工作。

转型到管理岗位后,就要多花些时间来考虑团队建设问题。只有团队的氛围比较好,才有机会取得较好的成绩。

合理计划,要事第一。刚刚转型的管理人员往往会有类似这样的抱怨“杂事太多,被不停地打断”。造成这一问题的很大部分原因在于,计划不够周全或者缺乏例行 沟通机制。例如,每日站立例会基本上可以消除很多这样的杂事。同时因为管理人员需要接触的人比较多,所以日常处理的事情也会比较多。这与做技术人员有很大 不同。

这时就要有非常合理的计划,保证要事被及时处理。需要注意的是,时间的急迫性往往会夸大事情的重要性。如果管理人员总是习惯将任务拖到最后的截止时间处理,则会打乱事情的优先级,导致做事失去计划性。

培养人才,用人所长。杰克•韦尔奇说过:“在你成为领导之前,成功只同自己的成长有关。当你成为领导之后,成功同别人的成长有关。” 管理人员要把培养下属作为一件重要的事情,只有团队里的人才层出不穷,团队才有能力去不断挑战更高的目标。用人所长则指在工作的安排过程中需要多关注下属 的长处,不能过度放大他们的缺点。正所谓“用人所长,天下无不用之人;用人所短,天下无可用之人”。人事任命需谨慎考虑,用对一个人,能省很多心;用错一 个人,要操很多心。将合适的人放到合适的位置,是管理人员必须面对的一个难题。

2012,当我们谈论移动互联网创业时,我们在谈论些什么?

2012年的移动互联网市场可以用“冰火两重天”来形容。

根据Google官方数据,Android设备激活量在2012 年3-6月4个月内,由3亿部增长至4亿部,增长率为33%。据苹果官方数字,iOS设备激活量从2012年4-6月由3.6亿部增长至4.1亿部,增长 了12%。而对于中国市场,根据友盟的数据,2012年第二季度Android App启动次数增长159%;iOS活跃设备增长42%,iOS App启动次数增长112%。 这些数字都表明了移动互联网用户和终端量在2012年仍在高速增长。

但另一方面,移动互联网创业之路却愈发举步维艰:同质化竞争加剧,推广成本攀升,盈利模式迟迟未能清晰,投资者的钱也烧得差不多了……

但移动互联网始终是座巨大的宝藏,吸引着无数人甘愿冒险探寻。那么当前,如何度过寒冬,成功地求生是每个创业者、投资人都在思考的问题。本文中我将列举几个2012年移动互联网创业的关键点进行讨论,内容仅供引发思考,不做结论。


创业机会在哪里?

洗牌前期,巨头们开始以各种方式大肆进驻。一方面是以腾讯为代表的巨头正在进行全面的软件布局。目前腾讯已推出了几十款覆盖各个平台的App,涵盖了社交、 浏览、订阅、输入、同步、安全、音乐、游戏、阅读等领域,以强大的资金、渠道和人才优势与大批创业者直接竞争。另一方面,百度、阿里巴巴、奇虎360、盛 大等公司开始竞相推出搭载自己定制的操作系统的手机,抢占移动互联网的入口……

如果比拼渠道、资金和对人才的吸引,小公司毫好无胜算。因 此,在巨头驻足的通用领域,采取与巨头直接竞争的方式异常艰难。那么,在这种环境下创业者在创新方向选择时可能需要考虑“垂直化”和“行业化”,更多地去 挖掘那些还未被发现或者巨头没有兴趣去做的细分市场。在游戏、SoLoMo、O2O、移动电商、儿童教育等直接可以从消费者手上收钱的领域都有机会,在整 个行业的真实收入迅速攀升的基础上,移动广告、开发工具、各种外包等周边产业也会迎来相应的繁荣,与之相关的风险投资、孵化器、财务、法务、媒体、人力资 源等领域也会被拉动,各种企业的移动化也需要“行业化”应用的推动。在这些方向上,都尚未出现真正集大成、占据绝对优势的产品,如果能做出好产品加上合适 的分发渠道,创业者仍然有机会。

同时“硬件化”也是一个选择方向。随着中国二三线城市智能手机的普及,智能手机的细分市场也开始成型,针对 不同性别、层级、年龄段消费者的手机需要配套的软件和系统定制,因此这个层面上创业者与厂商间的软硬整合合作也存在一定的机会,当然,其中还包括平板、智 能电视等领域。

Native App还是Web App?

记得2011年时,Web App的概念大行其道,同时伴随着Adobe Flash Player的诸多不利消息,一时间HTML5被一些人捧上了制高点。但近期,Flash产品(首当其冲是游戏)开始全面爆发。依靠着Adobe AIR、Stage 3D等强大技术的布局,移动设备上开始涌现大量高品质的Flash游戏。而HTML5却从云端跌回残酷的现实:HTML5移动游戏领域的早期探索者 Moblyng倒闭,Mark Zuckerburg亲口承认Facebook的HTML5战略是个错误,Chrome Web Store里面力推的游戏表现都不甚理想……由于表现能力不足,自身标准一直未确定,并且缺少Web App分发和盈利的渠道,导致HTML5阵营中并未出现拿得出手的成功案例。也许就像一位开发者曾经说过那样:“HTML5是未来的趋势,但不是现在的优 势。”

毫无疑问,每种技术方案都各自有其优劣之处,必须要根据实际情况灵活选择。例如对于许多交互不多的传统内容型网站来说,HTML5已 基本可以覆盖全部需求。但在目前Web App受限于浏览器或前端技术未标准化的情况下,开发者可以考虑进行组合应用,对于侧重性能、体验、设备特性、本地数据管理等HTML5表现力达不到的部 分用Native来做,HTML5表现力能达到的部分就用HTML5来做。

总的来说,开发者应该掌握并提前布局多种技术,不能在一棵树上吊死。

最好的盈利模式?

无论怎样,成功不是一时半会儿的事,“活下去”是当前最重要的话题。由于投资锐减,创业者需要更多、更早地去考虑盈利问题。其实目前的移动互联网有一系列的盈利模式可供开发人员选择:

  • Pay-Per-Download。下载支付,为获得App使用权一次性支付费用。
  • In-App Purchasing。应用内购买,通常是一些应用的功能、提升游戏等级以及虚拟商品,目前是大陆最容易获得高收入的模式。
  • Subscriptions。订阅,一般是逐月为App付费,《程序员》杂志等阅读类App通常会采取这一模式。
  • Freemium。免费下载,提供增值付费服务,在Evernote等工具类应用中常见。
  • Commissioned Applications。提供外包服务。
  • In-App Advertising。App内展示广告模式和传统互联网的广告模式十分接近,被开发者大量使用,但效果渐减。
  • Product Placement。植入式广告,例如在游戏中的某一道具就是某品牌的饮料。
  • Purchase Intermediation。为从第三方App中带来的流量或其他资源拿到分成,但在大陆也常常演变为资源、流量互换。
  • Per-unit royalties。通常是与终端厂商和各大平台合作,例如厂商为手机上预装付费等。
  • Distribution Exclusivity Deals。针对独家应用商店发部应用,前段时间Rovio的《Amazing Alex》通过应用汇发布时似乎就采用了这种模式。

在 2012年6月VisionMobile对全球1500名创业者的调查中发现,Pay-Per-Download是当前最频繁使用的盈利模式。共有34% 的创业者选择了这种方式,较2011年相比略有下降。紧随其后的就是In-App Advertising,占33%。而从今年起,In-App Purchasing模式开始火热,已跻身高回报的收益模式之一。

但创业者需要明白,没有最好的模式,只有最适合的模式。而选择标准往往取 决于他们的产品模型、规模和目标市场。例如在大陆,游戏用户很难为一款未知的游戏下载付费,因此In-App Purchasing在今年大肆流行。而对于一些理财类工具,用户反而愿意付费来选择高品质的产品来保证自己的安全和隐私。同时,对于同一款产品,在不同 阶段“盈利模式”也可以转型,《Angry Birds》就是最好的例子,在长期霸占App收费榜前排位置之后,随着新产品的推出和游戏生命周期到来,小鸟们已从排行榜上跌落,却找到了更为稳健的盈 利模式:其周边产品和授权费为其带来了丰厚的回报,当然在大陆这种模式可能会被山寨得让人吐血。

生态系统困境

再好的产品也需要依靠良好的分发渠道和健全的市场,可2012年的中国移动互联网生态系统可谓满目疮痍,大部分开发者都多多少少面对迷局。对于中国开发者而言,山寨术依然是亘古不变的话题,而在这之外,新的问题接踵而来。

App Store一度帮助苹果打造了最优秀的移动生态系统。但2012年的种种迹象表明,这片生态系统似乎正在遭受侵蚀。刷榜问题日益严重,在2012年3月 时,App Store曾经采用技术更新的方式阻止刷榜,但也默认了对之前刷榜严重的公司不追究。果不其然,苹果的这种“不作为”态度让新算法仅见效2个多月,一股新 的刷榜风潮就开始愈演愈烈。有开发者认为苹果应该像Google Play那样摆出“令可错杀一千,不可放过一个”的态度,然假设如此,想必肯定会有无良对手花钱帮你“刷榜”,让你欲哭无泪。

同样,在 Android的第三方市场,刷榜也是同样泛滥。因此,有许多国内的开发者和媒体开始曝光和谴责这些产品。但从市场层面来看,这种影响并不会波及到消费 者,倘若刷榜风险和成本极小,加上一些投资人“有钱赚,怎么赚都是赚”的纵容态度,那么必定会有更多的人铤而走险。

除此之外,App Store审核周期常常是漫长且毫无规律可循;去对手产品下面刷差评;有程序员直接拿别人游戏安装包破解反编译加入自己的广告账号,放渠道上偷广告流 量……开发者不仅要注意暴风雨和暗礁,还需要迎战其他船只的攻击,移动互联网生态圈的困局还有多久才能解开?

不过在2012年9月17日,App Store出现7小时的“锁榜”现象(指整个榜单全部锁住,排名几乎不动,偶尔有一两名上下的波动只是因为某些限免App到期,从免费应用榜单下架所 致)。这个情况与2012年3月20日(上一轮排名算法完全改变的前2天)出现的7小时锁榜现象如出一辙。因此,有人预测排名算法即将再次大调整,希望会 带来一些积极有效的变革。

走向海外?

虽然有一些应用在中国也取得了不错的成绩,但暂时而言,大陆终归是付费意愿较低的市场,并且还有着前文提到的各种恶劣的竞争环境,在此状况下,走“国际化” 战略似乎是个不错的选择。实际上,如今中国移动互联网的很多明星团队已走向海外、专注海外甚至如《海豚浏览器》这样“来自海外”。

成功者固然令人艳羡,但成功的路却并非所见即所得。作为一个统称,海外市场实际上被细分成很多个不同的市场:欧美市场、日本市场、韩国市场、拉美市场、东南亚市 场……每个市场都依靠语言、文化、渠道特色、市场机制等地域特点建立了壁垒,倘若没有找对法门,可能不仅没有找到宝藏,反而撞得头破血流。简单地以日本市场为例,虽然其ARPU值非常高,但日本市场的用户口味与其他国家有很大区别,盈利主要来 自卡牌游戏,而且日本用户对于美术画风、各种细节的要求非常高(例如相比其他亚洲市场,欧美风格的产品可能更受欢迎)。

另外,也不是所有的产品都适合走向海外。很多产品一开始就拥有中国市场的基因,离开这个环节与其他本土产品竞争,很可能水土不服。在近期我采访的几位开发者中,他们在谈到海外市场时纷纷谈到中国团队的技术优势,看来这一点是每个想要异国求生的团队必须具备的素质。

我从创建四家技术公司中学到的事

限于篇幅,90件事部分摘录如下。

1. 找到公司该做的一件事情。它应同时满足以下三点:你和团队对此最有激情;你和团队有望最擅于斯;巨大的市场机会等待开发。

2. 如果不满足以上三点,则说明做的事情不对。

3. 只做自己的一件事。

4. 产品是第一位的。

5. 评判产品好坏的唯一标准是用户的使用度和它带来的价值。

6. 早期决定未来成功的关键因素是客户欢迎度。

7. 如果一年内得不到客户欢迎的话,就应转移目标。

8. 目标一旦转移,就应当专注,且不走回头路。

9. 须有自知之明。

10. 不要只想自己,激发身边人的能力才重要。

11. 不要只想自己,客户才重要。

12. 确保能找到卓越的、能独当一面的联合创始人。

13. 与你喜欢的人一起工作。

14. 你和联合创始人坐的位置要保证相互看得到。

15. 不要与不喜欢的人一起工作。

16. 创始人要亲自抓重要的工作或项目。

17. CEO还要做其他人做不到的事情。

18. 与那些敢于争论、敢于说不的人一起工作。

19. 在聘用高管时,最重要的考量是文化切合度。

20. 白天上班乐于激烈争吵,下班回家还是好同事。

21. CEO且只有CEO可以确立公司目标,前进途径和资源利用。

22. 果断决定。

23. 激励士气。

24. 促使身边人同你一样关注企业。

25. CEO要负责每个职位的招聘。

26. 聘用的人要有激情解决你们想要解决的具体问题。

27. CEO要引导企业氛围、风格、步调和期望。

28. 时而强硬。

29. 真实而透明。

30. 如果你瞧不上某人,那么其他人都会知道。

31. 解雇决定要提前一天安排好,然后迅速解雇。

32. 考虑好是培养并指导员工,还是苛责他们。

33. 好聚好散。

34. 提供反馈。

35. 高管亦须评估。

36. 你也有错的时候。

37. 向前看五步。

38. 全面构建自己的技术。

39. 从开始就将社交融入公司DNA。

40. 提前六个月考虑是移动优先还是Web优先。

简悦创始人云风谈程序员的职业素养

程序员是可以当作一生的职业。但首先,你需要热爱编程,而不是把它作为完成其他人生目标的工具,你要不断地反思自己在哪些方面的努力是更有效率的。我认为,无论在哪个子领域工作的程序员,都要在三个方面提高自己。


第一,保持对未知领域的好奇心,尽力开阔视野。如果你只精通一门编程语言,那么就赶快去学习另一门,最好和之前那门语言的亲缘关系越远越好。这可以让你从不同的视角去看待过去的问题。如果你只专注于一个领域,那么去深入地研究一下其他领域也会有很大帮助。

多数人都喜欢在熟悉的知识结构下解决问题,因为全新的东西总有学习门槛,需要了解很多基础知识才能展开实际的工作。能轻松地把相关信息组织起来调配,与借助 外部资料是很不一样的。后者要经历一个相当痛苦的过程。但一旦习惯经常地学习和积累新知识,你就可以逐步掌握一套自己的方法来减轻这种痛苦。而要做到这点 却很难,需要保持单纯的好奇心。

第二,把握各个层次上的细节。尽可能了解清楚系统每个层面的运行:硬件如何调度机器指令;数据在硬盘、内存、缓存、CPU间的流向;代码如何被编译链接,代码经历了何种过程被加载到内存,JIT怎样加速字节码的运行;操作系统怎样管理线程、处理I/O;软件 用到的第三方模块和工具如何处理数据;在网络环境中,数据流的通信协议;代码中每个模块逐个层次中的相互关系……

对细节掌握得越多,思路会越清晰。在每个层次上,你会看到不同层次的设备对上一层业务逻辑的抽象方式,直到最终你直接面对的业务。对业务的抽象能力,来自你对业务的熟悉程度,实际上这种能力更是随同对细节的把握能力同时具备的。

第三,提升对代码的直觉。优秀的程序员能很快地发现性能热点、找到系统崩溃的原因、找出不合理的代码……除此之外,准确的估算能力也非常重要,这要求程序员 能够快速心算出每个模块的开销和输入的数据量之间的关系。在写下每行代码时能够判断其对性能的影响,以简洁去挑战各个层次模块间的耦合复杂度。

要培养这种能力,除了不断地编写代码之外,别无良方。在写代码的同时,要时刻保持思考,要对不好的地方零容忍。要在最早的时刻动手,任何推倒重来的代价都不会太大;放任它们只会让局面演变到不可收拾的程度。

保持自己总有代码可写,不断地去发掘自己新的兴趣点,拓展新领域。要单纯一些,编程本身就是一件有趣的脑力活动,而不必仅仅为了解决一些问题而写程序。

为程序员开一剂提高职业素养的良方

我认为程序员和医生在某些方面很相似。医生是在解决人的问题,而程序员是在解决产品的问题。它们都有相似的职责,都是用理性的技术手段解决问题。程序员可以从医生的身上借鉴到很多东西,比如职业素养标准。

程序员的职业素养是建立在技术水平上的。对程序员来说,技术是解决问题的手段,类似医生给病人治病用药。很多人工作没几年便觉得技术“精通”了,工作没挑战了。孙老爷子(孙思邈)骂这种人:“世有愚者,读方三年,便谓天下无病可治。”以前端开发来说,HTML、CSS的语法规则一个小时内完全可以掌握,但离运用它解决问题还相去甚远。


技术范畴里有各种著名、非著名的开源类库、各种“大牛”的文章、书籍。这些都是别人在解决所遇问题积累下来的方 法和经验。在解决自己项目中的问题时,可以用,可以借鉴,但要了解其中的“至精至微之事”,绝不能用“至粗至浅之思”去用它们。我经常看到一些简历中,列出一长串开源库的名字。但掌握它们的用法,丝毫不能代表技术水平有多高。

除了上述现象以外,还有另外一种现象,很多程序员确实热爱技术,但他们不是在尽心地为所服务的对象解决问题,而是借项目机会不管三七二十一地练手。

相反,如果是一个解决问题能力超强的程序员,应该遵循什么样的行为准则呢?

第一,先敬业后乐业。关于敬业,梁启超说:“敬业就是凡做一件事,便忠于一件事,将全部精力集中到这事上头,一点不旁骛,便是敬。”敬业的程序员不一定要天 天加班、没日没夜地工作。导致加班的因素也许是开发方式不对、架构不灵活或是技术落后。敬业的程序员会凭借自己的技术能力和判断力,解决掉其中的症结,而 不是得过且过。

我有一位同事就是敬业典范,几年里他参与过公司很多项目的开发,并且做每一个项目都很投入。比如做了一段时间的在线阅读项目,便开始对排版产生浓厚兴趣,也因此比其他人在项目中收获更多东西。

当程序员不能深入一个问题到“至精至微”的程度时会产生很多问题:

  • 不能更好地利用技术(也就不能更好地解决问题);
  • 不能提高自己的技术水平;
  • 体会不到工作的乐趣。

梁启超解释乐业时说:“人生能从自己的职业中领略出趣味,生活才有价值。”很多人上来就追求乐业,有点本末倒置了。

第二,认真严谨的态度。孙老爷子说“不得于性命之上,率尔自逞俊快,邀射名誉,甚不仁矣”,是说不能在人命关天的大事上轻率地炫耀自己才能出众,猎取名誉, 这样做就太不仁德了!无论能力多强的程序员,都不该有炫技的想法,这样就偏离了解决问题的根本出发点,对整个团队的技术氛围也会产生不良影响。相反,能力 越强的程序员,看待问题越全面、越深入,对表面上看似简单的问题也不会轻易下结论,会考虑更多潜在的问题。

第三,乐于交流和分享。要知道你 在Google上搜到的都是别人无私奉献出来的知识和经验,利用这些开源技术解决难题,应有感恩之心。其实当程序员看到应用某种技术能将问题完美解决,也包括解决别人遇到的问题时,会有一种成就感。在公司里,程序员利用工作时间解决的问题、获得的经验,有责任主动分享出来,帮助他人节省开发时间。

技术人员创业后就不再适合继续编码了?

“如果你已经有一年或两年的编码经验,你还做编码,那么你就错了。”几年前当我开始创业时,有人曾对我这么说过。

哈,这是多么愚蠢的想法!我整天忙于新技术、开发新的东西,学习新工具,关心工作上的事情。

一般来说,初创公司通常会使用最新或者最牛的技术,前端时间我们使用了PHP支持静态HTML,接着利用Python支持PHP,最近开始使用Ruby on Rails或者node.js支持PHP……或也许未来Scala也是个不错的选择,至少它现在变得很流行。

有许多技术出身的创始人和我一样热爱编码,崇尚自由——渴望自己当老板,设置项目的最后期限,选择自己喜爱的技术,解决唯一重要的或者至少自己感兴趣的问题。

我想说,没有好的编码技能,想成为一个好的程序员几乎是不可能的。现实中的创始人与这个相差甚远。

一位成功的创始人需要具备:

  • 一个好的创始人需要投入50%的时间;
  • 一个好的创始人必须保持警灯常亮;
  • 一个好的创始人必须做好客户拓展;
  • 一个好的创始人要计划公司的发展愿景;
  • 一个好的创始人必须随时关注行业动态;
  • 一个好的创始人必须勇于承担责任;
  • 一个好的创始人经常获得客户支持;

等等这些事情都是初创公司需要关注的,没有人能帮你分担,这些重担都落在了创始人肩上,花费的时间要比常人要多很多。

编程是很难

无论你是多么优秀的程序员,无论你是多么有经验,总会遇到难题。编程无需太多人关注,只需要保持注意力就好。多数情况下你需要处理模糊的想法,想法很难被记住,想法通常以交互的方式进行,想法需要你铭记于心。在你头脑中必须要有个抽象的系统模型——如果你忘记某个函数或者忘记数据,亦或忘记在哪个文件里,那么你都无法编码。

编程需要全神贯注

当你进行重要项目时,你试过集中注意力了吗?也许你想集中注意力、想认真工作,但结果并非这样,是吗?

时间

编程需要时间,大量的、长期的、不间断的时间。

四个小时是个不错的周期。你的大脑需要大量的时间来思考,当项目完成时,你需要1-2个小时来休息、放松大脑,然后再开始下一项工作。

番茄工作法

如果你使用番茄工作法并找到合理的方式来运用,2个小时还是很不错的。记住,如果你的大脑里还有其他想法,那么这两个小时是无用的。

番茄工作法的做法

1.每天开始的时候规划今天要完成的几项任务,将任务逐项写在列表里(或记在软件的清单里)

2.设定你的番茄钟(定时器、软件、闹钟等),时间是25分钟。

3.开始完成第一项任务,直到番茄钟响铃或提醒(25分钟到)。

4.停止工作,并在列表里该项任务后画个X。

5.休息3~5分钟,活动、喝水、方便等等。

6.开始下一个番茄钟,继续该任务。一直循环下去,直到完成该任务,并在列表里将该任务划掉。

7.每四个番茄钟后,休息25分钟。

在某个番茄钟的过程里,如果突然想起要做什么事情——

a.非得马上做不可的话,停止这个番茄钟并宣告它作废(哪怕还剩5分钟就结束了),去完成这件事情,之后再重新开始同一个番茄钟;

b.不是必须马上去做的话,在列表里该项任务后面标记一个逗号(表示打扰),并将这件事记在另一个列表里(比如叫“计划外事件”),然后接着完成这个番茄钟。

作为公司的创始人需要管理员工......你认为多久召开一次四小时不间断的会议?没有会议,没有Skype呼叫,没有迫切的电子邮件,没有服务器崩溃,没人问问题吗?

倘若真如此,那么你就是幸运的。

给创业者的建议:

最好的方案就是你不再做程序员。你可以利用30%的时间或者更少的代码来保持这种编码感觉。除非你有足够的时间可以修改Bug,否则请保留你的美好形象吧。

不要再为公司而投身编码,除非请不起程序员。

必须要有一支强大的创业团队,以便你不再是一个人因这些事情而烦忧,技术创业者需要像小鸟一般自由。

无论做什么事情要跟随自己的心灵,开发者可以通过运动、散步等来锻炼自己,任何有助于你编码的事情(耐性)都可以去尝试。

尽快地雇佣更多的程序员,然后不惜一切代价保护他们。

我曾听说,有的则是白天当创始人,晚上当程序员。要知道这样做会把你搞垮的,记住千万不要这么做。

英文出自:Zemanta

 

 

软件开发者最重要的四大技能

现如今,可供选择的技术、语言及平台可谓五花八门,因此作为软件开发者,要弄明白哪里是花时间培养个人技能的最佳投资点也就难上加难。常常有人向我征求关于如何成为更强的程序员的建议。人们问得最频繁的问题可谓万变不离其宗,即他们是否应该把时间花在某种与众不同的特定编程语言或技术上。

最近我花了很多心思琢磨此问题,并想出了一些我认为最要紧且能让你受益终生的技能,一旦软件开发者掌握了这些技能,不仅会给他们带来最佳的工作机会,还会使他们变得卓有成效。

技能一:解决问题(Solving Problems)

以前我曾谈到需要学会如何解决问题,甚至给出了如何学会解决问题的若干步骤,因为我认为这种技能对任何软件开发者都是至关重要的。软件开发百分之百就是解决问题。

若毫无问题,就无需软件。

所有软件都被设计用于解决某些用户问题,而通用解决方案就是由许多能搞定的小规模问题所组成的阵列。要是你不能解决问题,就不会精通软件开发,而你所用的编程语言或技术也就无所谓了。在解决问题时,大多数开发者的表现简直糟糕透顶。

我常常会听到一些关于求职面试太难的抱怨,因为面试官会要求开发者去解决有一定难度的问题。我谈过为何有难度的面试挺好,而其中的部分原因在于,面试官就是要测试开发者解决问题的能力。我知道,许多开发者仍然不同意我对此问题的观点,而且他们也不明白像TopCoder[2]那样的网站为何要不遗余力地完善其开发技能,至少从我的亲身经历来看,那正是TopCoder解决问题的实践活动,而参与此类实践活动正是我职业生涯的转折点。

假想你是木匠。要想成为出色的木匠,也许你应该擅长切削木材。也许你应该亲手做过各种各样的部件,同时也用过许多不同的工具切削木材。

无论你的木工经验有多少年,抑或设计出的家具或橱柜有多漂亮,每次你也要想方设法切削木材,努力做出各个部件。切削木材是木工活的基础技能,就像解决问题是软件开发的基础技能一样。

技能二:自学(Teaching Yourself)

在生活中,可能没有比学会学习更重要的技能了。此种技能在软件开发中尤其重要,因为据我所知,任何领域的变化速度都超不过软件开发。你不可能无所不知、无所不晓。甚至你都来不及投入时间去成为某一特定框架或技术的大师——因为事物发展得太快了!反而,你需要这样的能力,即为完成手头任务而快速获取所需知识的能力。

要是你真想具备某种能让你在软件开发职业生涯中始终与时俱进的技能,那就学习如何自学吧。

提高此种技能的唯一方法就是付诸实践。走出去学习新的编程语言或技术,即使你认为决不会用得上它(也不妨学一下)。将来你会惊讶地发现,你竟然可以很快地把它捡起来,因为你早就对相关基础知识一清二楚了。要是你能迅速适应日新月异的软件开发市场、以及与之相关的各种技术和平台,你就会拥有那些总是很抢手的技能。

尽管我对蒂姆·费里斯(Tim Ferris)的某些主张有点儿怀疑,不过他写了本很棒的书,名为《4小时变身厨师》(4-Hour Chef),其中介绍了若干如何快速学习事物的绝招。(我那时也正打算写本与此主题有关的书。)

技能三:命名(Naming)

要是有人问起我成天在做什么,那我八成会说“研读其他人命名的事物,以及给事物命名。”诚然,若没人真那么问,我也不会真这么答,不过我的确有可能这么答哦。

软件开发就是在描述形而上学的内容。我们所构建的大多数内容都是看不见摸不着的。授权经理收到授权请求,然后发出授权响应,与此同时,用户资源库会调用用户工厂去组建新用户——我们必须根据以上描述在心中去构建起完整的环境。

每次你编码时,就是在给事物命名。当阅读自己或他人所写的代码时,你会从代码中的事物名称获得对代码的大部分理解。通过在开发者亲手编写的代码中查看方法、变量及类的命名方式,大多数情况下,我能准确预测出开发者的技能水平。要给代码中的概念及数据起合适的名字,而缺乏此能力的开发者就像个哑巴翻译。无论你能否明白某事,要是你不能妥善地解释它,那么此事会转瞬即逝。

提高此种技能的最佳方式就是不断实践。只要我在读代码时有所领悟,我往往会重命名代码中的事物。由于我开始明白某个方法到底在做什么,因此我会给方法改名,以便与我的理解相一致。在读代码时我会做这么做,即便代码没有产生任何逻辑变化,也照样会这么做。

你越关注给事物起合适的名字,你就会越擅长此道。这也是你代码中最显而易见的一面。简单看一眼你的代码,很难分辨代码正确与否或效率高低,但如果代码能让我一望而知,那么我会认为你知道自己在做什么。

技能四:待人接物(Dealing with People)

尽管我把此种技能排在最后,不过在许多情况下,你可能会说它是首要的或最要紧的技能。所到之处皆有人。除非你单独工作,且只为你自己开发软件,否则,作为软件开发者,其他人就会影响到你的职业生涯。我以前谈过为何你可能不想批评某人,不过我们更多地是与他人打交道,而不是惹人烦。我总是会重新捧起戴尔·卡耐基(Dale Carnegie)的那本名著《人性的弱点》(How to Win Friends and Influence People),因为这本书对于学习如何做一名成功人士是如此重要。我以前说过,倘若你想提高人们的技能,那就阅读此书吧!

基本问题是,人类不是合乎逻辑的生物,我们是情感生物。当然,我们喜欢为我们的推理能力而自豪,不过实际情况是,我们所做的大多数决策更多地受到情绪影响,而非理智。

作为软件开发者,此种技能对你的意义在于,除非你能妥善地处理与其他开发者、经理、甚至客户的关系,否则,即便你有许多好点子或很有用的技能,你还是会四处碰壁。一般说来,积极参与到软件开发社区中去也会对你的职业生涯有很大帮助。不要仅限于人际交流,而要把你的名字传播出去,并广结善缘。成功做到这一切直接取决于你待人接物的能力。(在学习如何待人接物时想走捷径?那很简单。请与人为善!)

怎样看待实用技能?

请注意,在我的列表中并未包括任何特定技术,甚至连Web开发或移动开发这样宽泛的技能也没有,这是何原因?在一些技术领域具有坚实的基础的确很重要,不过这些领域都不及我上面提到的这4种技能重要。要是你能够解决问题、快速学习事物、恰当命名事物、以及待人接物,那么与你专门从事任何特定技术相比,从长远来看,你将会取得更大的成功。

有这样一种说法,要深入学习一到两门编程语言,并从事某个通用的专业领域,这当然很重要,不过,只要你还没带着那些抉择在这条老路上走得太远,并把精力集中在提高这4种重要技能上,你自会万事大吉!(你甚至可以学习C++)

译文出自:图灵社区(译者/高翌翔

英文出自:Simpleprogrammer

 

 

程序员的20个常见瓶颈

在扩展性的艺术一书中,Russell给出了20个有意思的估计:大约有20个经典瓶颈。
Russell说,如果在他年轻时他就知道这些瓶颈该有多好!这些论断包括:

* Database (数据库)

  1. 数据规模超出了最大内存限制
  2. 大查询和小查询
  3. 写写冲突
  4. 大表join超占内存

* Virtualization (虚拟化)
  1. 共享磁盘,抢磁道,磁头各种抖
  2. 网络IO波动

* programming(编程)
  1. 线程:死锁、相对于事件驱动来说过于重量级、调试、线程数与性能比非线性
  2. 事件驱动编程:回调的复杂性、函数调用中如何保存状态(how-to-store-state-in-function-calls)
  3. 缺少profile工具、缺少trace工具、缺少日志工具
  4. 单点故障、横向不可扩展
  5. 有状态的应用
  6. 搓设计:一台机器上能跑,几个用户也能跑,几个月后,几年后,尼玛,发现扛不住了,整个架构需要重写。
  7. 算法复杂度
  8. 依赖于诸如DNS查找等比较搞人的外部组件(Dependent services like DNS lookups and whatever else you may block on.)
  9. 栈空间

* Disk (磁盘)
  1. 本地磁盘访问
  2. 随机磁盘IO
  3. 磁盘碎片
  4. 当写入的数据块大于SSD块大小时SSD性能下降

* OS (操作系统)
  1. Fsync flushing,Linux缓冲区耗尽(linux buffer cache filling up)
  2. TCP缓冲区过小
  3. 文件描述符数限制
  4. 电源管理(Power budget)

* Caching (缓存)
  1. 不使用memcached
  2. HTTP中,header,etags,不压缩(headers, etags, not gzipping)
  3. 没有充分使用浏览器缓存功能
  4. 字节码缓存(如PHP)
  5. L1/L2缓存. 这是个很大的瓶颈. 把频繁使用的数据保持在L1/L2中. 设计到的方面很多:网络数据压缩后再发送,基于列压缩的DB中不解压直接计算等等。有TLB友好的算法。最重要的是牢固掌握以下基础知识:多核CPU、L1/L2,共享L3,NUMA内存,CPU、内存之间的数据传输带宽延迟,磁盘页缓存,脏页,TCP从CPU到DRAM到网卡的流程。

* CPU
  1. CPU负载
  2. 上下文切换。一个核上线程数过多,linux调度器对应用不友好,系统调用过多
  3. IO等待->所有CPU都等起
  4. CPU缓存。(Caching data is a fine grained process (In Java think volatile for instance), in order to find the right balance between having multiple instances with different values for data and heavy synchronization to keep the cached data consistent.)
  5. 背板总线的吞吐能力

* Network (网络)
  1.  网卡的最大输出带宽,IRQ达到饱和状态,软件中断占用了100%的CPU
  2. DNS查找
  3. 丢包
  4. 网络路由瞎指挥
  5. 网络磁盘访问
  6. 共享SAN(Storage Area Network)
  7  服务器失败 -> 服务器无响应

* Process (过程)
  1. 测试时间
  2. 开发时间
  3. 团队规模
  4. 预算
  5. 码债(不良代码带来的维护成本)

* Memory (内存)
  1. 内存耗尽 -> 杀进程,swap
  2. 内存不足导致的磁盘抖动
  3. 内存库的开销
  4. 内存碎片(Java中需要GC的停顿,C中无解)

上面用英文表达的,是我还不太理解的,望诸位赐教。

========================================原文===========================

In Zen And The Art Of Scaling - A Koan And Epigram ApproachRussell
Sullivan
 offered an interesting conjecture: there are 20 classic bottlenecks. This sounds suspiciously like the idea that there only 20 basic story plots.
And depending on how you chunkify things, it may be true, but in practice we all know bottlenecks come in infinite flavors, all tasting of sour and ash.

One day Aurelien Broszniowski from Terracotta emailed me his list of bottlenecks, we cc’ed Russell in on the conversation, he gave me his list, I have a list,
and here’s the resulting stone soup. 

Russell said this is his “I wish I knew when I was younger" list and I think that’s an enriching way to look at it. The more experience you have, the more different types of projects you tackle, the more lessons you’ll be able add to a list like this. So when
you read this list, and when you make your own, you are stepping through years of accumulated experience and more than a little frustration, but in each there is a story worth grokking.

  • Database:

    • Working size exceeds available RAM
    • Long & short running queries
    • Write-write conflicts
    • Large joins taking up memory
  • Virtualisation:

    • Sharing a HDD, disk seek death
    • Network I/O fluctuations in the cloud
  • Programming:

    • Threads: deadlocks, heavyweight as compared to events, debugging, non-linear scalability, etc...
    • Event driven programming: callback complexity, how-to-store-state-in-function-calls, etc...
    • Lack of profiling, lack of tracing, lack of logging
    • One piece can\'t scale, SPOF, non horizontally scalable, etc...
    • Stateful apps
    • Bad design : The developers create an app which runs fine on their computer. The app goes into production, and runs fine, with a couple of users. Months/Years later, the application can\'t run with thousands of users and needs to be totally re-architectured
      and rewritten.
    • Algorithm complexity
    • Dependent services like DNS lookups and whatever else you may block on.
    • Stack space
  • Disk:

    • Local disk access
    • Random disk I/O -> disk seeks
    • Disk fragmentation
    • SSDs performance drop once  data written is greater than SSD size
  • OS:

    • Fsync flushing, linux buffer cache filling up
    • TCP buffers too small
    • File descriptor limits
    • Power budget
  • Caching:

    • Not using memcached (database pummeling)
    • In HTTP: headers, etags, not gzipping, etc..
    • Not utilising the browser\'s cache enough
    • Byte code caches (e.g. PHP)
    • L1/L2 caches. This is a huge bottleneck. Keep important hot/data in L1/L2. This spans so much: snappy for network I/O, column DBs run algorithms directly on compressed data, etc. Then there are techniques to not destroy your TLB. The most important idea
      is to have a firm grasp on computer architecture in terms of CPUs multi-core, L1/L2, shared L3, NUMA RAM, data transfer bandwidth/latency from DRAM to chip, DRAM caches DiskPages, DirtyPages, TCP packets travel thru CPU<->DRAM<->NIC.
  • CPU:

    • CPU overload
    • Context switches -> too many threads on a core, bad luck w/ the linux scheduler, too many system calls, etc...
    • IO waits -> all CPUs wait at the same speed
    • CPU Caches: Caching data is a fine grained process (In Java think volatile for instance), in order to find the right balance between having multiple instances with different values for data and heavy synchronization to keep the cached data consistent.
    • Backplane throughput
  • Network:

    • NIC maxed out, IRQ saturation, soft interrupts taking up 100% CPU
    • DNS lookups
    • Dropped packets
    • Unexpected routes with in the network
    • Network disk access
    • Shared SANs
    • Server failure -> no answer anymore from the server
  • Process:

    • Testing time
    • Development time
    • Team size
    • Budget
    • Code debt
  • Memory:

    • Out of memory -> kills process, go into swap & grind to a halt
    • Out of memory causing Disk Thrashing (related to swap)
    • Memory library overhead
    • Memory fragmentation

      • In Java requires GC pauses
      • In C, malloc\'s start taking forever


If you have any more to add or you have suggested fixes, please jump in.

Thanks to Aurelien and Russell for all their applied brain power.

架构设计的关键原则

关键的设计原则

在开始设计之前,思考一下关键的原则,将会帮助你创建一个最小花费、高可用性和扩展性的架构。

  • 分离关注点,将应用划分为在功能上尽可能不重复的功能点。主要的参考因素就是最小化交互,高内聚、低耦合。但是,错误的分离功能边界,可能会导致功能之间的高耦合性和复杂性,

  • 职责单一,每一个组件或者是模块应该只有一个职责或者是功能,功能要内聚。

  • 最小知识原则,一个组件或者是对象不应该知道其他组件或者对象的内部实现细节。

  • 不要重复你自己,你只需要在一个地方描述目的。例如,特殊的功能只能在一个组件中实现,在其他的组件中不应该有副本。

  • 最小化预先设计,只设计必须的内容。在一些情况,你可能需要预先设计一些内容。另外一些情况,尤其对于敏捷开发,你可以避免设计过度。如果你的应用需求是不清晰的,最好不要做大量的预先设计。

当设计一个应用和系统的时候,软件架构的目的是通过将设计分离到不同的关注点,来最小化复杂性。例如,用户接口UI,业务处理Business Process,数据访问Data
Access
就代表不同的关注点。在每个关注点内部,你设计的组件应该集中的内部实现,不应该和其他的组件混淆代码。例如,UI处理组件不应该包括直接访问数据源的代码,相反,应该使用业务组件或者是数据访问组建获取数据。

但是,你还是要为你的应用做一个投入|产出决定。在某些情况,你可能需要简化结构。例如,UI直接绑定到一个结果集。通常,也要从业务的角度考虑功能的边界。下面的这些高层次的原则将会帮助你从更广的范围上考虑影响设计、实现、部署、测试和维护系统的因素。


设计

在每一层保持设计模式的一致性。在一个逻辑层的内部,组件的设计对于特殊的功能应该保持一致性。

不要在应用中复制功能。只能在一个组件中提供指定的功能,这个功能不能在其他组件中复制。这将会保持组件的内聚性,而且如果功能需要修改的话,会变得很容易。

组合优先于继承。无论在什么地方,如果需要重用代码的话,优先使用组合而不是继承,因为继承增加了父类和子类的依赖关系,限制了子类的重用,

为开发建立代码风格和命名空间。建立统一的代码风格,使用和组织有关系的有意义的命名空间。

在开发的过程中,使用QA来保证系统的质量。在开发的过程中,使用单元测试和其他QA技术,例如,依赖分析和静态代码分析。为组建和子系统定义清晰的行为和性能指标,使用自动化QA工具来保证不影响整个系统的质量。


应用分层

分离关注点。将应用分离为不同的功能,这些功能保持尽可能小的重叠。主要的好处是一个功能可以最小化和其他功能的依赖关系。另外,如果一个功能失败了,不会导致其他功能的失败,对于其他功能来说是独立的。使得应用更容易理解和设计,简化复杂系统的管理。

明确层之间是如何通信的。

使用抽象实现层之间的松散耦合。可以通过定义接口来实现。另外,还可以通过使用接口类型或者是基类定义常用的接口。

在同一层,不要混合不同类型的组件。例如,UI层不应该包含业务处理组件,相反,应该包含处理用户输入和处理用户请求的组件。

在层和组件内部保持数据格式的一致性。混乱的数据格式,将会导致系统更难实现、扩展和维护。


组件、模块和功能

一个组件和对象不应该依赖于其他组件的内部实现细节。

组件的功能不要超出范围。例如,UI处理组件不应该包含数据访问代码,或者是试图提供其他的功能。

理解组件之间是如何通信的。这需要理解应用一定要支持的部署方案。你一定要决定是否所有的组件都运行在同一个进程中?是否一定要支持跨越物理或者是进程边界的通信?还是实现消息为基础的接口?

为组件定义一个清晰的职责。


你还要考虑下面的这些横向的关注点:

日志

认证

授权

异常管理

通信。选择合适的协议,最小化网络的通信量,在网络上保护传递的敏感信息。

缓存。为了提高系统的性能和响应速度,需要确定什么应该缓存?缓存在哪里?设计缓存的时候,要考虑到web服务器场和应用服务器场的问题。