Feb 142014
 

开源的硬件、开源的软件,等你来参与

ElastosOrg是一个以Elastos操作系统开发为中心的一个开发者社区及软件工程管理工具的集合,

网址: http://elastos.org/

它上面的工程(project)分为四类:

  •  Elastos核心开发,所有代码需要经过一个Elastos核心研发团队的审查才能并入Elastos源码主干。
  •  Elastos工程开发,如Elastos on Ubuntu、Elastos on Lamobo等,Elastos在各种平台上的开发,产生的结果可能影响Elastos主干。
  •  Elastos核心构件开发/建议提案,利用Elastos技术,开发结果可能并入Elastos主干的各种实验工程。建议提案的意思是这类工程可能只是个proposal,没有源代码。
  •  Elastos应用开发。

ElastosOrg开发者社区为用户提供SNS及信息交流及成果展示等功能。SNS由用户(user)、组(group)等组成。

1、 elastos.org注册帐号
网址:http://elastos.org/register/
邀请码见本文后面所附,邀请码一经使用,就不可再用了。

Lamobo开源板社区需要单独注册帐号
http://lamobo.org/bbs/forum.php

2、 初始化有些登录信息,因为这些子系统中,要对用户设置独立权限等信息,所以需要做帐号初始化,但不需要再设置密码。
工程管理(project)系统:http://elastos.org/project/
源码管理(code review)系统:http://elastos.org/review/
测试用例管理(testlink)系统:http://elastos.org/testlink/
文档写作(wiki)系统:http://elastos.org/wiki/

3、 写BLOG
每个人,注册好帐号后,在elastos.org上就被设置了一个BLOG,这是为了让用户记录他们开发、使用过程中的各种信息的笔记。

4、 申请加入某个工程或得到某个源代码的操作权限
每个工程或源码的介绍信息中,都有类似下面的信息:
SNS: ElastosOrg http://elastos.org/groups/elastosorg/
CODE: http://elastos.org/review/#/admin/projects/ElastosOrg
Manager: http://elastos.org/members/xilongpei/profile/
上面的信息中,SNS对应的是该项目开发组在elastos.org上的组(group,如果这个组是个私有的组,有示该组不对外公开,你要先成为这个组的成员,然后才能访问这个组里面的信息),CODE对应的是该工程的源码仓库,Manager是该项目负责人在elastos.org上的SNS地址,通过该Manager在SNS上的介绍,你可以得到其更详细的联系人信息,如果他在SNS的profile页面上没有更多的联系信息,对不起,他可能不想被太多打扰。

有特别要求,请与其Manager联系。

 | 1,186 views | 0 comments | 0 flags | 

Mar 092016
 

http://mp.weixin.qq.com/s?__biz=MzAwMDUwNDgxOA==&mid=404597966&idx=1&sn=208df5a589a153c32535b86c77fbab3b&scene=0

一、研发工具与研发模式

据说,人之区别于禽兽,最大的特征在于利用,甚至发明工具。在没有任何其他工具时,我们只能借助于自己的肢体,一旦有了工具之后,我们的能力将会大大的增加。

 

但是,从另一个角度来看,工具也同时在限制我们的能力,甚至限制了我们的行为模式与思维模式。有一句俗话说得好:「手里拿着锤子,看见什么都像钉子。」

 

而在研发工具的领域,我们观察到另外一些有趣的现象:因为软件研发工具的开发者,同时也是工具的使用者。因此,他们不仅仅会受制于工具,也往往会由 此被激发,开发出对自己而言更加趁手的工具。开发者与使用者身份合二为一的现象,使得研发工具的发展,简直可以用「日新月异」、「层出不穷」甚至「争奇斗 艳」来形容。

 

随着软件复杂性的不断增加,以及软件开发的参与者不断增多,团队协作的辅助软件,也开始不断增加,随后我们发现:工具不仅仅限制了个人的行为模式,更进一步限制了团队的协作模式。

 

软件研发企业的管理者,往往会有某种错觉,他们会认为:管理就是定下制度、流程与规范,然后「下面的人」就会照此执行。因为有人「听话」,有人「不听话」,所以才需要奖励与惩罚的制度,来帮助管理者推行他的「规则」。所以,他们一般都很喜欢看《执行力》这样的书。

 

在开源社区,事情变得有些不一样。虽说开源社区也有「领导者」,甚至往往会有「精神领袖」,但他们并没有暴力手段,也没有经济手段,甚至行政手段。因此,要协调一帮自由散漫的黑客,共同开发高质量的开源软件,必须有更加高明的手段。

 

由于一切都是Open的,所以:不仅代码人人可见,开源社区的协作模式,也暴露在众目睽睽之下。从某种意义上来说:这促进了开源社区的协作工具的开发、进而使得开源的研发协作模式,以远远超过企业内部的演化速度飞速演化。

二、第一代开源协作模式

 

第一代开源协作模式,在早期几乎没有符合自身特殊需要的工具,有什么用什么,因此最为常用的email,被发展为Maillist,成为整个开发团 队的协作核心工具,大多数操作系统内置的diff/patch工具,使得代码的交流以email patch为主。这些老牌的开源项目,从使用RCS、CVS,到了后来也开始逐步引入svn/git,bugzilla这样的工具,但是围绕 mailing list开展协作的特征,则持久不变。

作为协作核心的Maillist

 

一个开源社区,往往就是一个邮件列表,随着软件的日益复杂,社区的不断扩大,邮件列表也会不断分化,通常会划分为:核心组、开发组、用户组。开发组与用户组的邮件列表,随着软件的架构分化为多个模块,还会进一步分解。

在邮件列表里,所有的用户都是平等的,在无法用工具保障流程的情况下,社区逐渐发展出了一套严格的邮件礼仪和格式规范。不规范的邮件,不会被理睬;不礼貌的家伙,甚至会被赶走。

 

邮件越来越多,即使分成多个邮件列表,依然太多。Archive这样的邮件归档、查阅的工具,就必须得有了。一封邮件,大家都来回复,严格re:的标题,组成了一个可供追溯的线索。

 

在邮件列表里,通常出现个人的名称,加上Reported-By、Tested-By、Acked-By的标记,即是一种代表个人名义的认可,也是流程规范的一部分,更是计算各人贡献的依据。

 

Bugzilla应运而生

 

在邮件中,有一类话题是最活跃的,那就是bug。但是,通过翻找邮件查阅bug的最新的解决状况,是非常困难的。一个bug,从提出,到最终解决, 并被确认在哪一个版本中发布fix,是一种稳定的状态转化模式。一个专有的处理工具,势必应运而生。Bugzilla、trac等一批工具,就由此被创造 出来了。

 

代码提交流程的规范化

 

开源社区,表面上非常的崇尚民主自由,但实际上却盛行精英主义、甚至是个人独裁的。我们往往会给某个开源项目的创始人,冠以「仁慈的独裁者」的头衔。虽然,是否仁慈,大家不得而知,但独裁确实是显然的了。

 

最大的独裁,是代码的管理权。因为作为创始人与核心开发者,他们往往以一己之力,贡献了绝大多数的代码,确定了项目最初的架构与发展方向。他们不会容忍任何人随意地向代码库提交代码。

 

在邮件列表中,一个新来的家伙,从没人认识,到能够独立的向代码库提交代码,非得经历艰辛的历程不可。这样的历程,简单的说,就是一次一次的 Code Review。被审核通过、合入代码库的patch越多,一个人对于社区的贡献就越大,可信度也越高,身份地位也逐步提高,然后,他也就可以去 Review其他人的代码了。

 

总结:在简陋的工具条件下,发展出高效、严格的社区协作模式

 

三、第二代开源协作模式

 

第二代开源协作模式,有两大特征:Web化、集成化。随着Web技术的不断成熟,开源社区也开始创造一个又一个的Web开源项目,其中Web化的项 目管理工具,如雨后春笋般冒了出来。在wikipedia上,issue-tracking systems列出了55个,project management software列出了152个,其中开源的也有30+,open-source software hosting列出了22个,堪称蔚为壮观。

 

这类平台又可以分为两大类:基于开源的项目管理工具或issue tracking工具,自建平台,以JIRA、DotProject、Redmine为代表;基于免费开源托管平台,以SourceForge、Google、LaunchPad为代表;

 

第二代的开源项目管理工具,可以说,主要是在向企业内的开发管理学习。文档、流程、角色、权限、统计报表等等功能,都开始出现了。有些开源项目,也在用这些东西。

 

以SourceForge与Google Code为代表的开源托管平台免除了开源项目搭建自己的官方网站,管理工具,代码仓库之类的繁琐事务,大大促进了开源项目的发展。不过,由于平台的功能总是受限的,因此自建门户,自组工具的开源项目依然层出不穷。

 

issue & milestone

 

在第二代开源协作模式日渐成熟的过程中,另一股潮流也正方兴未艾:「敏捷软件开发」。其中,最为深入人心的概念之一,就是每个迭代,完成一批User Story

 

在开源社区,这个概念被进一步演绎:无论是bug和feature,都被统称为issue。这些issue,被分到不同的milestone(版本),即使最后有可能延期,milestone也会定义一个预期完成时间。

 

这是好事?还是坏事?其实很难评价,因为从开源的原始教义而言:所有的贡献,都是自愿、随机、不可预期的。为自然生长的软件,规定里程碑,本来就显 得荒谬。但是,从另一方面而言,我们可以引用另一个中国人过马路的例子:「不管红绿灯,凑够一堆人就过马路」,开源软件,往往也是「不管里程碑,稳定一堆 特性和bugfix,就发布一个版本」。

 

如果在开源软件很少,更别提形成开源生态圈的情况下,这种随意的做法还是可行的。但是在大量软件,相互依赖的情况下,一个开源项目要赢得其他协作项目的信赖与协作,必须给出稳定的规划,以便相互配合。

 

这种规范,也是被逼出来的。

 

服务平台化

 

虽然黑客们喜欢写程序,但是要写的程序实在太多了,能够不重复造轮子,有现成的好工具可以直接拿来用,也是件好事。如果可以打开一个网站,注册一个用户,创建一个新的项目,剩下的事情自有平台帮忙打理,那么大家都可以愉快、专心的写自己的代码了。

 

平台在逐步进化,因而能够帮助开源项目,打理越来越多的事务。通常主流的开源项目托管平台,都能够完成:

  • 在线代码浏览,并能够支持不同的配置库
  • 需求管理、Bug管理,通常合并为Issue tracking
  • 版本与里程碑管理
  • 文档编写与管理,以Wiki的形式为主

更进一步的,还有能够完成:简单的自定义工作流、文件夹与静态资源管理、输出各种统计报表、甚至提供论坛、搜索、邮件列表以及各种排行榜等等。

在此之前,一个开源项目,是一个社区。到了大平台的时代,整个平台,构成了一个更大的社区。

 

总结:以Web形式提供的集成化开源项目托管平台,标志着开源项目的协作模式,进入成熟期

 

四、第三代开源协作模式

 

到了MySpace、Facebook与Twitter这样的SNS网站的兴起,开源项目的协作模式,受到SNS的启发,也随之进入了第三代,以 Social Coding为核心的开发协作模式,这样的模式在以Github为代表的网站上,体现的最为充分,众多的模仿者也层出不穷。过去的开源项目与托管平台,都 是以项目为中心来打造,而Github则是围绕着参与开源的人来打造。首先满足的不是项目的需求,而是个人的需求,由于对人的黏性大大增加,也使得 Github成为近年来最具吸引力的开发社区。

 

围绕着Github,一大批周边扩展服务被建立起来,构成了一个更加有活力的生态圈。而程序员们,不仅在Github上参与开源项目,更在Github上结交朋友,分享经验,增进能力。甚至这样的协作模式,还拓展到了编程领域之外,成为开放式协作的流行模式。

 

激励机制

 

第三代开源协作模式,以Github为代表,以Social Coding为精髓,这一代模式想要解决的问题,是激励机制的问题。

 

第一代开源协作,虽然创造了一批大大有名的项目,但事实上却是一个非常小圈子的事业。即使是最为成功的Linux内核开发,也不过1000~2000人。一旦人多事杂,就会出现管理混乱的现象。

 

第二代开源协作,虽然借鉴了很多企业界的规范管理经验,但是在事实上,却是不适应开源软件的风格的,举一个例子:在Redmine中存在的角色、权限、工作流之类的东西,实际开源项目使用的,却非常少。

 

第三代开源协作,借鉴了社交网络中的各种数值化模型,关注者数量,Star数量,Fork数量,Issue数量,Pull Request数量,都在显要位置标示出来,对于开发者形成正向激励,还有很多的统计图表,形象的展示了项目的活跃程度。

开源社区,原本就有非常深厚的,统计补丁数计算贡献度的传统,这一点在Github被发扬光大,可以说是优秀的继承与创新。

 

基于fork/pull request的协作机制

 

在github,一键就能够fork自己的分支,然后可以跟原有的分支毫无关联,也可以非常方便的提交pull request,这就带来了更加频繁的分裂,使得分裂常态化了。

 

原来的开源社区,开发者修改了代码,希望能够贡献给社区,需要穿越种种障碍,如果社区不接受,最后开发者只能逼不得已,自己开一个新的分支,变成一个新的项目。

 

在分裂是异常的状态下,分裂是罪恶的,是不应该的,是会带来阵痛的。当分裂变得常态化,pull request也变得常态化,分分合合,以每天N次的速度发生,恰恰因为如此,他不再是一种罪恶,而是一种健康的、向上的、以更快速度进步的模式。大家不 再是在一个版本下,各自贡献,而是在各自的版本下,独立发展,想分就分,想合就合。

 

Pull request,从一个代码合并的方式,变成了开发者之间主要的交流方式,他们发现,最好的交流,正是通过源代码来交流,一切的讲道理,都不如用源代码来讲道理。这恰恰是程序员们最习惯,也最喜欢的一种交流方式。

 

围绕Github出现的扩展服务

 

较之上一代的平台,Github提供了优秀的开放扩展机制:OAuth、API、SDK、WebHooks、ServiceHooks等等,使得围绕Github,扩展各种满足项目特定需要的服务,变得非常容易。

 

这就是从上一代平台的开源大社区,进化为「围绕Github的开源生态圈」。

 

到目前为止,Github一共支持超过170个不同的扩展服务,其中较为热门的服务有:

  • 与其他项目管理工具集成(Bugzilla,Asana, Basecamp,Redmine,JIRA,ZohoProject)
  • 与持续集成服务集成(Travis,Bamboo,CircleCI)
  • 与消息通知服务集成(Amazon SNS,Email,IRC,Jabber)
  • 与DevOps服务集成(AWS OpsWorks, DeployHQ)

 

Github 开放平台与API,基于Github OAuth API,其他网站可以支持开发者用自己Github账号登录,并使用一些有趣的服务。

 

  • Cloud IDE,用Github账号登录,直接在浏览器里打开一个IDE,编辑自己在Github上的开源代码
  • Resume Service,根据开发者在Github上的各种社交行为与开源项目贡献度,自动生成格式化的简历

这些扩展服务,极大的丰富了开源生态圈的内涵。

 

总结:社区天生就应该是社交化的,Social Coding与开源社区,简直就是天作之和。

 

五、开源协作模式的新探索

 

Git:作为标配

目前看来,git作为分布式配置库的王者地位,已经不可动摇了。能够初步总结的原因,至少有三个:

  • git与github互相促进,作为全球最大也最流行的开源社区,他的标配是git。这也导致越来越多的开源项目,选择git作为标配
  • 众人拾材火焰高,越是参与开发的人不断涌入,越是帮助git发展得更快。这是一个赢家通吃的世界
  • 开源生态圈的出现,使得围绕git、github发展出一大批相关的开源项目、开源工具以及次级社区。这一现象,在docker横空出世之后,再一次得到展现。

 

Code Review:必不可少

 

开源社区,一直有非常悠久的CodeReview的历史,哪怕在最早的mail & patch的时代,Review也是开源协作的头等大事。仅仅梳理Review的历程,也可以看到其中工具与流程的发展。

 

最初是邮件review,然后是在集成平台上内置review功能,或者提供更强大的review插件。到github创新的提出pull request,则是一种更加方便有效的review模式。

 

与此同时,独立于集成平台的专门的code review工具,也开始发展起来:Review Board、Google Gerrit、Facebook Phabricator是其中重要的几个代表。

 

Workflow:百花齐放

 

在git逐步流行之后,大家发现基于git可以选择的「玩法」实在是太多了。从最初写下一行代码,到最终出现在项目发布的版本之中,期间可以有无数的「路径」。

 

在git-scm.com官方教程《ProGit》里,提及了三种:集中式工作流、集成管理员工作流以及司令官与副官工作流。

 

在蒋鑫的《Git权威指南》里,又提及基于TopGit、基于submodule、基于subtree、基于repo、基于gerrit、以及git与svn配合使用的不同工作模型。

 

再后来:GitFlow、Github的Pull Request、以及基于Github的Github Flow等等工作模式,堪称百花齐放。

 

为什么会出来这么多workflow?因为团队与项目的差别,实在太大了。现在到我们简直无法想象:那些在各种情况下都坚持使用SVN都开发者,是怎么熬过来的?

 

当然,从另一方面来说:选择太多,也会带来另一种烦恼…

 

CI、CD、DevOps

 

从Everything as Code到Everything Automation,是另一个越来越明显的趋势。前两天,我从机场出来,正好看到两个并列的广告牌,一个广告的大意是:「UPS助您打通全球供应链」、 另一个则是「中国银行助您打通全球供应链」。这真的很有意思,看来在各行各业,大家都开始在关注整个生命周期的各个环节之间的打通。

 

只是,在软件领域,我们会感觉到这是一种回归。毕竟,最初的软件开发,都是很简单的。在一台计算机上,自己写程序,自己编译,自己调试、运行,最后发布。既不用依赖他人,更不用等待什么流程。

 

随着项目越来越复杂,参与的人越来越多,我们的软件,不能仅仅运行在自己的机器上,或者需要部署到服务器上,或者需要发布到某种平台上。在协作者众多的情况下,如何分工合作?

 

在开发者水平参差不齐的情况下,如何保证质量?在分工、协作、流程与质量保证的要求之下,如何提高效率?

 

这些都是DevOps致力于解决的问题,也是DevOps不断得以发展的原动力。

总结:开源社区,始终在进步,Github代表的也只是「一代」而已,新的一代协作模式,还会被创造出来的。

 

六、暗线:工具、习俗背后的逻辑

 

过去是如何?未来又会怎样?想要回答这类问题,其实需要更加深入的思考:「开源社区的协作模式,为何会变?变化背后的逻辑是什么?」

 

开源社区研发工具的两大目标:降低门槛,提高效率

 

开源社区,与普通的软件开发最大的不同,就是参与者多多益善。在《大教堂与集市》中,Eric Steven Raymond总结到:「如果开发者协调者有至少一个像Internet这样好的沟通媒介,并且知道如何不靠强制来领导,那么多人合作必然强于单兵作 战」,这简直就是绝妙的预言。虽然当年的ESR也许并未预测到,基于Internet会出现那么多辅助开源的相关工具(他们当时还只有邮件列表)。

所以,开源社区一直在致力于两个看上去相反的目标:「吸引尽可能多的人,以尽可能简单、便捷的方式,参与到开源中来」、「在人多得超乎想象的情况下,依然能够保持,甚至不断提高效率」。

 

如何计算参与者的贡献?

 

开源社区,不会给参与者发工资,因此激励是一个大问题。公平、公开、公正大计算所有参与者的贡献,以所有人都能够接受都形式,计算并公布各种排行 榜,可以说是开源社区特有都「刚性需求」,因此SNS与开源社区的结合,成为必然。以后,面向开源协作的大数据分析,也一定会出现。

 

如何激励、吸引、回报参与者?

 

计算参与者的贡献,仅仅是公平激励的基础。让激励变得有趣,变得有价值,变得有意义,则是吸引与回报参与者的不二法门。因此:游戏化的思路,会被越来越多的引入到开源社区中来。

 

如何保障项目质量?

 

开源项目保障项目质量都最大利器,是引入数量众多都热心测试者。但是,仅仅有人愿意测试,主动、积极都帮助测试,已经越来越不够了。随着项目越来越复杂,开源项目必须逐步走出仅仅依赖肉眼、依赖人多+运气的质量保障模式。

 

自动化测试、以及更加规范的Review流程,则是必然出现,而且将越来越重要的环节之一。

 

如何协调一致的工作?

 

自由与规范,计划与变化,兴趣与责任。经常会在社区里,成为争论的热点话题。虽然在《大教堂与集市》中,ESR极力鼓吹「礼物文化远远胜过交换经济」,但是:「在一个庞大的社区,各种各样的事务都需要有人去完成,而且还不能漫无章法。」

 

因此:「某种调节手段、协调者与协调机制、甚至是看不见的手」之类的东西,会慢慢的回到社区

 

如何在社区里平等、高效的协商?

 

目前来说,依然只能是线上讨论+线下开会。虽然,很多开源社区,开始学习《罗伯特议事规则》这样的开会圣经。但是,开会依然是最令程序员感到苦恼的事情。在这方面,将来会不会出现更好的辅助工具,这方面很值得期待。

 

结束语

 

唯有变化,是不变的。开源协作模式,同样如此。惟愿我们,能够成为推起其前进的力量之一。

 | 589 views | 0 comments | 0 flags | 

Oct 152015
 

http://blog.jobbole.com/92713/

 

介绍: 为什么好的提交信息如此重要

当你随意浏览任一 git 仓库的日志,你很可能会发现其中的提交信息或多或少有点乱。举个例子,瞧一瞧我早先提交到 Spring 上的这些宝贝

1
2
3
4
5
6
7
$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"
e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement() method as it turns out this was one of the culprits in the recent build breakage. The classloader hacking causes subtle downstream effects, breaking unrelated tests. The test method is still useful, but should only be run on a manual basis to ensure CGLIB is not prematurely classloaded, and should not be run as part of the automated build.
2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated ConfigurationPostProcessorTests until further investigation determines why it causes downstream tests to fail (such as the seemingly unrelated ClassPathXmlApplicationContextTests)
147709f Tweaks to package-info.java files
22b25e0 Consolidated Util and MutableAnnotationUtils classes into existing AsmUtils
7f96f57 polishing

狂吐吧!和最近提交到同一个仓库的信息比较一下:

1
2
3
4
5
6
7
$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"
5ba3db6 Fix failing CompositePropertySourceTests
84564a0 Rework @PropertySource early parsing logic
e142fd1 Add tests for ImportSelector meta-data
887815f Update docbook dependency and generate epub
ac8326d Polish mockito usage

你更喜欢阅读哪一个?

前者长度和形式截然不同,后者则简洁一致。前者像是随意为之,而后者才是精心构思的。

虽然很多仓库的日志像前者一样,但也有例外。Linux 内核 和 Git 自己都是很好的例子。Tim Pope 维护的仓库,以及 Spring Boot 也都不错。

这些仓库的贡献者知道,和后续开发者(事实上未来就是他们自己)沟通一个改动的上下文(context),最好方法就是通过一个好的 git 提交信息。代码差异(diff)可以告知改动的内容,但只有提交信息才能正确地告诉你为什么(why)。Peter Hutterer 很好地指出了这一点:

重建一段代码的上下文是一种浪费。我们不能完全避免,我们只能努力尽最大可能去减少它。提交的信息就可以做到这一点,以至于一个提交信息可以表明一个开发者是不是一个好的合作者。

如果你对如何写好 git 提交信息没有仔细想过,那你很可能没有怎么使用过 git log 和相关工具。这里有一个恶性循环:因为提交的历史信息组织混乱而且前后矛盾,那后面的人也就不愿意花时间去使用和维护它。 又因为没有人去使用和维护它,提交的信息就会一直组织混乱和前后矛盾。

但一个好的日志是一个优美和有用的东西,一旦日志处理的好,那么git blame、revert、rebase、log、shortlog 和其它子命令都将发挥它们的作用。查看别人的提交和 pull 请求是值得的,而且可以随时独立完成。理解几个月或者几年前发生的代码变动不仅变得可能,而且高效。

一个项目的长期成功依赖于(除了其它方面)它的可维护性,一个维护者最有力的工具就是项目的日志。所以非常值得花时间学习如何正确地维护它。刚开始可能很麻烦,但很快会成为习惯,最终会成为人们自豪和生产力的源泉。

我在这篇文章只会讨论如何保持一个健康的提交历史的最基本要素:即如何写好个人的提交信息。其它重要的实践,比如 commit squashing,我在这里不会涉及。我可能会在后续文章里讨论这些。

对于什么是惯用的约定,即命名和格式等,大多数编程语言都已经形成惯例。这些约定千差万别,但是大多数开发者都同意选择一种并坚持下去,这比让每个人自行其事导致混乱要好得多。

一个团队提交日志的方法应该一致 。为了创建一个有用的修改历史,团队应该首先对提交信息的约定形成共识,至少明确以下三件事情:

风格。包含句语、自动换行间距、文法、大小写、拼写。把这些讲清楚,不要让大家猜,并尽可能保持简单。最终的结果就是一份相当一致的日志,不仅让人读起来很爽,而且可以定期阅读。

内容。哪些信息应该包含在提交信息(如果有)的正文中?哪些不用?

元数据。如何引用问题跟踪 ID,pull 请求编号等?

幸运地是,如何生成一个地道的 git 提交信息已经有完善的约定。事实上,大部分都集成在 git 命令中,你不需要重新发明什么。你只需要遵循如下七条规则,就可以像老手一样提交日志。

七条很棒的 git 提交信息规则

记住:这都是之前都说过的。

  1. 用一个空行隔开标题和正文
  2. 限制标题字数在 50 个字符内
  3. 用大写字母写标题行
  4. 不要用句号结束标题行
  5. 在标题行使用祈使语气
  6. 正文在 72 个字符处换行
  7. 使用正文解释是什么和为什么,而不是如何做

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Summarize changes in around 50 characters or less
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of the commit and the rest of the text as the body. The
blank line separating the summary from the body is critical (unless
you omit the body entirely); various tools like `log`, `shortlog`
and `rebase` can get confused if you run the two together.
Explain the problem that this commit is solving. Focus on why you
are making this change as opposed to how (the code explains that).
Are there side effects or other unintuitive consequenses of this
change? Here's the place to explain them.
Further paragraphs come after blank lines.
 - Bullet points are okay, too
 - Typically a hyphen or asterisk is used for the bullet, preceded
   by a single space, with blank lines in between, but conventions
   vary here
If you use an issue tracker, put references to them at the bottom,
like this:
Resolves: #123
See also: #456, #789

1. 用一个空行隔开标题和正文

来自 git commit 帮助页:

虽然不是必须的,在提交的信息中先用一行简短的文字(少于50个字符)总结改动是好的想法,后面空一行就是更为详细的描述。提交信息中第一个空行前的文字可以作为题目,这个题目会在整个 Git 用到。比如,git-format-patch 把一个提交转化成 email,它就使用这个题目作为邮件的标题,提交中余下的部分作为邮件正文。

首先,不是每一个提交都需要标题和正文。有时简单一行也可以,特别是当这个改动很简单将来也不会变化。比如:

1
Fix typo in introduction to user guide

不需要再多说什么了。如果读者想知道拼写错误具体是什么,她通过 git show,git diff 或者 git log -p 命令,就可以很容易地看到这个改动。

如果提交的信息像下面命令行那样简单,你可以在 git commit 时使用 -m 开关。

1
$ git commit -m"Fix typo in introduction to user guide"

但如果一个 commit 需要多解释一点,你就要写一下正文。比如:

1
2
3
4
5
Derezz the master control program
MCP turned out to be evil and had become intent on world domination.
This commit throws Tron's disc into MCP (causing its deresolution)
and turns it back into a chess game.

这种情况下使用 -m 开关就不太方便。你真的需要一个合适的编辑器。如果你还没有设定好和 git 命令行一起使用的编辑器,可以参考 Pro Git 的这个章节。

无论如何,在浏览日志时,你会发现把标题和正文分开是值得的。下面是完整的日志:

1
2
3
4
5
6
7
8
9
10
$ git log
commit 42e769bdf4894310333942ffc5a15151222a87be
Author: Kevin Flynn <kevin@flynnsarcade.com>
Date:   Fri Jan 01 00:00:00 1982 -0200
 Derezz the master control program
 MCP turned out to be evil and had become intent on world domination.
 This commit throws Tron's disc into MCP (causing its deresolution)
 and turns it back into a chess game.

现在执行 git log –online,就只印出主题这行:

$ git log --oneline
42e769 Derezz the master control program

或者,git shortlog,按用户来归类提交信息,为了简洁一样也只显示标题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ git shortlog
Kevin Flynn (1):
      Derezz the master control program
Alan Bradley (1):
      Introduce security program "Tron"
Ed Dillinger (3):
      Rename chess program to "MCP"
      Modify chess program
      Upgrade chess program
Walter Gibbs (1):
      Introduce protoype chess program

git 中标题和正文之间的差别还体现在许多其他的功能上,但前提是标题和正文之间要有空行,这才能正常工作。

2. 限制标题字数在50个字符内

50个字符不是一个硬性规定,只是一个经验之谈。把标题行限制在这个长度,既保证它们容易阅读,也强迫作者去思考如何用最精简的方式解释发生了什么。

小技巧:如果你发现很难总结,那你可能一次提交太多改动了。 争取作原子的提交(一个题目对应一个单独的提交)

GitHub 的界面充分考虑到这些约定。如果超过50个字符的限制,它会警告你:
gh1

标题行中超过69字符的部分都被会截断,显示为省略号:
gh2

所以目标是50个字符,但一定不要超过69个字符。

3. 用大写字母写标题行

这个很简单。标题行的首字母大写。

例如:

  • Accelerate to 88 miles per hour

而不是:

  • accelerate to 88 miles per hour

4. 不要用句号结束标题行

标题行不需要考虑标点符号。而且如果希望保持在 50 个字符以内,慎用空格。

例子:

  • Open the pod bay doors

而不是:

  • Open the pod bay doors.

5. 在标题行使用祈使语气

祈使语气就是像给一个命令或指示一样叙述或写作。一些例子如下:

  • 打扫你的房间
  • 关门
  • 倒垃圾

你现在读到七个原则中的每一个都是用祈使语气书写的。(“正文在 72 个字符处换行”等)

祈使语气听起来有点粗鲁;所以我们通常不使用它。但对 git 提交信息的标题行而言,它确实很棒。一个原因是当 git 代表你创建一个提交时,它自己就是使用祈使语气。

例如,使用git merge 后的默认输出信息读起来就像:

1
Merge branch 'myfeature'

当你使用 git revert 时:

1
2
3
Revert "Add the thing with the stuff"
This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.

或者当在一个 GitHub  pull请求上点击“Merge”按钮时:

1
Merge pull request #123 from someuser/somebranch

当你用祈使语气编写你的提交信息时,你遵守了 git 内在的约定。例如:

  • 重构 X 子系统以增加可读性
  • 更新新手入门的文档
  • 删除弃用的方法
  • 发布1.0.0版本

一开始这样写会有点尴尬。同样是用来描述事实,我们更习惯用陈述方式去讲话。这也就是为什么提交信息常常读起来都是这样:

  • 用 Y 修正了问题
  • X的改变行为

有时编写的提交信息像是一个内容的描述:

  • 对损坏事物的更多修正
  • 新酷的 API 方法

有一个简单的规则,每次把它做正确就可以减少误解。

一个格式正确的 git 标题行应该可以完成下面的句子:
如果被采用,这个 commit 将把你的标题放在这里

例如:

  • 如果被采用,这个 commit 将会重构 X 子系统以增加可读性
  • 如果被采用,这个 commit 将会更新新手入门的文档
  • 如果被采用,这个 commit 将移出弃用的方法
  • 如果被采用,这个 commit 将发布 1.0.0 版本
  • 如果被采用,这个 commit 将从 user/branch 合并 #123 pull 请求

注意下面这些非祈使格式不能工作:

  • 如果被采用,这个 commit 将用 Y 修正了问题
  • 如果被采用,这个 commit 将X 的改变行为
  • 如果被采用,这个 commit 将对损坏事物的更多修正
  • 如果被采用,这个 commit 将新酷的 API 方法

记住:使用祈使语气只在标题上是重要的。你在编写正文的时候,可以放宽这一限制。

6. 正文在72个字符处换行

Git 从来不自动换行。当你编写一个提交信息的正文时,你必须考虑到正确的间距和手动换行。

推荐在72个字符处换行,这样 git 有足够的空间来缩进文本,还可以保持整体都在80个字符以内。

一个好的编辑器在这里可以有所帮助。例如当你编写一个 git 提交时,可以很容易在 Vim 上设定 72 个字符换行。但是通常,IDE 提供文本换行的智能支持都很糟糕(虽然在最近版本中,IntelliJ IDEA终于有所改善)。

7. 使用正文解释是什么和为什么,而不是如何做

这个提交是一个来自 Bittcoin Core 的好例子,解释了什么被改动了和为什么:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
commit eb0b56b19017ab5c16c745e6da39c53126924ed6
Author: Pieter Wuille <pieter.wuille@gmail.com>
Date:   Fri Aug 1 22:57:55 2014 +0200
   Simplify serialize.h's exception handling
   Remove the 'state' and 'exceptmask' from serialize.h's stream
   implementations, as well as related methods.
   As exceptmask always included 'failbit', and setstate was always
   called with bits = failbit, all it did was immediately raise an
   exception. Get rid of those variables, and replace the setstate
   with direct exception throwing (which also removes some dead
   code).
   As a result, good() is never reached after a failure (there are
   only 2 calls, one of which is in tests), and can just be replaced
   by !eof().
   fail(), clear(n) and exceptions() are just never called. Delete
   them.

看一下完整的 diff,可以想象作者当下花了多少时间提供这些上下文信息,这大大节省了同伴和未来提交者的时间。如果他不这么做,这些信息可能就永远消失了。

大多数情况下,你可以省去改动的具体实现细节。 在这点上,代码通常是不需加以说明的(如果代码太复杂需要文字解释,可以使用代码注释)。首先把你做这个改动的原因交待清楚 —— 改动前是如何工作的(和出了什么问题),现在是如何工作的,以及为什么你要采用这种方法解决问题。

未来的维护者会感谢你,这个人可能就是你自己!

小技巧

学着去热爱命令行。抛弃 IDE。

拥抱命令行是明智的,理由就像 git 子命令那样多。Git 是强大的,IDE 也是,但是表现的方式不同。我每天都使用 IDE (IntelliJ IDEA),也用过不少其它的IDE(Eclipse),但我看到集成 git 的IDE ,都无法企及命令行的方便和强大(一旦你了解它)。

某些 git 相关的 IDE 功能是很有用的,比如通过调用git rm 删除一个文件,用 git 重新命名一个文件。但一旦你开始使用 commit、merge、rebase 这些命令,或者进行复杂的历史分析,IDE 就无能为力了。

要发挥 git 的全部火力,那就是命令行。

记住无论你使用 Bash 还是 Z shell,都可以使用 Tab 补齐脚本来减轻记住子命令和开关的痛苦。

阅读 Pro Git

Pro Git 这本书可以在网上免费得到了 ,太棒了。好好利用吧!

 | 506 views | 0 comments | 0 flags | 

Sep 182015
 

这是一个非常有趣的 非主流前端领域,这个领域要探索的是如何用工程手段解决前端开发和部署优化的综合问题,入行到现在一直在学习和实践中。

在我的印象中,facebook是这个领域的鼻祖,有兴趣、有梯子的同学可以去看看facebook的页面源代码,体会一下什么叫工程化。

接下来,我想从原理展开讲述,多图,较长,希望能有耐心看完。

让我们返璞归真,从原始的前端开发讲起。上图是一个“可爱”的index.html页面和它的样式文件a.css,用文本编辑器写代码,无需编译,本地预览,确认OK,丢到服务器,等待用户访问。前端就是这么简单,好好玩啊,门槛好低啊,分分钟学会有木有!

Continue reading »

 | 495 views | 0 comments | 0 flags | 

Sep 052015
 

http://drops.wooyun.org/%E8%BF%90%E7%BB%B4%E5%AE%89%E5%85%A8/8169

 

0×00 前言


运维安全是企业安全保障的基石,不同于Web安全移动安全或者业务安全,运维安全环节出现问题往往会比较严重。

一方面,运维出现的安全漏洞自身危害比较严重。运维服务位于底层,涉及到服务器,网络设备,基础应用等,一旦出现安全问题,直接影响到服务器的安全;另一方面,一个运维漏洞的出现,通常反映了一个企业的安全规范、流程或者是这些规范、流程的执行出现了问题,这种情况下,可能很多服务器都存在这类安全问题,也有可能这个服务还存在其他的运维安全问题。

本文一方面希望帮助甲方覆盖一些盲点,另一方面也能够为白帽子提供一些漏洞挖掘的方向和思路。

0×01 Attack Surface


一图胜千言,下图是个人近期总结的一些常见的运维风险点。

enter image description here

附XMIND源地址:https://github.com/LeoHuang2015/ops_security/blob/master/%E8%BF%90%E7%BB%B4%E5%AE%89%E5%85%A8.xmind

0×02 运维安全对抗发展


攻防对抗本身就是不平等的,防御是一个面,而攻击者只需要一个点。要防住同一level的攻击,需要投入的防御成本是巨大的。 在攻防对抗的各个level,高level的攻击手段是可以随意贯穿低level的防御层面。

救火

对于很多小公司(其实也包括很多大公司),对待安全漏洞的态度基本上都是遇到一个坑,填一个坑,这种纯“救火”的态度无法保障运维安全,只会像打地鼠一样,疲于奔命。

然而大部分公司都处在这个level——填坑救火(不救火的公司没有讨论的必要)。一方面是公司自身的安全意识不强;另一方面是小公司的安全资源配备有限。

漏网之鱼 VS 建设 + 运营

不同于小公司,一些大公司,特别是互联网公司,安全发展已经逐渐的从“救火”进入到“建设”的阶段。

从甲方的角度而言,这个过程是艰辛的,长久的。

在企业进入安全“建设”的阶段时,运维安全漏洞会呈指数级下降,一些常见和普通的问题不再出现。

这个时候,对抗点会集中在一些比较边缘的点。包括不常见的服务端口,依赖第三方服务的问题,又或者是一些合作方服务器安全漏洞等情况。

比如:

WooYun: 腾讯内部员工接私活导致某qq.com域服务器shell进入内网

WooYun: 腾讯某站配置不当可导致部分地区腾讯视频播放源损坏

通常情况下,造成这些安全问题并非是安全技术的缺陷,更多的是安全规范、标准流程覆盖不全的情况,如新业务三方业务收购的业务,运维体系还没有统一,运维安全建设没有及时跟上;即使在安全规范和流程覆盖完全的情况下,在具体的执行也会出现一系列问题。安全规范和标准流程越多,越容易出现执行上的问题。

这两类问题是建设时期比较典型的情况。很多时候,领导都会有这样的疑问,我们的规范、流程已经推到各个部门,看起来各个部门也按照标准执行了,为什么还会有这么多“漏网之鱼”?

于是如何主动的发现这些漏网之鱼也是一个急迫的需求。

这个时候需要安全运营的介入,安全运营在戴明环中扮演的量C/A的角色,定期check安全规范、流程标准的执行情况,然后推动安全问题的Fix,找到根本原因,一方面不断的完善规范和流程,另一方面不断的提升运维安全的覆盖面。

比较常见的就是安全扫描,通过定期扫描发现的问题,反推流程和规范的执行;当然,通过白帽子报告的漏洞,确定是流程和规范的原因后,进行反推也是一种有效的方式。

“新”漏洞 VS 预警 + 响应

天下武功,唯快不破

在运维安全提醒建设到相对完善的情况下,通常情况下,企业是相对安全的。但是,一旦有新漏洞的出现(在国内,有exp发布的漏洞往往就等于新漏洞),拼的就是响应速度。

一方面是需要安全运营对这些严重漏洞的快速预警;另一方面就是安全专家的技术功底了。在没有官方补丁发布的情况下,如何通过一些hack技巧进行防御也是非常重要的。

比如最近几年比较大的安全事件,如2013年7月17日的struts2漏洞,2014年4月7日的心血漏洞,就算是国内甲方最强安全团队BAT也是难于幸免。 这一level,甲方非常难做,唯一能保障的就是在中招后提示响应和修复的速度。

人 安全意识 VS 安全教育

在整个运维安全的对抗中,人这一块尤为重要,运维安全做的越好,这块越发重要。

安全规范和标准可以落实到各个部门,以流程的方式强制执行。但是运维人员安全意识的问题,很难进行控制。

最简单的就是弱口令,弱口令,弱口令!

各种系统的弱口令,各种后台的弱口令,各种服务的弱口令。这么多年了从来没有断过。

很多运维有些“坏”习惯。

比如直接在web目录进行web文件备份、nohup后台运行程序。这样会导致备份文件、程序执行的日志泄露;又或者随便开一个web服务下日志或者传数据,如python -m SimpleHTTPServer,这样就直接把目录映射到所有用户,如果是根目录,影响就更大了;当然,还有些运维喜欢把自动化脚本上传到git,脚本这东西,密码就在里面,一不小心就直接泄露了密码。

比如弱口令: WooYun: 百度某分站修改了弱口令还更弱(可shell可内网)

比如web服务开放问题: WooYun: 腾讯某服务配置不当导致包括数据库文件、密码hash等任意文件可下载

比如运维在Github泄露导致的安全问题: WooYun: 淘宝敏感信息泄漏可进入某重要后台(使用大量敏感功能和控制内部服务器)

0×03 参考


http://drops.wooyun.org/papers/410

 

 

 | 433 views | 0 comments | 0 flags | 

Jun 162015
 

http://blog.jobbole.com/87509/

 

本文是构建能够每秒处理 3 百万请求的高性能 Web 集群系列文章的第一篇。它记录了我使用负载生成器工具的一些经历,希望它能帮助每一个像我一样不得不使用这些工具的人节省时间。

负载生成器是一些生成用于测试的流量的程序。它们可以向你展示服务器在高负载的情况下的性能,以及让你能够找出服务器可能存在的问题。通过负载测试了解服务器的缺点,是测试服务器弹性以及未雨绸缪的好方法。

负载生成工具(Load-Generating Tools)

在进行负责测试时要牢记一件重要的事:你能在 Linux 上建立多少个 socket 连接。这个限制是硬编码在内核里的,最典型的就是临时 W 端口的限制。(在某种程度上)你可以在 /etc/sysctl.conf 里扩展它。但是基本上,一台 Linux 机器只能同时打开大约 64,000 个 socket 。因此在负载测试时,我们不得不通过在单一的连接上尽可能多地发出请求来充分利用 socket 。 除此之外,我们还需要不止一台的机器来产生负载。否则,负载生成器会把可用的 socket 占用导致不能产生足够的负载。

我一开始用的是‘ab’,Apache Bench 。它是我所知道的 http 基准测试工具中最简单、最通用的。并且它是 Apache 附带的产品,因此它可能已经存在于你的系统中。不幸的是,我在使用它的时候每秒大约只能生成 900 个请求。虽然我见过其他人使用它每秒能达到 2,000 个请求,但我可以立即告诉你,‘ab’并不适合我们的基准测试。

Httperf

接着,我尝试了 ‘httperf’。这个工具更强大,但是它依然相对简单并且功能有限。要算出每秒生产了多少个请求并不是仅传递参数那么简单。经过我的多次尝试,获取了每秒超过几百请求的结果。例如:

它以每秒 1,000 个的速率创建了 100,000 个会话(session)。每次会话发起 5 次请求,时间间隔为 2 秒。

1
httperf --hog --server=192.168.122.10 --wsess=100000,5,2 --rate 1000 --timeout 5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Total: connections 117557 requests 219121 replies 116697 test-duration 111.423 s
Connection rate: 1055.0 conn/s (0.9 ms/conn, <=1022 concurrent connections)
Connection time [ms]: min 0.3 avg 865.9 max 7912.5 median 459.5 stddev 993.1
Connection time [ms]: connect 31.1
Connection length [replies/conn]: 1.000
Request rate: 1966.6 req/s (0.5 ms/req)
Request size [B]: 91.0
Reply rate [replies/s]: min 59.4 avg 1060.3 max 1639.7 stddev 475.2 (22 samples)
Reply time [ms]: response 56.3 transfer 0.0
Reply size [B]: header 267.0 content 18.0 footer 0.0 (total 285.0)
Reply status: 1xx=0 2xx=116697 3xx=0 4xx=0 5xx=0
CPU time [s]: user 9.68 system 101.72 (user 8.7% system 91.3% total 100.0%)
Net I/O: 467.5 KB/s (3.8*10^6 bps)

最终,我使用这些设置达到了每秒 6,622 个连接:

1
httperf --hog --server 192.168.122.10 --num-conn 100000 --ra 20000 --timeout 5

(总共创建了 100,000 个连接,并且以每秒 20,000 个连接的固定速率创建)

它还有一些潜在的优势,并且拥有比‘ab‘更多的特性。但它不是我要用在这个项目里的重量级工具。我需要的是能够支持分布式多负载测试节点的工具。因此,我的下一个尝试是:Jmeter。

Apache Jmeter

这是一个功能齐全的 web 应用测试套件,它可以模拟真实用户的所有行为。你可以使用 Jmeter 的代理去访问你的网站,进行点击、登陆、模仿用户可以做的所有行为。Jemeter 会把这些行为记录下来作为测试用例。然后 Jmeter 会反复执行这些动作来模拟你想要的用户数量。尽管配置 Jmeter 比 ‘ab‘ 和 ’httperf‘ 复杂得多,但它是一个很有趣的工具!

根据我的测试,它每秒可以产生 14,000 个请求!这绝对是一个好的进展。

我使用了 Googlle Code project 上的一些插件,并且使用它们的“Stepping Threads”和“HTTP RAW”请求,最终每秒大约可以产生 30,000 个请求!但这已经达到极限了,所以还要寻找另一个工具。这里有一个我之前的 Jmeter 配置,希望可以帮助到其他人。虽然这个配置离完美相差甚远,但有时它可以满足你的要求。

Tsung: 重型的(heavy-duty)、分布式的、多协议测试工具

它每秒基本可以产生 40,000 个请求,这绝对是我们想要的工具。类似于 Jmeter,你可以把一些行为记录下来在测试时运行,并且可以测试大多数的协议。比如 SSL、HHTP、WebDAV、SOAP、PostgreSQL、MySQL、LDAP 和 Jabber/XMPP。与 Jmeter 不同的是,它没有让人感到迷茫的 GUI 设置,它仅有一个 XML 配置文件,和一些你选择的分布式节点的 SSH 密钥。它的简洁和效率对我的吸引力,完全不亚于它的健壮性和可扩展性。我发现它是一个很强大的工具,在正确的配置下它可以每秒产生百万级的 HTTP 请求。

除此之外,Tsung 还可以在 html 上产生图表以及输入你的测试的详细报告。测试的结果通俗易懂,并且你甚至可以把这些图片展示给你的 boss 看!

在这个系列文章的剩余部分,我还会讲解这个工具。现在你可以继续浏览下面的配置说明,或者直接跳到下一页。

在 CentOS 6.2 上安装 Tsung

首先,你要安装(Erlang 需要的) EPEL 源。因此,在进行下一步之前要把它安装好。安装完后,继续安装你用来产生负载的每个节点需要的包。如果你还没有在节点之间建立无密码 SSH 密钥(passwordless SSH key),那么请建立之。

1
yum -y install erlang perl perl-RRD-Simple.noarch perl-Log-Log4perl-RRDs.noarch gnuplot perl-Template-Toolkit firefox

从 Github 或者 Tsung 的官网上下载最新的 Tsung。

1
wget http://tsung.erlang-projects.org/dist/tsung-1.4.2.tar.gz

解压并且编译。

1
2
3
tar zxfv  tsung-1.4.2.tar.gz
cd tsung-1.4.2
./configure && make && make install

把示例配置复制到 ~/.tsung 目录里。这是 Tsung 的配置文件和日志文件的存放地方。

1
cp  /usr/share/doc/tsung/examples/http_simple.xml /root/.tsung/tsung.xml

你可以根据你的需求去编辑这个配置文件,或者使用我的配置文件。经过大量的尝试以及失败后,我目前的配置文件在使用 7 个分布式节点时可以每秒产生 5 百万个 HTTP 请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?xml version="1.0"?>
<!DOCTYPE tsung SYSTEM "/usr/share/tsung/tsung-1.0.dtd">
<tsung loglevel="notice" version="1.0">
<clients>
<client host="localhost" weight="1" cpu="10" maxusers="40000">
<ip value="192.168.122.2"/>
</client>
<client host="loadnode1" weight="1" cpu="9" maxusers="40000">
<ip value="192.168.122.2"/>
</client>
<client host="loadnode2" weight="1" maxusers="40000" cpu="8">
<ip value="192.168.122.3"/>
</client>
<client host="loadnode3" weight="1" maxusers="40000" cpu="9">
<ip value="192.168.122.21"/>
</client>
<client host="loadnode4" weight="1" maxusers="40000" cpu="9">
<ip value="192.168.122.11"/>
</client>
<client host="loadnode5" weight="1" maxusers="40000" cpu="9">
<ip value="192.168.122.12"/>
</client>
<client host="loadnode6" weight="1" maxusers="40000" cpu="9">
<ip value="192.168.122.13"/>
</client>
<client host="loadnode7" weight="1" maxusers="40000" cpu="9">
<ip value="192.168.122.14"/>
</client>
</clients>
<servers>
<server host="192.168.122.10" port="80" type="tcp"/>
</servers>
<load>
<arrivalphase phase="1" duration="10" unit="minute">
<users maxnumber="15000" arrivalrate="8" unit="second"/>
</arrivalphase>
<arrivalphase phase="2" duration="10" unit="minute">
<users maxnumber="15000" arrivalrate="8" unit="second"/>
</arrivalphase>
<arrivalphase phase="3" duration="30" unit="minute">
<users maxnumber="20000" arrivalrate="3" unit="second"/>
</arrivalphase>
</load>
<sessions>
<session probability="100" name="ab" type="ts_http">
<for from="1" to="10000000" var="i">
<request> <http url="/test.txt" method="GET" version="1.1"/> </request>
</for>
</session>
</sessions>
</tsung>

刚开始的时候有很多东西要理解,但你一旦理解了它们后就会变得很简单。

  • <client> 只是简单地指定了运行 Tsung 的主机。你可以指定 Tsung 使用的 IP 和 CPU 的最大数。你可以使用 maxusers 设置节点能够模拟的用户数量上限。每一个用户都会执行我们之后定义的操作。
  • <servers> 指定了你要测试的 HTTP 服务器。我们可以使用这个选项去测试一个 IP 集群,或者一个单一的服务器。
  • <load> 定义了我们的模拟用户将会在什么时候“到达”我们的网站。以及它们达到的有多快。
    •  <arrivalphase> 在持续了 10 分钟的第一个阶段里,以 每秒 8 个用户的速率到达了 15,000 个用户。
    • <arrivalphase phase=”1″ duration=”10″ unit=”minute”>
    • <users maxnumber=”15000″ arrivalrate=”8″ unit=”second”/>
    •  这里还有两个 arrivalphases,它们的用户都以同样的方式达到。
    •  这些 arrivalphases 一起组成了一个 <load>,它控制了我们可以每秒产生多少个请求。
  • <session> 这部分定义了一旦这些用户达到了你的网站,它们将会执行什么动作。
  • probability 允许你定义用户可能会做的随机事件。有时他们可能点击这里,有时他们可能点击那里。所有的Probability 加起来一定要等于 100% 。
  • 在上面的配置里,用户只做一件事,所以它的 probability 等于 100% 。
  • <for from=”1″ to=”10000000″ var=”i”> 这就是用户在 100% 的时间里做的事情。它们循环遍历 10,000,000 次并且 <request> 一个网页:/test.txt 。
  • 这个循环结构允许我们使用少量的用户连接去获取比较大的每秒请求数量。

一旦你已经很好地理解了它们,你就可以创建一个便利的别名,去快速观察 Tsung 报告。

1
2
vim ~/.bashrc
alias treport="/usr/lib/tsung/bin/tsung_stats.pl; firefox report.html"
1
source ~/.bashrc

然后启动 Tsung

1
2
3
[root@loadnode1 ~] tsung start
Starting Tsung
"Log directory is: /root/.tsung/log/20120421-1004"

结束后观察报告

1
2
cd /root/.tsung/log/20120421-1004
treport

使用 Tsung 去规划你的集群构造

现在我们拥有了一个足够强大的负载测试工具,我们可以规划余下的集群构造了:

1. 使用 Tsung 去测试一个单一的 HTTP 服务器。获取一个基本的基准。
2. 对 web 服务器进行调优,定期使用 Tsung 进行测试提高性能。
3. 对这些系统的 TCP 套接字进行调优,获取最佳的网络性能。再来一次,测试,测试,不停地测试。
4. 构造 LVS 集群,它包含了这些充分调优过的 web 服务器。
5. 使用 Tsung IP 集群对 LVS 进行压力测试。

在之后的两篇文章里,我将会向你展示如何使你的 web 服务器获取最高性能,以及怎样用 LVS 集群软件把它们整合起来。

 | 611 views | 0 comments | 0 flags | 

Jul 102014
 

http://blog.eood.cn/nginx_logs?weibo

Nginx 日志对于大部分人来说是个未被发掘的宝藏,总结之前做某日志分析系统的经验,和大家分享一下 Nginx 日志的纯手工分析方式。

Nginx 日志相关配置有 2 个地方:access_log 和 log_format 。

默认的格式:

access_log /data/logs/nginx-access.log;

log_format old '$remote_addr [$time_local] $status $request_time $body_bytes_sent '
'"$request" "$http_referer" "$http_user_agent"';

相信大部分用过 Nginx 的人对默认 Nginx 日志格式配置都很熟悉,对日志的内容也很熟悉。但是默认配置和格式虽然可读,但是难以计算。

Nginx 日志刷盘相关策略可配置:

比如,设置 buffer,buffer 满 32k 才刷盘;假如 buffer 不满 5s 钟强制刷盘的配置如下:

access_log /data/logs/nginx-access.log buffer=32k flush=5s;

这决定了是否实时看到日志以及日志对磁盘 IO 的影响。

Nginx 日志能够记录的变量还有很多没出现在默认配置中:

比如:

请求数据大小:$request_length
返回数据大小:$bytes_sent
请求耗时:$request_time
所用连接序号:$connection
当前连接发生请求数:$connection_requests

Nginx 的默认格式不可计算,需要想办法转换成可计算格式,比如用控制字符 ^A (Mac 下 ctrl+v ctrl+a 打出)分割每个字段。

log_format 的格式可以变成这样:

log_format new '$remote_addr^A$http_x_forwarded_for^A$host^A$time_local^A$status^A'
'$request_time^A$request_length^A$bytes_sent^A$http_referer^A$request^A$http_user_agent';

这样之后就通过常见的 Linux 命令行工具进行分析了:

  • 查找访问频率最高的 URL 和次数:cat access.log | awk -F ‘^A’ ‘{print $10}’ | sort | uniq -c
  • 查找当前日志文件 500 错误的访问:cat access.log | awk -F ‘^A’ ‘{if($5 == 500) print $0}’
  • 查找当前日志文件 500 错误的数量:cat access.log | awk -F ‘^A’ ‘{if($5 == 500) print $0}’ | wc -l
  • 查找某一分钟内 500 错误访问的数量:cat access.log | awk -F ‘^A’ ‘{if($5 == 500) print $0}’ | grep ’09:00’ | wc-l
  • 查找耗时超过 1s 的慢请求:tail -f access.log | awk -F ‘^A’ ‘{if($6>1) print $0}’
  • 假如只想查看某些位:tail -f access.log | awk -F ‘^A’ ‘{if($6>1) print $3″|”$4}’
  • 查找 502 错误最多的 URL:cat access.log | awk -F ‘^A’ ‘{if($5==502) print $11}’ | sort | uniq -c
  • 查找 200 空白页cat access.log | awk -F ‘^A’ ‘{if($5==200 && $8 < 100) print $3″|”$4″|”$11″|”$6}’
  • 查看实时日志数据流tail -f access.log | cat -e

    或者

    tail -f access.log | tr ‘^A’ ‘|’

总结

照着这个思路可以做很多其他分析,比如 UA 最多的访问;访问频率最高的 IP;请求耗时分析;请求返回包大小分析;等等。

这就是一个大型 Web 日志分析系统的原型,这样的格式也是非常方便进行后续大规模 batching 和 streaming 计算。

 | 1,936 views | 0 comments | 1 flags | 

May 272014
 

http://www.solagirl.net/find-icon-fonts.html

 

要找到一款适合自己用的Icon Fonts,首先要了解资源。本文列举了一下常见的icon fonts,并描述了icon fonts的特点,了解图标字体的特点能够帮助你在选择字体时有的放矢,选择适合自己的。

 

按照编码分类

  • 拉丁语编码(Latin encoding),用字母或单词代替图标,例如d表示日历图标
  • Unicode编码,例如fontawesome,用.fa-glass:before { content: "\f000";}表示酒杯图标

按应用方式分类

  • 直接写在html代码里,例如<span>d</span>表示日历图标
  • 用css插入图标编码,例如<i></i>,对应样式.fa-glass:before { content: "\f000";}
  • 将图标编码放到标签属性中,例如用data-属性:<span data-icon="&#xE001;" aria-hidden="true"></span>,再如ICONIC的用法<span title="icon name" aria-hidden="true"></span>

Chris Coyier写了一篇文章,总结了常用的Icon Fonts链接。

icon-collections

http://css-tricks.com/flat-icons-icon-fonts/

WE LOVE ICON FONTS

Google Webfont提供网络字体CDN,weloveiconfonts.com提供类似的服务,只是全部为图标字体。

welovewebfonts

http://weloveiconfonts.com/

Fontello

Fontello的特色在于可以定制自己的字体包,不仅可以上传自己的svg图形,还能将第三方Icon Fonts提供商的字体加进去,比如Font awesome,Entypo。

fontello

http://fontello.com/

ICOMATIC

icomatic的字体直接使用英文字母表示,而非常见的unicode。使用时语法如下所示:

1
2
3
<div class='icomatic icon'>alert</div>
<div class='icomatic icon'>arrowdown</div>
<div class='icomatic icon'>arrowleft</div>

用户既可以下载已经完成的网络字体包,也可以通过其APP创建自定义字体包。

icomatic

http://www.icomatic.io/

ICONIC OPEN

ICONIC的免费图标引用形式多种多样,不仅可以当做网络字体使用,也能直接引用svg或svg sprite。

iconic

https://useiconic.com/open

ICONIC PRO

Iconic的收费图标有一些十分有趣的特性,比如一个图标的不同部分可以使用不同颜色;图标可以根据屏幕尺寸大小改变样子,对小屏幕隐藏一些细节,大屏幕上则展现更丰富的细节。

iconic-pro

https://useiconic.com/tour/

Genericons

一款针对博客的免费网络图标字体,由WordPress的开发者Automattic提供,在WordPress默认主题中有用到。

genericons

http://genericons.com

 | 1,652 views | 0 comments | 0 flags | 

May 192014
 

http://www.csdn.net/article/2014-05-19/2819818-technical-details-programmer

【编者按】在网站发布前,开发者需要关注有许多的技术细节,比如接口设计、用户体验、安全性、Web标准、性能、SEO等,倘若一个疏忽就会影响到整体的体验效果。在Stackexchange上有人提出:作为一名Web开发者,哪些技术细节是需要考虑的?作者Hedgehog对该文进行了编译,这些资源有助于你了解一些关键技术,比如HTML、HTTP、XML、CSS、JavaScript、浏览器兼容性,减少网站加载时间的技巧、XML站点地图、W3C规范等。一起来看下:


 

问:对于一个Web开发人员来说,在发布一个站点之前,他需要处理哪些细节性的问题。假如Jeff Atwood能在站点上忽略了对HttpOnly cookies,sitemaps和cross-site request forgeries的关注,那我还能忽略些什么呢?

对于一个设计或提供站点内容的人来说,他们总认为站点的可用性及内容总比这个平台重要的多,当然在这个方面,Web开发人员没有什么话语权。对于一 个Web开发人员来说,其更多需要关注的是站点的稳定性,是否表现良好,安全性,是否满足了其他商业目标(例如花费不少太高,构建时间不少太长,在 Google提供的搜索结果中是否有个良好的排名)。

我们可以从这个角度上讨论这个问题:一个Web开发者在可信网络环境下做了些成成果,并且他打算将这个成果部署到当前这个糟糕的互联网环境上。另外,我也寻找一个更具体的答案而非一个模糊的”Web标准”,我的意思是已经了解了HTTP上的HTML、JavaScript、CSS技术,且认为你已经是一个专业的Web开发人员。那么,除此之外还有那些标准,在什么环境下使用?为什么?请提供一个链接到标准的规范。

答:以下大部分的观点也许大部分都已知悉,但是其中有少量的观点你获取从来没有看过,别担心,你不必全部理解他们,或许对你来说你永远也不需要了解到他们。

一、接口设计及用户体验

 

  • 你需要知道各种浏览器实现标准不一致,你需要保证你的站点在主流浏览器上能够良好运行。至少需要测试:基于Gecko引擎的浏览器(例如:Firefox),基于Webkit引擎的浏览器(例如Safari和其他一些手机浏览器),Chrome,IE及Opera。同时也需要考虑在不同的操作系统上,各种浏览器如何渲染你的站点。
  • 考虑你的站点将会被如何使用:是在手机端访问,PC上的浏览器访问,亦或是搜索引擎。
  • 在避免影响用户的情况下如何发布更新。是否有一个或者多个测试/临时以便在不打断站点访问的情况下进行架构、代码及内容的更新。是否有自动化的方式对在线站点进行发布。这些可以使用一套版本控制系统及自动化构建方式来有效实施。
  • 不允许向用户提示不友好的错误信息。
  • 不要以纯文本的方式提供出用户的email地址,因为他们会收到过多的垃圾邮件而死亡。
  • 在用户生成的链接上增加rel=”nofollow”属性,以避免垃圾邮件。
  • 对你的站点建立些限制,当然这应该是经过深思熟虑的-这也属于安全性范围。
  • 学习如何逐步提高站点功能。
  •  为避免重复提交,当POST成功执行后需要进行页面跳转。
  •  不要忘记考虑辅助功能。它总是一个好主意,且在某些情况下这是一个法律要求。 WAI-ARIA和WCAG2个在这方面的良好资源。
  • 不要让我想该如何进行操作。

 

二、安全性

 

  •  有很多需要阐述,但是OWASP开发指南中依据对Web站点安全性从头到脚进行了介绍。
  •  要了解注入特别是SQL注入,并学会如何避免他。
  •  永远不要相信用户的输入,也不是来自于请求别的(包括cookie和隐藏的表单字段值)。
  •  不要使用单独类似MD5或SHA加密策略,在进行散列密码值时,使用作料或多种作料以防止彩虹攻击。对于短密码,采用一个短散列算法处理,例如:bcrypt或scrypt。
  • 不要使用你想象中的身份认证系统,很容易得到一个微妙的错误和不可测试的问题,甚至你自己都不知道会怎么回事。
  • 了解处理信用卡规则。
  • 使用SSL/HTTPS处理任何敏感数据。
  • 防止会话劫持。
  • 避免跨站点脚本攻击。
  • 避免跨站点请求伪造。
  • 避免点击劫持。
  • 确保你的系统安装了最新的补丁。
  • 确保你的数据库连接信息是安全的。
  • 了解最新的攻击技术以免影响到你的平台。
  •  阅读谷歌安全手册。
  •  阅读web应用程序黑客手册。
  • 考虑最小权限的负责人机制。

 

三、性能

 

  • 如果有必要的话实现缓存策略。理解Http caching和html5 manifest并在合适的地方使用它们。
  • 优化图像-不要使用20 KB大小的图像做重复背景。
  • 了解如何gzip/deflate内容。
  • 合并/连接多个样式表或多个脚本文件,以减少浏览器连接的数量,并通过gzip来压缩多个文件中的重复内容。
  • 阅览雅虎卓越性能站点,其中包含大量很棒的指南,例如端到端的性能提升方法,YSlow工具。Goole page speed是是一个优化参考的好去处。
  • 使用CSS image sprite技术减少图片请求。(ps:前段时间用node-canvas做了个本地化的css-sprite工具,有需要的可以找我拿源码^_^)。
  • 访问量大的站点可以将内容划分到多个域下,但不要超过4个域。
  • 静态内容(例如图片,css文件,js文件及一些静态文本)应该存放在一个单独的域下面,并且不能使用cokies,因为在每次请求时,都会将cookies带上。CDN(内容分发网络)是一个不错的选择。
  • 减少一个浏览器页面上发起的http请求数量。
  • 使用JavaScript文件压缩技术。
  •  确保在站点的根目录下有一个favicon.ico文件,即使该文件未被任何使用,流量器也会自动加载它。如果没有这个文件的话,将会导致大量的404错误,从而占用你的服务器带宽。

 

四、SEO(搜索引擎优化)

 

  • 使用搜索引擎友好的的url,例如:使用example.com/pages/45-article-title 而非example.com/index.php?page=45
  • 当使用#动态内容更改#到#!然后在服务器$_REQUEST[“_escaped_fragment_”]是什么Googlebot使用,而不是#!换句话说,#!页= 1/变成/?_escaped_fragments_=页= 1。此外,对于可能使用FF.b4或铬,history.pushState用户({“foo”的:“酒吧”}“。?/页=1”,“关于”,);是一个伟大的命令。因此,即使在地址栏改变了页面不会重新加载。这使您可以使用?而不是#!保持动态内容,并告诉服务器当您发送电子邮件,我们是这个页面后的链接,以及AJAX并不需要再作额外的要求。(Google翻译,没有完全理解…)
  • 不要使用”click here”这样的链接,这样会浪费SEO的机会并且也会让人更加难以理解。
  • 要有一个XML站点地图,最好是在默认位置/sitemap.xml的。
  • 当你有两个指向不同的地址,可以使用<link rel=”canonical”…/>,这个问题也可以从谷歌网站管理员
  • 使用Google Webmaster Tools 和 Bing Webmaster Tools.
  • 使用Google Analytics。
  • 了解机器人搜寻算法和搜索引擎爬虫的工作方式。
  • 重定向请求(使用301永久移动)要求www.example.com到example.com(或者反过来),以防止分裂谷歌两个网站之间的排名。
  • 你还要知道还有很多恶心的爬虫程序运作在网络上。(以前在做一个百科词条整理时,对某网站的词条进行了深度遍历,但程序运行不久IP就被封杀了。)

 

五、技术点

 

  • 理解HTTP协议,例如:GET,POST,Session,Cookies以及“无状态”的含义。
  • 根据W3C规范写你的XHTML/ HTML和CSS,并确保他们通过验证。这是为了避免浏览器的使用非标准的浏览器,如屏幕读取器和移动设备的正常工作。
  • 了解JavaScript在浏览器中的运行机制。
  • 理解JavaScript、css及其他资源在页面上是如何被加载的,并考虑他们对性能的影响。现在普遍接受将脚本放在应用程序或html5底部执行。
  • 了解JavaScript沙箱的工作原理,特别是如果你打算使用iframe。
  • 你要注意到JavaScript是可以被禁止的,并且AJAX是一个拓展而非基线。很多普通用户已经离开了它,NoScript越来越受欢迎,移动设备或许不会像你想象的那样运行,谷歌将无法运行大部分的的JavaScript。(不解,noscript标签是定义在未能执行js时的输出,当是当前js横行的时代,真的还有很多用户禁用js吗???)
  • 理解重定向301和302的区别。(这也是SEO中的一项)
  • 尽可能深入了解你的开发环境。
  • 考虑使用Reset CSS或Normalize.css。
  • 考虑JavaScript框架(如jQuery,MooTools,Prototype,Dojo或YUI3),这将使用JavaScript进行DOM操作时,隐藏了很多的浏览器差异。
  • 考虑到JS框架及性能,可以使用一个服务,如谷歌库API来加载框架,使浏览器可以使用它已经缓存,而不是从你的网站下载一个副本的框架副本。(CDN)
  • 不要重复造轮子。做任何事情之前先搜索关于如何做到这一点的组件或例子。有99%的可能性有人已经做到了和发布了一个开源版本的代码。
  • 在明确你的需求之前,不要使用20个库去堆砌功能。特别是在客户端访问,其最重要的就是让事情轻便、快速和灵活。

 

六、Bug修复

 

  • 你要知道你将要花费80%的时间去维护你20%时间写的代码,所以编码时请仔细。
  • 建立一个良好的错误报告解决方案。
  • 有一个能让大家提供建议或提出批评的系统。
  • 将未来支持的功能及维护人员记录在文档中。
  • 频繁的备份! (并且确保这些备份是功能性)埃德·卢卡斯的回答有一些忠告。有一个恢复策略,而不只是一个备份策略。
  • 有一个版本控制系统来存放文件,例如Subversion,Mercurial或Git。
  • 不要忘记做些验收测试,类似Selenium框架可以提供方便。
  • 请确保您有足够的日志记录在案,例如使用框架log4j,log4net或log4r。如果你的网站发生了错误,你要知道发生了什么事情。
  • 当登录时请务必同时捕获处理异常和未处理的异常。报告/分析日志的输出,因为它会告诉你网站中的关键问题。

很多知识都省略了,并不是因为他们不是有用的答案,而是它们要么过于详细,要么超出了范围,亦或对某些人来说过于深入。大家应该知道这知识概述,请随意畅谈,因为我可能错过了一些东西或者也犯了一些错误。

 

推荐阅读:

 

 

译文出自:Cnblog

 | 666 views | 0 comments | 0 flags | 

May 042014
 

http://bpdevel.wordpress.com/2014/02/21/user-last_activity-data-and-buddypress-2-0/

BuddyPress uses ‘last_activity’ data extensively: for display purposes (‘last active 3 days ago’), to sort results, and to determine whether a WP user is a valid site member. At the same time, ‘last_activity’ has been a perennial performance bottleneck. In the case of users, the information was stored in wp_usermeta. This table gets exceptionally bloated on busy sites, and it’s not properly indexed for the sorts of ORDER BY queries we were performing on it. See #5128 for more background.

A fix for this longtime issue is in place for BuddyPress 2.0. (See r7860.) Short version: user last_activity data is now stored in a ‘last_activity’ row in the wp_bp_activity table. We’ve modified our core queries to take advantage of the new location. And we’ve done a bit of trickery to make sure that the wp_bp_activity table is available for storage, even if the Activity component is disabled. The performance improvements are pretty extreme; I’ll post benchmarks as we near 2.0′s release.

Plugin developers who use user ‘last_activity’ data are urged to account for the new schema. In the past, you may have accessed user last_activity like this:

update_user_meta( $user_id, 'last_activity', $time );
$last_activity = get_user_meta( $user_id, 'last_activity', true );

You are urged to use our API functions instead:

bp_update_user_last_activity( $user_id, $time );
$last_activity = bp_get_user_last_activity( $user_id );

In cases where you are making direct database queries based on this info, please consider using BP_User_Queryinstead. At the very least, you should refactor your queries to use the new schema.

For the time being, ‘last_activity’ data will continue to be mirrored in wp_usermeta, so your plugins will continue to work. However, you’ll get deprecated notices every time you use the _user_meta() functions to access the information. And hey, the new way performs much better, so you’ll want to update anyway.

Here’s a list of the plugins I found in the wordpress.org plugin repo that will need updating:

  • bp-group-control
  • bp-default-data
  • welcome-pack
  • activate-users-in-buddypress
  • bp-groups-suggestions
  • hts-display-active-members
  • bp-member-widget
  • buddypress-community-stats
  • buddypress-sitemap-generator
  • bp-ninja

Questions regarding this change? Need help migrating your code? Please leave a comment below.

(A quick note regarding ‘last_activity’ for groups and blogs. The basic problem there is the same as for users, but the scaling issues are much less severe, so they have not been touched for now. Keep an eye out for relevant updates.)

#2-0#last_activity

 | 2,129 views | 0 comments | 0 flags | 

May 032014
 

 

DNS预获取(dns-prefetch)

http://blog.webfuns.net/archives/1357.html

 

今天翻看twitter的源码的时候看到了一下内容:

<link rel=”dns-prefetch” href=”http://a0.twimg.com”/>

<link rel=”dns-prefetch” href=”http://a1.twimg.com”/>

<link rel=”dns-prefetch” href=”http://a2.twimg.com”/>

<link rel=”dns-prefetch” href=”http://a3.twimg.com”/>

<link rel=”dns-prefetch” href=”http://api.twitter.com”/>

查阅了相关资料,知道DNS Prefetch也就是DNS预获取,也是前段优化的一部分。在前段优化中关于DNS的有两点:一是减少DNS的请求次数,第二个就是进行DNS预先获取。

DNS Prefetch 已经被下面的浏览器支持

  • Firefox: 3.5+
  • Chrome: Supported
  • Safari 5+
  • Opera: Unknown
  • IE: 9 (called “Pre-resolution” on blogs.msdn.com)

默认情况下浏览器会对页面中和当前域名(正在浏览网页的域名)不在同一个域的域名进行预获取,并且缓存结果,这就是隐式的DNS Prefetch。如果想对页面中没有出现的域进行预获取,那么就要使用显示的DNS Prefetch了,也就是使用link标签:

<link rel=”dns-prefetch” href=”http://api.twitter.com”/>

DNS Prefetch应该尽量的放在网页的前面,推荐放在<meta charset=”/>后面。

PS:可以通过下面的标签禁止隐式的DNS Prefetch。
<meta http-equiv=”x-dns-prefetch-control” content=”off”>

内容整理自:DNS-Prefetching

参考:
网站优化应重视 DNS 预获取(DNS Prefetching)

 | 1,079 views | 0 comments | 0 flags |