求高手给我说说stl应该stl怎么玩玩

霍炬的网络日志 | huoju's blog
March 23, 2011
这几天在twitter上说到不少ruby到底好不好的事情,总结一下,写了这个blog。
今年年初开始我打算深入体验一下ruby on rails,对我来说,已经很多年没有接触"新语言"了。在这个深入体验开始之前的几年,也有若干次浅尝辄止,基本都是玩了几下,觉得要学的东西真多,用PHP顺手写一个也很简单嘛,就放弃了。
但我想一个东西迅速风靡世界一定是有原因的,就算我最终不去真正使用它,弄清楚背后的原因也是值得的。于是我就放下了老程序员的心态,像一个初学者一样从最基本的文档看起,尝试各种大家称赞的项目,搞不懂的地方就去问熟悉ruby的人,不仅问如何实现,还要问"为什么会这样","过去什么样","其他语言解决某个问题的方法在这里如何对应"。几个月下来,虽然我还没能用ror真正开发一个完全独立的项目,但总算是有了一个全貌的概括性了解,也知道了历史和文化,体会了社区的氛围。这个时候,我想大概是可以对rails发表一些评论了。
在这一次尝试之前,我最担心的事情是"性能问题",现在看来这是一个伪问题,首先ruby的性能并没有这么差(前几年确实不太好,不过现在已经很好了),其次,用来做一个网站应用,无论是什么语言,最后都要依靠缓存和分布来解决,也就是说最终都要依赖于正确的系统架构,而不是语言本身的性能,最后,就算是性能真的差又完全不可解决的问题,完全可以用效率更高的语言来写,把处理的结果通过各种通讯方式交给ruby就是了。在计算机硬件发展到今天这样,性能问题大多不存在,只有架构师水平的差距。我见过很多用了几十台机器的系统但抗不住几十万的负载,这能怪语言和平台本身的性能差吗?
在所有关于ruby优点中,我唯一不能认同的是"学习曲线平缓",事实上,ruby的学习难度比较高,确实远远高于PHP,要说平缓,大概是相对于J2EE的平缓。我相信这是很多对ruby误解和攻击的来源,从表面上看起来,要学会ruby尤其是ror,至少需要理解设计模式,知道服务器系统的运作方式,甚至需要熟悉操作系统,要用好ror,更需要接触各种项目和各种标准,这些都需要花去很多学习时间。同时配合的还有各种测试工具,部署工具,虽然不是必须,但最终还是要学的(这里我还欠缺很多呢)。我曾经开玩笑说ruby社区的人破坏了英语的纯粹性,因为他们fork新项目太容易,大家都喜欢创造各种开源项目,直接符合功能的名字都被用光了,于是只好用各种奇怪的相关的英语单词,以至于搜索很多英文单词竟然会找出来ruby的项目。这些东西直接塞给一个初学者确实有很大的压力。ruby on rails的Getting start又太停留在表面,勉强算是尝鲜,距离真正实用差的太远。相对来说,PHP就简单多了,页面直观对应在PHP文件上,什么都不用懂也能写(当然写好也很不容易),这造成的结果就是谁都可以懂PHP,但不是谁都能懂ruby。人们为了掩盖学习的痛苦,就容易去攻击对方无用。在我这次下决心深入学习之前,我也觉得PHP最好,记得之前某次尝试的时候 @rainux 跟我说,刚刚上手是很难感觉到ror的好处,需要持续用一段时间才会慢慢发现。
ror在架构和开发流程管理也坚定的支持了很多理论,比如MVC,比如敏捷,比如TDD...这些同样增加了学习成本,当然也增加了被攻击的接口,比如:TDD太扯淡了,所以ror也扯淡。或者:我最讨厌敏捷了,所以也讨厌ror。实际上,敏捷和TDD本身都没错,他们都有成熟的方法论和实践,有足够好的工具配合,能解决很多问题。如果不认同这个,只能说是开发和项目管理经验太少,没碰上过复杂问题。有错的是对敏捷和TDD的错误鼓吹,两者不能混在一起。
另外一个常见说法是寻找ruby的大流量项目案例。但其实寻找ruby开发的"top项目"没意义。DHH和37s创造的都不是适合所有人的产品,他们只愿意在某一领域做到最好。不是所有人都有兴趣创造亿级别产品,何况也没几个人真能做成。对大部分项目,千万是一个很好的级别,那是ror最佳实践领域,而在现实中,大部分项目能做到100万pv,已经算了不起了,想亿级别pv的技术方案未免过早了。
在组织技术团队的问题上,流行语言的难度是差不多的,10个人的团队任何语言都很容易组织起来,但换个角度看,任何语言也很不容易组织10个人的团队,只不过难的方法不一样。A语言可能是找人难,一周就收到1份简历,B语言可能是鉴别难,一天收到200份简历,看都看不过来。其实最难的事情是组织一个10个人的靠谱团队,这个团队用什么语言相对于寻找10个靠谱的人的难度可以忽略不计。
选择一个语言,并不是选择语言本身,同时也是选择社区。ruby社区的活力,友好,规整,统一的审美,给我留下了非常深刻的印象。DHH和37s对这个社区影响巨大,我也相信他们的理念,小公司未必不好,小公司未必不伟大,追求pv不如追求极致的产品。我们创造一个产品,是为了解决一类人的问题,并不是为了超越谁或和谁竞争。
15年前,PHP 3.0之前的版本完全不可用(当然,那时候PHP的简称还叫做Personal Home Page),那时候用c写cgi/isapi或者用perl是网站最常见的开发形式。那时候说PHP是下一代语言,很多程序员都会不同意,他们会挑出来PHP一万个不如c或者不如perl的地方。这些都没错,但世界是会变化的。PHP今天确实成了一种应用广泛,老幼皆宜的语言。我并不认为未来ruby会取代PHP,但至少,我认为下一代高质量的互联网产品出现在ruby社区的机会更大,这就像当年PHP vs perl一样,乃大势所趋。
最后我说一句可能不太好听的话,如果你没有下决心转型成为一个写信教主那样的专门忽悠的人,如果你还觉得技术有点意思,还想自己创造点产品,那么应该保持足够的技术敏感力,认真的学习一些新东西,而不是给自己寻找各种借口。就像
一样。要多问问自己,是这东西真的不好,还是自己学不进去了?当然,承认后者是很难的。一年前我也确实没学进去。
我学ruby的过程中,很多朋友提供过不少帮助,没有他们的回答和blog,估计会学的更难。在此一并感谢: @rainux @robinlu @moming2k @Anxonli @soulhacker
Posted by virushuo at
3:25 PM
July 17, 2010
提供了一系列方便的函数,可以很容易的把文本绘制在屏幕上,对于一个Frame来说,一般并不需要担心文本的排列问题,这些Core Text的函数都可以直接搞定,只要给他一个大小合适的CGRect就可以。
但,在某些情况下,我们还希望知道这段文本在绘制之后,对应绘制的字体字号设置,在屏幕上实际占用了多大面积。举例来说,有文本段落a,屏幕大小rect,通常做法是以rect创建path,然后创建CTFramesetter,再然后创建CTFrame,最后用CTFrameDraw画出来,这时候,往往文本段落占用的实际面积会小于rect,这时候就有必要获得这段文本所占用的真正面积。
最理想的情况是使用
double CTLineGetTypographicBounds( CTLineRef line, CGFloat* ascent, CGFloat* descent, CGFloat* leading );
这是Core Text提供的函数,传入CTLine,就会得到这一行的ascent,descent和leading,在OSX上通常可以工作的很好,但是在iOS(iPhone/iPad)上这个函数的结果略有不同。
正常情况下,计算行高只需要ascent+descent+leading即可。在这个略有不同的情况下,leading的值会出现偏差,导致算出来的结果是错误的。如果不管行距,ascent+descent计算出来的Glyph的高度还是正确的。
这样就有了第一步
在创建用于绘图的CFAttributedStringRef时,除了设置字体,多设置一个CTParagraphStyleRef,其中特别应该确定行距kCTParagraphStyleSpecifierLineSpacing。在计算这里时,先逐行计算ascent+descent,累加起来,再加上一个行数*之前设置好的行距,这样算出来的就是这些文本的实际高度,CTLineGetTypographicBounds返回的结果是宽度,这样就可得到文本实际填充面积的Rect了。
但是这还是有问题,因为OSX上和iOS处理不同,所以事实上iOS的模拟器和真机的最终效果是不一样的,这样调试程序很麻烦。
于是还需要第二步
在最终往页面上绘制的时候,不再用CTFrameDraw来一次绘制全部,而是使用CTLineDraw逐行画,在画之前,先用CGContextSetTextPosition来设置好每行文本的位置。这样就保证了在任何平台上绘制效果一致。
问题就解决了。
CoreText在OS X和iOS上实现有很多细节区别,比如说,对CTRun的划分方式也不一样,在iOS上划分出来的Run数量比OSX上少很多,是按照字体划分的Run,按照文档出来,这是正确的,但OSX上是一个字一个Run这样划分的,和文档不符。iOS上的处理显然效率更好。
stackoverflow 上有一个
,不过没考虑到iOS的区别
Posted by virushuo at
3:32 AM
1, 2010
今天我在twitter上说我的QQ一年都用不了几次,不如卖掉。
说他做生意比较需要短点的QQ号,因为在twitter上有了不少了解,我就干脆送给他了。晚上回来给了他相关信息。这时候发生了好玩的事情,竟然有人为了得到这个QQ号,想通过"社会工程学"的方法钓鱼。我虽然不会上当,但是觉得具有一定欺骗性,所以分享出来,提醒大家注意。
邮件很短,截图在此
1. 图中这个邮箱注册的不错。有一定欺骗性。在此也提醒大家,这不是 @co eta 的邮箱。要识别是不是常用邮箱,有一个快捷的方法,就是用google搜索一下,看看以前的活动记录。如果没有活动记录,一般是刚刚注册的。
以往的活动记录,在互联网上相当于信用卡账单,这也是我一直劝大家不要太注意所谓隐私的原因之一。你需要给自己留下信用记录,以便别人查对。知道 @co eta 真正的邮箱的朋友也可以搜索一下,看看有多少结果。
google一下看活动记录,这个办法甚至可以应对精心搭建的带有反向解析域名相似的邮件服务器(可称为官方钓鱼)。是简单而有效的办法。
当然也有推友提到自己因为防止垃圾邮件,保护的很好,以致于没有任何搜索结果,这种情况是比较特殊的,可以通过其他方法验证,我下面也会提到。
2 注意前面的co eta co eta,他确实设置了用户名,但正常人是不会这样写名字的。肯定是姓名的形式,就算用昵称,也很少有人重复两遍。碰上这种情况,至少应该注意提高警惕了。这不正常。
3 注意判断对方书写习惯。这封邮件在这方面也略显粗糙。比如 @co eta 虽然在成都,但说话利索,很少在后面加"咯"这样的语气词。他的标点都是全角,一般不出现半角。这是由输入法的习惯和键盘布局决定的,也是类似指纹的标记,如果不换机器或输入法,通常不会有太大变化。
4 还有一些其他细节线索可以判断一个邮件是否是钓鱼。这方面大家可慢慢思考,不多说。而我们需要做到的原则是,不要在不能确认身份的情况下说重要的东西。
确认身份的方法包括但不限于:和对方谈一些细节问题,比如谈谈@co eta的具体业务,看看对方是否知道。我今天和@co eta第一次直接聊天的时候,也聊了不少话。这些对话都可以从细节中确认对方身份。
当然,如果能打个***问一下,可能会更容易点。对方的声音和说话习惯,是更难伪造的。在***中多说几句,还可以注意到对方所处环境,是否局促,是否紧张,是否反应速度慢,这些迹象都代表了有异常发生,要特别注意。
最好的方法还是双方都使用OTR签名,这是判断身份和保护信息安全的重要手段,虽然麻烦,但非常有效。当然送个QQ号这种小事就不用麻烦 @co eta 专门装个OTR了,我通过对话已经能确认他的身份了。具体做法很多,可以以此为基础,推导出来更多的办法。
一个基本的原则是,要至少通过两个渠道来确认。比如 在twitter上dm一下,然后在gtalk上说一下,在网上说一下,***说一下。让不同渠道说的内容相关,这样就可以确认出两边是否是一个人。这个思路可以举一反三。
总结一下必须具备的意识: 1 理解重要信息可能被泄露,必须具有安全意识 2 保证安全是繁琐的,但很重要。所以请用多种渠道确认对方身份,这是最基本的一步。 这两点非常基本,但是如果可以深刻理解,确实可以解决很多问题。
技巧说完了,我总结一下教训: twitter上坏人还是存在的,一个QQ号都值得这样做。其他的信息想必也有各种人,出于不同的目的而感兴趣。所以,用不明来源的第三方上推的推友,请记得改密码,没准你的密码早被存下了。我非常非常非常相信,有人曾经用某个第三方或是某个api收集了大量twitter帐号的密码和信息,在某些时候会使用的。
安全意识必须常常记在心中,在关键问题上谨慎对待。注意,邮箱地址是可以伪造的,gmail难一些,但仍然有可能伪造。所以千万注意分寸,什么东西会让你丢钱,什么东西会让你送命。考虑好后果,做事就会谨慎。
有一些不让人反感的确认信息小办法,可以分享。比如我要给别人汇款,对方短信过来一个帐号,怎么确认呢?礼貌起见,可以跟对方说:麻烦您能把具体金额再给我确认一下吗?对方如果能发出来细目,一般就差不多。第一次联系的人可以当作寒暄说一些往事,等等。
一般来说,安全是非常难达到的目标,我们可以默认自己的行为是不安全的,然后通过一系列的手段来降低不安全的概率,最终达到一个比较好的平衡。本文列出的是一些简单,易于实施的办法。深刻理解这些原则,未必可以保证绝对安全,但至少可以应付大部分麻烦。
Posted by virushuo at 12:06 AM
December 27, 2009
这是一个用于文本加密的库,主要用于http协议下的防窃听。一般来说,如果应用htt 协议可以有效的避免窃听。但有几种情况必须考虑。
(1) 主机同时有htt 和http协议,部分用户通过htt 协议访问,获得了保护。但也有用户通过http访问,这部分用户会遭到窃听。除非关闭http请求,全面转向htt 。
(2) 主机并没有htt 支持。
很多情况下,我们需要保证主机安全,最好的办法是将其混入数字森林中。即:这台主机输出的内容没有人能看得懂的,只由无意义的代码和数字组成。用户浏览这台主机,不会触发任何关键词扫描。甚至该主机连htt 协议都不使用,更凸显其低调本色。
换言之,一个网站如果把自己的内容都变成字母和数字的组合,且不使用htt 协议,那么他就是数字森林中的一片树叶,丝毫不引人注意。
我们的目标应该是传输过程中不引人注意,并非绝对的不可破解的安全。
因此这个库的工作流程是:
1 php对"内容"做rsa加密->将加密结果输出到页面上。
2 用户浏览页面,html代码中的"内容"被加密成数字形态。私钥可以直接输出在页面代码中,也可由用户输入一次,保存在cookie中。使用cookie会降低密钥泄露的危险,更加有效。
3 通过javascript在用户浏览器上将这些数字解密为内容。
4 通过javascript dom来把内容写回到页面上。用户即可浏览。
利用javascript解密,可以把运算负担分散到客户端上。窃听者如要窃听每一个页面的内容,则必须要 1 获得密钥 2 用密钥解密内容
在已知密钥情况下,如客户端的每个页面运算负担为 1 ,页面数量n ,那么窃听者获得密钥之后的运算负担为 1*n。
为了运算效率,使用小质数作为rsa的p,q,理论上窃听者可以通过因数***算出密钥,其运算负载为k,注意k 远远大于1。
如果每个站点使用不同的密钥,共计m个站点,窃听者的运算负担为 m*k+1*n,且负载集中。
而,如果采用双向可逆加密方法,在得知算法的情况下,窃听者运算负载极小。如果在通过变换算法来增加难度,又无法做到通用,给用户正常浏览造成困难。使用rsa方法,算法是标准的,用户使用成本很低,窃听成本很高。
在项目代码中,我已经实现了这一目标。但仍然有效率问题。
目前问题:
1 在没有bcmath和gnumath函数的php主机上,php加密内容的运算效率很低。和bcmath差距几十倍。好在大部分情况下,主机都是有bcmath函数的。这个问题不严重。
2 JS的bigint运算效率很低,主要是powmod的效率低,而这是rsa解密最频繁的操作。
希望有兴趣的朋友加入这个项目。效率问题解决后,还需要port在一系列常用软件上。比如dabr或twitese等。
另外,需要的质数可以在
我放了一个demo在:
可以看html代码,里面是没有中文内容的。
update: 使用了
的大数运算库,效率提高很多。
Posted by virushuo at
6:56 PM
August 28, 2009
如前所述,这次活动我分享了银杏搜索在使用 mp监控方面的一些经验和演变过程。其实起初我认为这是一个相当冷僻的话题,没多少人会有类似的需求或是兴趣。没想到的是还是有很多同学说有用,也在沙龙上碰到了一些正好也在做这方面开发的朋友。非常令人欣慰。
总体来说,这个方案还是有很大的局限性。局限性首先来源于我们的服务特性,可以说是为了解决特殊问题的特殊方案。其次,还有很多地方不完善,仍然需要在应用中进一步完善。 t放在这里了:
View more
另外做个广告,
即将召开,含金量颇高。有兴趣参加的,可联系 agilechina@cn.infoq.com 购票,说是我介绍来的可以有100块钱优惠 :D
Posted by virushuo at
3:11 PM
July 27, 2009
题外话:有人问我,这么极端的安全有用吗? 我的回答是:对某些人没用,对某些人有用,对另外一些人可以救命。
前文:
,是关于计算机安全方面的内容
Version: 1.0b virushuo (twitter@virushuo) 20090727
注意:
1 这不是一份完整的安全手册,只是一些知识参考。但他能帮助你了解那些最重要的细节。如果有发现相关部分好的文档和教程,请提供给我,我连接上。
2 本文主要用于商业安全和个人隐私安全(包括你的私人照片,银行账号等的安全),本文不鼓励将这种技巧用于其他用途,使用在其他用途造成的损失和后果与本文无关,正如用菜刀杀人与磨刀的老大爷无关。
3 本人并非专业研究计算机和网络安全。只是觉得略有所知,所以分享一些常识。如有专业人士认为有错漏,请不吝赐教。virushuo( attt ) gmail.com
4 Geek的选择,
恭喜你成为本年度收获明信片最多的人
6 本文会时常修补增加内容,要转载请务必注明出处和以上注意事项。
账号安全和如何选择安全的服务
使用互联网,就是在使用各种服务。对于大部分服务来说,账号是唯一用来识别你的方式。账号安全不仅关系到你的在线数据安全,还关系到你的身份。如果对方盗用了你的账号,就很容易利用信任关系,从你的朋友手里盗走更多的东西,并且危害你朋友的安全。这不仅在计算机安全上成立,在现实中也比比皆是,比如如果你的手机落到别人手中,对方也有可能利用你的手机给你家人打***说你出了车祸,急需手术费用等方式骗钱。在互联网上,不加密的情况下,你并不能知道那个熟悉的账号后面是你的朋友还是江洋大盗。所以,不仅为了你自己,为了你和朋友们的安全,请保护好你的账号。
安全的服务至少应该提供可选的htt 连接方式和一个足够复杂的验证码。来看看gmail和国内比较常用的新浪,163邮箱的对比吧。
1 复杂的验证码
一个足够安全的验证码至少要包含以下特征:
要有横向和纵向的随机扭曲
位置和大小要随机变化
验证码长度要随机变化
内容应该是字母的而不仅仅是数字
字体要有随机的变化
最好再有足够的干扰图案和条纹
目前看来,能符合以上大部分特征的服务,只有google,yahoo和m 这3家。这样的验证码在目前的情况下OCR出结果的成功率非常低,这样对于防止暴力破解相当有效。换句话说,如果有人想猜测你的密码,如果想解开如此复杂的验证码,只让计算机替他一个个试验是不行的,必须还需要有个真正的人来帮他做识别。这样就让破解的速度大大下降,成本大大上升,距离安全就更近了一步。
图0:看看google的验证码,其实有时候人来辨别也有一定困难。
国内常用的服务商中,sina和163的验证码也算安全,虽然距离gmail尚有较大距离。第二梯队的网站的验证码通常极不安全。
图1:163的中文验证码,其实也并不是很难处理。OCR(图像识别)软件要处理的情况通常比这个更复杂。
看看tom的,是不是觉得惨不忍睹?这种水平的验证码OCR的成功率轻松就可以达到100%,事实上和不存在是一样的。交***来拍违章车牌的系统,要处理的情况都要比这个复杂吧?识别率不一样在98%以上?
图2:Tom的验证码,不堪一击
2 进行安全登录
常用google的同学会发现,当你登录google账号的时候,地址栏上的http会自动切换到htt 。也就是说,google是强制使用htt 方式进行登录的。进行登录的时候,需要把用户输入的用户名和密码发送给服务器,验证用户身份。如果是普通的http方式,所有传输的数据都是明文发送的,包括刚才输入的账号和密码,这种明文信息是非常容易被截获的,数据包所经过的任何一个节点都可以轻松获取,和你在同一个局域网的用户也有可能利用arp欺骗等方式获得这些数据。想想看,你在路边急需上网,突然发现了一个可用的无线连接,是不是很高兴?这时候,如果通过http登录了邮箱,账号就可能被泄露了。所以,强制使用htt 的方式进行登录,是非常必要的安全措施。google和yahoo都已经是这样的方式了。
同样看看163和sina吧。163是可选 l的,默认是选中,勉强算合格。sina也可选 l,但默认是不选中,高下立现。至于tom,似乎那个"增强安全性"被选中之后也不会通过htt 登录...
图3:sina免费邮箱,"增强安全性"默认是不选中的
3 日志功能
日志可以帮助你了解是否你的邮箱被入侵过。遗憾的是,目前应该只有gmail具有这个功能。把页面拖到gmail邮箱的最下面,可以看到 Last account activity: 1 minute ago at this IP 字样,这里给出了最后一次账号活动的时间和ip。
图4:gmail页面尾部有log功能
按一下Detail,信息更完整,最近的所有访问都有记录,包括IMAP方式,POP方式,WEB方式,一个也会少。有这个功能,可以很容易的知道是否有别人使用过你的邮箱。有人入侵就会留下时间和IP。这些记录是不可被抹掉的,除非入侵google的服务器。这可不是件容易的事。
图5:gmail的活动报告
鉴于以上原因,
我强烈建议使用gmail作为你的主要邮箱
,这是目前互联网上能找到的安全性最高的服务了。甚至我认为一个有理智的入侵者不应该来打你gmail的主意,因为他们很难成功,即使成功也很难不留下痕迹。
经过以上分析可以发现,除了大的服务商,google/yahoo/m ,包括163/sina..,大部分网站是不提供htt 方式的登录的。所以,至少应该让你的账号分为2组,不要把普通论坛之类的账号和邮箱账号的用户名密码相同。
update:从留言等反馈中看来,很多朋友推荐QQMail,据说也符合以上特征,不过我没用过,也不好评价。在这些指标上可能没问题,不过根据目前大量QQ群聊天纪录轻松被某些部门拿到手的情况看来,就算指标上没问题,实际应用效果恐怕也要打折扣。所以,还请结合用途,自行判断。
用***来验证对方的身份
,通常是伪造一个网站,诱骗用户输入一些类似账号密码的信息。这就产生了如何验证网站身份的问题。我们如何知道打开的页面确实是google,而不是别有用心的一小撮人伪造的呢?
看页面样式?看网站地址?***是都不可靠。网页样式很容易做到完全一样。地址则可以注册相近的,或欺骗性比较强的域名。比如,注册一个 sina-account-service.com 自称是sina账号服务中心之类。
最稳妥的确认对方身份的方式,是通过查看***来确认。
大部分浏览器在访问htt 网站的时候都会在显眼的地方提供查看***的功能。一般来说应该是一个锁头一样的图标。***可以帮助你确认站点身份,这样你就不会被钓鱼或DNS欺骗。这些具体的欺骗手法我以后还会说到。只要判断***是否是由是可信任的机构颁发的,是否是这个网站的正确拥有者所有,就可以知道你浏览器打开的这个网站是不是真身了。***有问题,那么这个网站一定有问题,这时候就不要进行登录或是找回密码或是重设密码之类的操作了,无论页面上写了什么,牢记这个原则,***不符合,就是不可信任的。对于163,sina这种邮箱来说,只在登陆的时候提供了 l加密,用户在输入密码之前甚至没有机会察看一下***,实在是令人遗憾的事。
图6:在safari中查看gmail的***
图7:在firefox中查看gmail的***
简单介绍一下钓鱼欺骗的办法吧。比如说,你收到一封邮件,来自sina-account-service@sina.com.cn,邮件告诉你,你的sina邮箱账号被攻击,需要立刻修改密码。这时候应该怎么办?正确的方式应该是完全不理,因为任何一个邮箱服务商不会这样给你发信。
当然,很多人觉得还是要点去看看的。于是就点了邮件中的连接。看一看应该没什么损失嘛...是的...不过...
这时候有两种可能,一种可能是:你来到了一个叫做 sina-account-service.com 或是干脆叫china-sina-account-service.com 的网站,页面内容和平时你使用sina邮箱的密码修改页面是一样的。这时候你会不会有可能在里面输入了密码?
有人会说了:"光页面像是不行的,域名不对嘛。" 没错,攻击者注册了sina-account-service.com 这样的域名,虽然看起来像那么回事,但是并不能骗住所有人。那么,另外一种情况:你看到的地址真的是 http://login.sina.com.cn/xxxx 这次相信了吗?这时候仍然不相信的人就不多了。
其实域名一样是可以仿造的。最简单的方法,如果对方修改你的hosts文件,把login.sina.com.cn指向了他控制的一台服务器,那么刚才的情景就很容易发生了吧?除了改hosts这种低级手段,还有很多其他的"高级"一点的方法,比如DNS欺骗...总之,这是完全可以实现的欺骗方法,事实也证明是带来损失最大的。
现在我们知道了,通过看域名来验证网站是否为真的办法是不可靠的。最可靠的办法是查看***。大多数浏览器默认的128位的***已经非常难伪造了。256位的***被伪造就更困难了。当然,这里说的"困难"是伪造出一个真正的,完全一样的***。如果只是要骗过浏览器,还有一些其他办法,特别是IE6,竟然还曾经出现过可以被伪造***的bug。
总结一下就是:
没有***的网站很可能是假的。错误的***一定是假的。
看起来正确的***也存在一定可能是假的。
对***和htt 方面知识有兴趣的同学,可以去看wiki百科
保护你的重要账号守则
1 选用安全级别高的服务。邮箱可以推荐gmail,yahoo mail。yahoo mail有出卖用户的恶劣记录,但仅讨论产品,仍然是最安全的邮箱产品之一。
,保护好你的计算机安全,打开防火墙,注意检测木马。
3 不要在不安全的地方使用你的重要账号。
4 选择一个足够复杂的密码,并根据重要程度增加复杂性,对于最重要的服务,不要和其他服务公用同一套账号密码。如果不能做到所有服务的密码各不相同,至少也应该分成几个级别,对最重要的服务使用最复杂的密码,不要和其他服务使用相同的密码。随手注册的论坛之类可以使用简单密码。
5 时常检查邮箱是否有入侵迹象。
6 不信谣不传谣,什么"中奖了","好友请你输入账号","你的账号被盗用,请在此修改密码"之类的东西统统不要相信,牢牢记住,你唯一可以输入密码的情况是:一台安全的计算机,输入密码的页面***正确,使用htt 。除此之外,在任何情况下都不要输入你的账号密码。
7 应该理解,不通过htt 加密的登录是极不安全的。存在极大的泄露可能。注意检查***。熟悉你使用的产品的安全特性。
8 多注册几个马甲,分为不同的安全级别,用在不同的地方,这样在最糟糕的情况下,损失也可以小一些。
如何选择密码和密码提示问题
如果你选了一个123456作为密码,恭喜,这是最常被用到的密码之一。如果你用了qwerty,恭喜,这也是最常用到的密码之一。至于用户名和密码一样的家伙们,你确定你真是有隐私而不是暴露狂吗?
好吧,你选了一个6位数字密码。如果你幸运的没有选择你自己的生日,没有选择你的手机尾号,那么运气最糟糕的破解者大概要尝试10的6次方次。仅仅100万次,在这个时代,如果你的服务商没有可靠的验证码,没有限制一天尝试密码的次数,那么这个运气最糟糕的家伙试完全部的100万次排列组合也不太可能超过24小时。这个运算能力空前强大的年代,用反复尝试的办法来破解密码已经越来越容易了。所以必须要让密码变的更复杂。
密码提示问题是容易被忽略的地方。很多人设置一个复杂的密码,却往往设置一个简单的密码提示问题。这就好比你家装了一把防盗性能很好的锁,但是却在门口的地毯下面藏了一把钥匙一样危险。
密码提示问题和密码应该是同等重要的,而不是注册的时候演示的那种"你的爸爸叫什么名字"之类的愚蠢问题。
正确的密码和密码提示问题选择守则
1 够复杂
所谓够复杂,意思是:超过8位,包含字母,数字,不同的大小写和至少一种符号。这样的组合会让暴力破解者累死。如果你跟我一样喜欢用13位以上的长密码,那么试图暴力破解的人可能会等到他老的敲不动键盘也拿不到你的密码。如果不是网站的服务,而是rar压缩包之类的文件密码,就更要遵守这个原则,文件打开的时候可不会问你验证码。
2 不要和你的公开信息有关
如果你遵守了1,那么也就没有这条的问题了。一个那么复杂的密码不太可能包含直接的个人信息。如果你实在不愿意遵守1,那么,至少不要用你的生日,***号码,门牌号这种非常容易得到的个人信息。
对了,也不要把这些东西作为问题放到你的密码提示问题中。竟然有服务商会把默认的密码提示问题写做"我爸爸的生日",用户也老实的跟着回答了。要知道有种东西叫做户籍系统,你以为真的没人能知道你爸爸的生日?
3 使用不同的密码
不要给不同的服务使用相同的密码。这世界奇怪的事情太多。你很难知道对方是否把你的密码md5之后保存了,也很难保证各服务的安全性能一样好。如果你使用了一样的密码,那么泄露一次,全盘皆输。
如果实在不想记那么多密码,那么选出来最重要的几个,用最复杂的密码。其他的可以简单一些。其实,实在忘记,可以通过邮件来找回密码,这样邮箱安全就更重要了。
按照我的建议,你应该去注册一个gmail邮箱,然后按照原则1来设置一个13位以上的密码,然后再也不要再其他任何地方使用这个密码。
4 别把你的密码记在本子上
我常常看到,有些人使用非常复杂的密码,密码的强度是合格的。但是他们自己也记不住。于是就写在一个小本子上,或者干脆记在一个文本文件里。这是非常危险的习惯。一旦丢失,所有的密码都丢了,而且因为他自己并不能记住密码,小本子一旦丢掉,连去修改密码都做不到了。
最重要的几个密码一定要用脑子记住。其他的密码可以记录下来,但是要选择一个适当的密码管理工具。如果你使用mac,那么就是Keychain Acce 。这是一个非常安全的工具。如果操作系统本身不带有密码管理功能,还有
。但是要注意软件来源安全(以前也讲过这个问题),也要考虑软件本身的可靠性。
下一部分我们来探讨网络传输过程的安全,以及如何做到真正的匿名。
一些相关链接:
Posted by virushuo at
2:59 AM
July 24, 2009
Version: 1.0b virushuo (
) 20090724
注意:
1 这不是一份完整的安全手册,只是一些知识参考。但他能帮助你了解那些最重要的细节。如果有发现相关部分好的文档和教程,请提供给我,我连接上。
2 本文主要用于商业安全和个人隐私安全(包括你的私人照片,银行账号等的安全),本文不鼓励将这种技巧用于其他用途,使用在其他用途造成的损失和后果与本文无关,正如用菜刀杀人与磨刀的老大爷无关。
3 本人并非专业研究计算机和网络安全。只是觉得略有所知,所以分享一些常识。如有专业人士认为有错漏,请不吝赐教。virushuo( attt ) gmail.com
4 感谢
的支持和建议
,你妈妈
#amoiist
6 本文会时常修补增加内容,要转载请务必注明出处和以上注意事项。
网络是怎样传递信息的
整个互联网,可以看作是一台台计算机组成。当然,他们承担了不同的任务。一些机器负责存储你的信息,一些机器负责寻找路线,另外一些则只负责传递。你的信息,或者叫做数据,总是穿过了一台台计算机,才到达最终的目的地。可以想像,在穿过这一台台计算机的时候,是一次多么惊心动魄的历险。每台计算机后面都有一双眼睛,有的还不止一双。这其中可能有你的朋友,可能有完全中立者,不幸的是,你的敌人也往往混迹其中,虎视眈眈。
如果你不采用任何安全措施,则你的信息对于这无数个环节都是透明的。这可能意味着:你的商业机密转天见报,你的情书转天成为办公室趣谈,你的账号上一大笔血汗钱不翼而飞。当然,当然,还有最糟糕的......你还没来得及反映过来,就发现被人塞进车里送到一个不知名的地方。为了不至于成为陈冠希或是被躲猫猫,那么你必须得把这个事情重视起来。
大部分情况下,危害安全的行为都是广泛的,并非针对你个人,比如说,用扫描器来大量寻找具有某些漏洞的机器,或是用爬虫来尝试用123456做邮箱密码的家伙。所以,只要稍微设置一些障碍,对方往往知难而退,去寻找更容易上手的菜鸟。而,特殊情况下,你被盯上了,这就要非常留心了。
一份数据(文档,照片,聊天的一句话,统称数据),从你的计算机上完成编写,经过你的网络发出,进入公共网络。经过无数节点之后,到达某处,等待另外一方获得。这就是进行一次互联网应用的过程。我们来依次看看这个过程中哪里会产生安全问题。
1 你的计算机是否安全?你的操作系统是否有漏洞?你的计算机内是否有木马或病毒?是否有其他人可以使用你的计算机?
2 你的网络是否安全?你的局域网内还有谁?
3 经过的节点安全吗?你的数据是否进行了加密?
4 为你提供服务的服务商安全吗?你所拥有的账号是否泄露?
5 你的IP地址安全吗?你是否愿意被别人追踪到你的IP?
6 除了目标方,还有别人能看到你的信息吗?尤其是email和IM的聊天。
先问问自己这些问题,如果***不确定,那么就继续往下看吧。
计算机安全
计算机安全是一切的基础,但又往往被忽视。可以想像,如果在你使用计算机的时候,身后永远站着一个人,时刻盯着你的屏幕,那一切安全都无从谈起。所以,首先要保证你有一台足够安全的计算机。这个安全是一系列良好的习惯。绝对不是***一个杀毒软件就可以高枕无忧的。
1 补丁,木马,病毒,以及其他
对于个人计算机的信息安全来说,最大的挑战是木马。木马真正实现了"你身后永远站着一个人"的效果。相比之下,病毒最多是破坏资料,侵占系统资源,尚无泄密之忧。在这个时代,我认为病毒的安全危害远远小于木马了。现代破坏者们也不再和当年的hacker们一样,乐于通过写一个"得不到任何利益"的病毒程序来炫耀自己的水平。他们更感兴趣是你的银行账号,邮箱密码,网游账号等等真正能变成钱的东西。就算这些都没有,控制你的计算机去帮一些网站刷Alexa排名也是能赚钱的。从几年前开始,新的木马程序和流氓软件产生的速度远远高于传统的病毒,其中"利益为上"是主要原因。
***一个木马到你的计算机上有很多方法。最简单的方法,就是诱使你***某个程序。 这个行为又可以分成很多具体操作。常见的有:
a 绑定在正常的软件中。
b 通过常见的聊天工具,利用你的好友给你发送消息,骗你下载(比如QQ尾巴)
c 群发邮件,诱使你运行附件
d 把图片,flash等等打包成exe文件,把木马捆绑上。
最简单的办法永远是骗。千万不要看到"骗"这个词,就觉得技术含量很低。实际上,这个办法学名叫做"
"。实在是一种专门的学问,不可小看。后面我们还要多次提到这个词,你可以看到,几乎在各个环节,只要有人参与,就有"社会工程学"发挥的机会。
比最简单的方法复杂一点的办法,就是利用浏览器的漏洞。IE是个漏洞百出的浏览器,出现过多次致命漏洞。通过在网页中嵌入一些代码,就很容易利用带有漏洞的IE把木马***到计算机上,比如"灰鸽子"。
最复杂的方法,就是缓冲区溢出(其实利用IE的漏洞也是缓冲区溢出的一种。),你的计算机上总是运行着很多程序,这些程序,包括操作系统(windows)本身,都可能存在各种漏洞。这些漏洞如果被巧妙的利用,就可以用来***木马。历史上有几次大的破坏,比如针对windows漏洞本身的"红色代码","尼姆达"。而如果你不小心***了权限很高,漏洞很多的软件,那么就更容易被攻击。比如我之前说过绿坝的危害。
要保证你计算机的安全,建议做到以下几点:
a 如果可能,不要使用Windows。Mac和Linux的安全强度高的多(很多人认为Mac/Linux安全是因为用户群体小,这个看法是不对的。后面我会用一些例子说明),Windows也并非如大家印象中的那么不安全,只不过需要付出更多的精力来调整和维护。这和一般认为Windows"易于使用"的特性恰恰相反。
b 如果要使用Windows,必须做到及时更新,打所有的补丁。最近看很多人号召关掉Windows自动更新,这是比较危险的行为。
我记得360安全卫士提供了给Windows更新的功能,还不错,如果关掉了Windows自动升级,那么就用360的吧。
(从目前的情况看来,360不再可信。不要再装了)反正不升级是肯定不行的。
c 正确使用防火墙。Windows XP自带了防火墙,一般来说就不用装其他的了。只要把大部分没用的端口关闭掉,就能应付很多情况了。
如果你有一个路由器,那么配置合理的话可以当作硬件防火墙使用(当然也会导致一些新的问题)
d 不要运行任何来历不明的程序。包括你朋友的推荐来的。如果有朋友通过m 或是邮件发给你一个软件或让你下载,那么问他几个问题,以确认是他本人在操作计算机。必要的时候,甚至可以打个***给他。不要怕麻烦,很多时候,这也是在帮助你的朋友。
e 如果你非常热爱折腾新软件。那么,准备一个虚拟机,专门用来试用软件。确认安全和有用之后再挪到你的工作系统上使用。相信我,你没有那么多需要的软件。
f 如果可能,尽量使用开源软件,并注意在下载的时候校验MD5或PGP,以便确认你下载的是真正的软件,而不是被别人替换过的。可
其实,我甚至想极端的建议拒绝从不提供任何校验方式的下载站下载,这种下载站要么缺乏基础的安全常识(这样他们就很难保护你的安全),要么就是根本不负责任。
g 杀毒软件在这个时代用处不大,空占资源,还可能惹出来很多新麻烦。包括把能够保护你的软件悄悄删掉(后文会提到)。所以,如果你做到了前面几点,就别浪费这份钱了。
2 权限,账号和共享
使用计算机是有权限的。一般来说,应该降低权限使用。不幸的是,我在很多地方看到人们大摇大摆的使用administrator(或者是具有管理员权限的其他账号),这是系统的最高权限,就像你这台计算机的上帝,日常用这么高权限的账号,危险啊!更糟糕的是,很多人的administrator账号没有设置密码,或是只有简单的密码,在这个危险的世界里,这是和裸奔差不多的行为。正确的做法是:
a 给自己的日常使用建立一个权限较低的账号。甚至低到这个账号只能运行指定的程序才好。
b 前面说了,尽量不要和别人公用计算机,哪怕是家庭成员,限于现状,实在做不到的时候,也应该给其他人单独建立账号,而不要公用一个账号。这些账号的权限都不应该太高,因为一个安全意识不强的人中招,有可能影响到所有人。一些网吧管理软件可以帮助你更好的完成这项工作。
c 设置一个复杂的密码。如果你的administrator密码为空,或是很简单,那么别人很容易通过访问C$来读取你的硬盘,这意味这对方可以拿走你硬盘上的所有文件,管他是艳照还是商业机密。(至少在XP时代,这样还是可行的),所以,给你的administrator设置一个复杂的密码吧。
d 时常注意检查你的共享文件夹。比如说,你在家里把笔记本上的文档通过共享复制到台式机,而你忘记关闭了笔记本的共享。那么下次你去咖啡厅上网的时候,跟你公用一个无线网络的人也可以轻松拿走这些文件。(但愿里面没有艳照...) Windows 使用管理工具->计算机管理->系统工具->共享文件夹 中可以查看哪些文件被共享了。
顺便说一句,我见过某人,从一个竞争对手的总经理笔记本上,弄到了数G的文档,无所不包,甚至包括该公司员工的工资表,相当壮观。其实,那个可怜的家伙也没犯太大错误,无非是违背了c和d原则而已。
在Mac中,默认系统是不允许直接使用最高权限账号root的,其实这也是unix家族的传统。在需要使用管理权限的时候,会给予提示并要求输入密码(这个特性我4年前写过
)。这个小小的技巧让系统安全性大大增加。Windows Vista似乎也采用了类似的方式,不过据说做的不好用。我没用过,就没发言权了。
Mac中,默认的共享只有一个"公共文件夹"和其下的"投递箱",公共文件夹是所有人都可以看到的文件,而"投递箱"是别人给你传递文件用的,顾名思义,放到这里的文件,只有你本人才能访问,哪怕投递者本人,一旦放进去也不能再访问了。这些默认的设置很好的引导用户正确使用共享功能,降低了安全隐患。Windows通过一定设置应该也可以实现同样的效果。
3 公共计算机安全守则
如果万一你需要在公共场合使用计算机,那么往往代表存在着极高的安全隐患。必须要提起重视。你永远也不知道你使用的这台计算机上***了什么软件。是否有自动屏幕截图?是否有键盘按键记录?是否记录所有发送的数据包?天,这就好像你到酒店开房,永远也不知道房间是否有隐蔽式摄像机和***一样......
当然,对方可能是你很好的朋友,他并无恶意,也没打算窃取你的机密。但是,如果他的安全意识不高,那么他早就成了别人饵下的鱼。你跑上去登录一下你的邮箱,只不过是给幕后黑手多一份惊喜罢了。
所以,同样也遵守一些守则吧:
a 不使用不加密的服务。只访问htt 的服务,这可以有效的避免有人记录你登录数据,所谓登录的数据就是你的用户名和密码。如果不是htt 的服务,那么你的用户名和密码是用明文发出的。等于白白送给别人。
b 不要使用你最重要的邮箱。你最重要的邮箱往往是你一系列服务的基础,如果这个邮箱落到别人手里,他可以通过找回密码来搞定你所有的服务。所以,最好准备一个备用邮箱,专门放一些不太重要的东西,以及在这种场合使用。
c 一个小技巧。输入密码的时候,先打开一个记事本,在里面胡乱按很多字符,然后用鼠标把你需要的密码字符一个个粘贴,复制到相邻的位置。然后把他们连同一些多余字符,一起复制粘贴到密码输入框中,删去多余的字符,登录。这个技巧是为了防止计算机后台运行了键盘记录木马,鼠标位置的移动比键盘的纪录难的多,所以经过这番折腾,能给窃取者制造一些麻烦,给你修改密码的行为争取一些时间。复制粘贴一些多余的字符,是为了防止有记录剪贴板内容的木马存在。这样他们得到的密码是比实际多几个字符的。
d 一旦回到你的安全计算机上,必须修改你的密码。要修改的密码包括你在公共计算机上使用过的服务,也包括同名同密码的其他服务。比如 iamhere@gmail.com 和 iamhere@163.com两个邮箱密码相同,你只登录了后者,但是前者的密码一样要改一次。不然,假如后者密码被键盘记录器记录了,那么前者也会被试验出来。c的技巧是为了给你争取到一些修改密码的时间。
公共计算机往往是安全泄露的重要环节,我听说过有人网游账号被盗,有人邮箱被盗,今天还听说了一个朋友因为邮箱被盗,最终导致支付宝被盗。这些尚且是损失一点钱和时间。如果你立志做一个匿名网民,邮箱里面有一些不想被别人知道的文档,那么...诸多血的教训一定要牢记啊。
待续,下一篇中我们将讨论什么样的网络服务比较安全,应该选择什么样的邮箱作为主要邮箱,如何保护你的账号安全等话题。
Posted by virushuo at 11:19 AM
July 15, 2009
是我相当佩服的程序员,做同事的一段时间里,让我学到了很多东西。从当年就看他在做lighttpd的缓存扩展
,也实际使用情况。近几年这东西经过几次改进,越来越好用。甚至创下过单服务器跑满1G网卡的记录。这次很高兴能有机会请他来
分享一些经验。
他所在的环境也非常好,有相当大的流量可以实际应用,这也是大部分人难得的机会。我看到了很多人在twitter上的
,如果有机会,希望你们也能来beta技术沙龙,分享下你的经验,不同行业下的背景肯定不一样,这是相当有讨论价值的。
争论最多的地方应该是 线程/进程 。这是永恒的争论,频率大概只小于"java好还是C#好"。这几天在Top Language组里面也在讨论线程和进程的问题。按照我个人有限的经验,我更倾向于多进程,尤其是存在共享数据区域的时候,多线程的写还是挺容易出问题的,更不容易调试。一种说法是:使用锁是基本功,但我宁可采用多进程,分开数据区域。(mod_cache的多个进程之间也是不共享数据的)。当然,这事关应用场合,对于缓存来说,这种处理完全可行。确实有一些情况必须使用多线程写,但这种情况我也没觉得线程比进程能好多少。事实上,除了图形界面程序,我个人不打算在任何地方应用多线程了。
也有说法认为多进程是浪费了多个核。其实不然,服务器程序是连续处理的,虽然进程之间存在等待和数据复制的问题,但多个任务的连续处理正好可以弥补这个空闲,计算资源不会被浪费。用个不怎么贴切的例子来简要说明一下吧:文件下载的时候,如果下载一个文件,分开多个线程,同时下载多个块能加快一些速度,而如果有多个文件下载,那么所有文件都单线程下载,但多个文件同时进行,最终速度是差不多的。前者需要处理锁,后者什么都不用管,简单很多。
这样做设计上可能需要花一些心思,不过我觉得比处理锁还是容易点。如果说"用好锁是程序员的基本技能",我认为能够正确的划分数据区域和任务,降低耦合也是必须的基本技能。这样划分好之后,程序是可以分布在多台机器上(当然通讯开销更大),未来的扩展余地更大。(仍然是要看应用场合的)
twitter上看有朋友提到更好的解决方式是erlang。不过这个我尚未涉足,不甚了解。不敢乱说,还希望有实际经验的朋友能写点东西分享。
继续说回lighttpd和mod_cache。这个组合其实是相当不错的,也有过很大的应用考验,可以放心用了。基于lighttpd,我也写了一个mod,用来做转发。用途是从某个url pattern转向某个端口。一般人可能用不到这个功能,也没什么成熟产品。于是我就基于lighttpd写了一个,效果很好,目前已经运行了500多天无故障。
在大量并发请求的时候,我认为event base是个不错的选择。我对lighttpd 1.5的实现不太满意。但1.4是相当不错的。现在作者不怎么活跃,不过已经足够用了,代码也相对简单,有问题可以自己改改看。是个不错的选择。
这次活动有视频记录,
可以看到。
另,下次活动主题是:
,欢迎到时候来参加和讨论。
Posted by virushuo at 12:55 AM
1, 2009
update:留言中jjgod的方法更为正宗和简单。请参考。不过如果dylib之间有依赖关系,你又不想重新编译。那大概还是要用我这个办法的。
所谓dylib,就是 d风格的动态库。基本可以认为等价于windows的dll和linux的so。mac基于 d,所以也使用的是dylib。
如果你需要引用一个第三方的dylib,在xcode下编译出cocoa程序,在本机上运行是不会出问题的。但是发布出来,给其他用户用,就可能出问题。因为用户不一定有这个库。
这个问题给我造成了相当的困扰,我到现在也没找到正规的方法。但是我确实解决了这个问题,虽然方法不一定正宗。不管怎么说,写下来,
如果暂时没有更好的办法,那么先这样做。如果谁有更好的办法,也请一定不吝留言或邮件给我
我的办法是这样的:
1 otool -L youra .a /Contents/MacOS/youra 这一步的意思是对你编译出的a 使用otool命令,以便获得依赖哪些dylib的信息。注意这个路径。cocoa的a 在命令行下表现为目录。所有相关的东西都在里面。
结果如下所示:
youra .a /Contents/MacOS/youra :
/System/Library/Frameworks/Cocoa.framework/Versio /A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
/usr/local/lib/lib01.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib02.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib03.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versio /A/CoreFoundation (compatibility version 150.0.0, current version 476.0.0)
/System/Library/Frameworks/A Kit.framework/Versio /C/A Kit (compatibility version 45.0.0, current version 949.0.0)
/System/Library/Frameworks/Foundation.framework/Versio /C/Foundation (compatibility version 300.0.0, current version 677.12.0)
注意我标红的地方。假如lib01,lib02,lib03是本程序引用的第三方库,那么在这个程序里面,他们的引用地址是位于/usr/local/lib上的。这是开发机上的***情况。而使用这个程序的客户机未必***这些东西,所以程序就要出错。
显然,我们需要做2件事。a 把这些库附带在a 上
b 把他们的引用地址修改到正确的位置。
2 mkdir youra .a /Contents/dylib
在编译出来的a 中,创建dylib目录
然后把所有需要的库复制过去
cp /usr/local/lib/lib01.dylib youra .a /Contents/dylib/
cp /usr/local/lib/lib02.dylib youra .a /Contents/dylib/
cp /usr/local/lib/lib03.dylib youra .a /Contents/dylib/
3 i tall_name_tool -change
/usr/local/lib/lib01.dylib @loader_path/../dylib/lib01.dylib "youra .a /Contents/MacOS/youra "
i tall_name_tool 是苹果提供的用来修改dylib***名称的命令。这个命令执行之后,再用otool -L 就可以看到变化了
youra .a /Contents/MacOS/youra :
/System/Library/Frameworks/Cocoa.framework/Versio /A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
@loader_path/../dylib/lib01.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib02.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib03.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versio /A/CoreFoundation (compatibility version 150.0.0, current version 476.0.0)
/System/Library/Frameworks/A Kit.framework/Versio /C/A Kit (compatibility version 45.0.0, current version 949.0.0)
/System/Library/Frameworks/Foundation.framework/Versio /C/Foundation (compatibility version 300.0.0, current version 677.12.0)
注意标红的位置。已经变化了。@loader_path 指的是应用程序运行的位置,也就是youra .a /Contents/MacOS/youra ,所以要用一个..,以便定位到第2步创建的dylib目录。
重复这个命令,修改lib02,lib03
4 otool -L youra .a /Contents/dylib/*.dylib
继续用otool 来检查dylib下面使用的第三方库是否还有其他依赖,i tall_name是否正确,重复1,2,3的步骤,把所需要的dylib复制过来,修改i tall_name。
如果都改对了,那么这个a 就附带上了dylib,可以在其他机器上正确运行了,不用非要寻找/usr/local/lib下面的库了。
刚才我们修改的结果是一个build的结果。当然,每次build都这么折腾一下很麻烦。所以继续这样做:
1 前面的步骤得到了一个完整的dylib目录。把这个dylib复制一份备用。比如放在你的xcode项目下面。
2 编写一个脚本:
mkdir "$TARGET_BUILD_DIR/$PRODUCT_NAME.a /Contents/dylib"
cp -f /your/path/to/xcode_project_name/dylib/*.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.a /Contents/dylib/"
i tall_name_tool -change
/usr/local/lib/lib01.dylib @loader_path/../dylib/lib01.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.a /Contents/MacOS/$PRODUCT_NAME"
(用这个格式重复前面对a 使用过的dylib)
3 在xcode中,展开targets节点,右键点工程名称,在菜单中选Add->New Build Phasa->New Run Script Build Phasa,在打开的对话框里面,把刚才的脚本贴进去。如图所示。
这个脚本会在build之后自动运行。不过我这里有个奇怪的问题,如果Shell里面写了/bin/sh,会报告找不到这个文件(实际上存在),而让shell为空,反而可以正确的运行shell命令。
经过这些处理,每次编译出来的a 就可以拿到其他机器上运行了。可真够麻烦的...
Posted by virushuo at 10:09 AM
June 15, 2009
简单谈几点绿坝的技术上的错误。如果不改进,我相信未来会造成巨大的损失。
1 不应该用木马的方式来保护自己。
站在绿坝的观点上,认为不能被孩子随便卸载和杀掉,所以就要强力的保护自己。于是用了一系列只有病毒和木马才会用的办法。这是典型的方法错误。正确的方法应该是给孩子一个单独的账号,降低此账号权限。然后绿坝以管理员身份运行。这样就不用靠流氓手段保护自己。家长和成年人也可不受其干扰。眼前使用的办法,其实也保护不了自己的安全和不被卸载。
2 缓冲区溢出的问题必须要重视。
到目前为止,密歇根大学提出的缓冲区溢出漏洞没有被修正。而根据电脑报文章,用户在正常使用中时而会导致浏览器崩溃。这大概也是溢出的迹象。在我的周末的简单研究中,觉得确实如密歇根大学报告所说"使用了较陈旧的编程方法",系统中存在缓冲区溢出的机会大大增加。
简单的反编译就可以发现,程序中大量数组和内存操作是不安全的。导致缓冲区溢出的机会很大。还有相当数量的硬编码,把一些密码之类的东西直接写了进去。这些不良的编程习惯都会带来安全问题
缓冲区溢出并非让程序崩溃退出那么简单,事实上利用这种漏洞是可以完全控制一台计算机的。历史上几次大的病毒传播,比如nimda,比如红色代码,都是缓冲区溢出引起的。缓冲区溢出不仅困扰小公司,对微软这种大公司也是巨大的安全威胁。但是像绿坝这样,把漏洞百出的代码做最广泛的推广和强制***,实在是匪夷所思。如果真的这么推广下去,真的都***了,未来还不知道出什么事。
如果被用来攻击电子政务系统或是骨干网的路由设备,造成的损失很非常大。不知道到时候政府会不会后悔现在的行为。
3 不加密的升级方式很危险
绿坝的升级都是通过http的,并且频繁调用gethostname来做d 解析。一方面,简单的d 欺骗就可以让系统***恶意代码。另一方面,如果升级服务器被攻击掉,也很有可能导致前几天的"暴风断网"事故重演。规模恐怕还要大的多。
4 杀毒软件怎么办
绿坝的很多行为,和木马很相似,这些行为必然会被杀毒软件和木马清除软件识别。如果工信部强令杀毒软件把绿坝加入白名单,最终就等于在系统里面为病毒制造一个保护伞。病毒和木马可以通过附着在绿坝上面,躲避杀毒软件的扫描。这也是严重的安全问题。
总结:一般来说,大规模***的软件要特别注意安全问题。最有效的办法是降低自己的权限,那么就算出现问题也不至于影响太大。但是绿坝反而用不正当的方式获得了很高权限。而高权限的软件则要至少能保证自己的安全,绿坝显然也做不到这点,绿坝调用各种dll并没有做校验,这都是非常容易被利用的。
一个具有高权限,又被普遍***的软件,一定会吸引大量的攻击,这个诱惑太大了。这在windows一贯历史上都得到了验证。而一个不严谨,具有高权限,又广泛***的软件,一旦被攻击,结果会怎么样呢?历史上没有过先例。但我想一定不是个好结果。
另外,在我研究的这部分(xnet2.exe,gn.exe,xdaemon.exe)中,我没有发现往服务器发送用户隐私的行为。但这不代表其他部分没有。大正的引擎是和绿坝是完全独立的,只是通过exe进行了简单调用,这部分也存在前面提到的问题,很容易被冒充或注入。在卸载方面,我看到了绿坝的卸载代码,就软件开发者来说,他们确实是想完全卸载,不留痕迹的。但是因为技术原因未必能做到。而且在某些其他程序干扰下,可能卸载也不能顺利完成。这也造成了"不能卸载"的假象。
如果工信部真的想解决未成年人保护问题,请将此软件开源,以便保证其中立和完善。苹果操作系统甚至自带了未成年人保护功能,这确实是应该的。但不应该是用目前这种危险的方式进行。
说到担心计算机被政府控制用来限制言论自由的观点,我觉得也不用太在意。事实上,所有政府都希望做到这事,但在操作上是如此的不具备操作性。如韩寒所说,计算机上有个东西叫做键盘。这就决定了不可能有超越用户存在的软件,哪怕是最厉害的病毒。一个试图当上帝的程序,最后的命运往往是去见上帝。
计算机是完全开放的,互联网也是。他们的体系和架构就决定了这一特点,任何与这个特点相反的努力都是徒劳的,好像螳臂挡车,阻挡历史的车轮。必然是不可实现的。
Posted by virushuo at
8:53 PM
May 29, 2009
是关于iphone开发的。对iphone开发有兴趣的人非常多,一方面是a tore造成的财富神话,另一方面也确实是有iphone的人越来越多。大家都偶尔想写点小程序玩玩吧。
作为一个mac用户,能感觉到企业对苹果平台的兴趣在逐渐变大,甚至连腾讯这种以不兼容为美的公司都做了QQ for mac/QQ for iphone。几个做共享软件的朋友跟我说,iphone程序是个富矿,很可能重现当年共享软件的疯狂。(其实国外现在做共享软件也是不错的)
我虽然用了很多年苹果,不过一直也没开发过"真正的"苹果的应用程序。我已经很多年不写图形界面的程序了,通常只写人们看不到的东西,就算有需要,也是三两下扒拉出来一个命令行程序用。而
自从抽奖赚到了一个iTouch之后,就一直尝试着iPhone的开发,我偶尔去看看他做的东西,总觉得Objective-C这东西很古怪,非常不符合我对C的审美,因此也更加没兴致尝试了。
在这次沙龙活动中,听了robin和Tiny的介绍,倒是发现了一些以前没注意到的东西,所以觉得还是值得做个笔记。
Objective-C的古怪之处,主要是一些语法看起来很晦涩。奇怪的定义和符号混合起来,让这种语言看着一点也不像C。Tiny在演讲中多次强调了,阻挡人们学习Objective-C的主要原因就是这种奇怪的语法,容易让人不适应。
当然,仔细想想,似乎所有用来写图形界面的语言都扩展了大量的独有特性。这句话也可以反着理解成:凡是没做特殊扩展的语言,在写图形界面程序的时候都比较困难。
以我的认识,这种困难主要来自图形界面设计的复杂性,和消息/事件传递的难度。如果不写图形界面程序,C足够完成任何功能。而一旦要处理复杂的界面和消息响应,复杂度陡然上升,这就需要面向对象了。在以往,delphi改造了pascal,VC改造了C++,主要的目标都是为了基于面向对象,简化消息处理,事件相应和界面设计。MFC固然难以理解,不过还是比手工用API处理消息容易一些,程序越复杂,这个差距就越明显。
Objective-C要解决的问题也差不多是这些。Objective-C用可视的方式设计界面,用拖拽的方式来创建事件关系,扩展了一些语法,把C改造成了面向对象语言。用引用计数和autorelease池,使内存管理变的简单,对于字符串处理这种容易出问题的操作进行了封装。感觉用起来很像delphi。有人甚至做了一个
,确实有很多相似之处。
和C++不同,Objective-C是基于消息传递的,后来我猛然想到,这是来自Smalltalk的思想(其实Wikipedia中,关于
的介绍第一句就是"Objective-C is a reflective, object-oriented programming language, which adds Smalltalk-style me aging to the C programming language."),想到了这个也就知道那些古怪的语法是怎么来的了。在Smalltalk中更极端,连运算都是以消息形式完成的。Objective-C中似乎还没到这个地步。但是已经有Smalltalk的感觉了。这些特性让Objective-C成为一种非常具有动态特征的语言,这也造成了一些错误在编译检查是正确的,但是到运行时出错。所以写程序的思想也要随之调整一下。
明白了这些东西,也就更容易理解Objective-C的思想。觉得别扭是大家都被C++和Java带到坑里了,其实Smelltalk才是纯粹的面向对象语言。如果对Smalltalk不太熟悉,可以来看看徐宥的
,明白了这些思想,对理解Objective-C有很大帮助。
写程序最难的事情,就是逻辑的描述,内存管理和字符串处理。Objective-C很顺利的解决了这几个问题。所以按照我的判断标准,这就是一种不错的语言了。就目前的语言特性看,不太容易成为C++那么混乱和让人抓狂的语言。再加上苹果的精心维护和推动,未来应该很看好。甚至将来成为最常用的语言之一也说不定呢。
如果你来参加了这次活动,应该已经能动手写iPhone和mac程序了。其实一些要点点破了之后,mac/iPhone的开发一点也不难,比其他平台上简单的多。程序员可以不太关注语言的多义性和复杂表述,更容易专心于写程序本身,也更容易获得高质量的程序。
PPT在这里:
另请在twitter上follow betasalon :
Posted by virushuo at
6:39 PM
May 22, 2009
切分是最基本,且最多变的思路之一,说基本,是因为在学习程序设计的第一天就应该知道,说多变,是因为在未来的很多年里,你会不停的应用这个方法来解决问题。不幸的是,切分这个思路并没有得到应有的重视。
大概是因为这个词比较土,说起来也比较普通,远不如并行,集群,负载平衡这些词听起来大。所以碰到一个问题的时候,往往被拿出来的解决方案会是以上3个大词之一,很少有人去认真的考虑切分问题。但事实上,这3个大词所需要的技术,其实也是建立在良好可切分的系统之上的。
最近碰到了2个项目,都是典型案例。
案例1 ,小公司,发展的不错。一台服务器眼看不够用了,于是就买了第二台,希望能做一个"负载均衡"系统。很多人大概认为负载均衡,是类似自来水一样的技术,只要打开笼头,清水就汩汩涌出。往往忘记了水龙头后面的水管和自来水公司。
一个服务器上放了很多个服务,是很难应用负载均衡这种技术的。必须先要把服务拆开,找到性能薄弱的点,对这个点进行负载均衡,才能得到比较好的效果。否则很可能用了80%的力气,但是只得到20%的结果。
案例2,某外企。之前我们给他们做过咨询,解决了一次问题,上次我们找到了系统最慢的地方,去掉了老系统中性能消耗多的地方,用通用的缓存(squid/memcached)系统来代替他们用php写的硬盘文件缓存,上次的改动让性能困扰远离了他们一年,随着业务发展,性能又显得不够了。
比起来一年前,他们的服务器数量增长了一倍。其中大量服务器用于做mysql集群和web集群。服务器是复杂的网状关系。前面说过,这种不分主次的架构往往只能解决20%的问题。而且很容易到达瓶颈。
套用回那3个大词,这个系统确实是集群的,负载平衡的。因为所有服务器的功能是完全一样的,任何一台单独拿出来,都是完整的系统镜像。看上去很美,但实际用起来可没有这么理想。在实际应用中,一台服务器出了问题,几分钟之后,所有的服务器都出问题了。并没能如预期想像的,损坏一两台不影响正常工作。
这个案例中,实际使用了6台服务器做mysql集群。每台服务器的数据是完全镜像。可以想像,如果6台服务器中有一台出了故障,所有的压力就会被平均分到其他5台上。在集群负载大的情况下,增加1/5压力,很可能让另外的5台直接被压垮。这时候发生的情况,就好像最近株洲的塌了的大桥一样,一个桥墩一个桥墩,好像多米诺骨牌一样,一路塌了下去。
从任何角度看来,这都不是一个好架构。别说稳定了,连基本的服务都保证不了。
对于2个案例,我给出的解决方案都是先做切分,然后再分别进行优化。首先可以按照业务切分,把现有服务器分成多个组。对于web前端和mysql集群,每组2~3个足够应付大多数情况。每组服务器数量太多,不仅造成单点故障的概率增加,也容易在自身的数据同步中消耗大量的资源。
比较以下两张图:
改造前:
改造后:
之前的结构是所有web服务器放着同样的应用,所有数据库服务器放着同样的数据。改进后的结构是将整个系统按照服务内容和性质拆成了几组。从ServiceA到Service n 采用了不同的配置方式,简单的只用一组机器,复杂的用多组。在实践中,其实还可以分的更细致,甚至几个Service公用一组机器。(之前
,有道讲他们的
,也提到了类似的办法)
后者的好处很明显,最明显的:
1 可以有效的使用资源。比如:服务A是低负载型的,并非核心业务,可以给予较少的资源。(较少的机器,较差的机器) ,而服务B是核心服务,需要全力支持。
2 可以简单的监控性能。所有服务都混在一起的时候,碰到性能问题很难下手分析。很有可能是最不常用的服务A中有bug,导致了整个集群性能低下。寻找这种bug要耗费大量的人力和时间。
3 易于备份,升级时切换服务平滑。
4 为下一步优化做好准备。综合以上2点,下一步可以集中资源,对重要服务专门进行优化,保证稳定和性能。
在以上的例子中,我们可以看到,专门对重要服务B进行负载均衡,无论在成本上还是性能受益上都比对整个应用进行处理划算的多。
除了根据明显的业务边界进行切分,还有很多种方式,比如按照时间,按照读写频率等。
这种思路也不仅仅应用于web server/database。比如,设计缓存的时候,也应该进行一定的切分。以squid为例,应该把文件大小差不多的文件放在一个squid中,把更新频率接近的文件放在一个squid中。这些都是让架构清晰,性能提高的办法。
从系统设计的初期,就应该贯彻这个思路,用子域名来标记不同的服务(img.yourdomain.com, .yourdomain.com...),比用虚拟目录的方式(www.yourdomain.com/img,www.yourdomain.com/ )更便于切分。
很多人咨询过我这个问题,不过他们都是从seo和产品方面考虑,从来没想过这是和技术相关的。如果所有的应用都放在www之下,未来一旦想把一个服务挪到另外一台服务器上,就很困难----不是没有办法,只是难度比较高。 子域名只需要设置一下域名解析,把要挪走的服务指向新的ip,几分钟就搞定了。
这个办法的实质,仍然是降低系统耦合度。必要的关联数据,宁可采用http请求的api形式,也不要跨数据库进行查询。http请求可以很方便的跨服务器,可以设置页面缓存等,跨数据库请求则只能在数据库上花力气,最后又退回了对全部数据做数据库集群,master/slav的老路上e(当然,这不是一条原则,还是要根据应用的具体情况而定)。诸如此类,尽量要将思路放远,不要贪图眼前的小得失。(常见的说法:数据库怎么也比http快吧...这没错,不过要看应用场合)
能在一个单一的服务中承载尽量多的数据和请求,这当然是所有技术工作者不懈的追求。在此之前,如果先进行合理的切分,再令每个服务的性能最大化,一般都能得到更大的好处。简单是美,简单就是力量。
Posted by virushuo at 10:55 PM
8, 2009
我曾经想自己写一个udp server来接受我的服务器程序发回来的状态,然后做跟踪和统计。后来被
批评为自己重复造轮子。于是转向试图利用 mp协议来做。
用 mp有几个原因:
1 mp是基于udp协议的,具有udp的所有好处(数据状态这种东西,用tcp是不合适的)
2 mp比较成熟,周边的软件非常多,后面可以很方便的处理收集数据,绘图等等一系列的功能。(rrdtool/cacti....)
3 因为我们要监控的服务非常多,所以希望能设计一个尽量免配置的方案, mp的树型结构正好获取节点下面所有的被监控值。 mp在网管系统中有很大规模的应用,但是似乎没什么人用来监控软件服务。而,目前我们知道的对 mp和cacti的应用,似乎大部分都只停留在了用来监控服务器状态(mem,load average,net io,disk)上,有点可惜。
在这篇blog里面,我提到的用法应该不是最正宗的,但是有效。其实很多大厂商甚至自己修改 mp协议,做出自己的分支协议来。比起他们,虽然我做的不太正宗,但是也不为过。
我要实现的东西大概可以用这张图来描述:
概括起来:很多个服务分布在很多台机器的很多个端口,所以我们需要在每台机器上放一个 mp代理,得到他们的状态,然后再统一通过 mp协议获取这些状态。由于服务太多了,必须要免于配置,这就更显示出了 mp协议的优点。
扩展 mp有几种方法,不过综合起来,我认为最简单和灵活的还是agentx协议。agentx完全是独立在 mp server之外的,可以一层层的套起来。其他的协议要么要在 mp上加东西,要么要写mib的模块文件,都相当麻烦。
不过,最常用的 mpd,反而对agentx支持不好。至少他们自称还是试验性质,不建议用。我试图在 mpd.conf中允许agentx协议,也几经挫折。最终决定找别的方案。似乎大家都习惯把 mpd当作唯一的 mp server,其实类似产品还有很多, mpd时间比较久,但我认为并非最好的。在ubuntu的apt源里面,都有几种其他方案可用。
当然,由于我并非希望取得系统的硬件状态,所以我也并不一定要找一个通用的产品。所以最后我决定用jagentx(http://eden.dei.uc.pt/agentx/)。
jagentx实现了 mp v1 协议和agetnx协议,一般来说足够用了。他们网站首页的那张图,很好的说明了agentx方式的系统结构。
jagentx提供了比较友好的api和demo,不过还是有一些bug,我做了一些修改。
1 jagentx的master(相当于server),对于master mib的读取,只能支持 mpwalk,不能支持 mpget。其实是一个状态设置错了。
在 Master_Engine.java中
if (!any_subagent_queried){
int error_index = 1;
int error_status = Pdu.NO_SUCH_NAME;
后面,加上
if(value != null)
error_status = Pdu.NO_ERROR;
就可以了。
2 是关于se ion的。如果客户端退出,没有注销,就要等自己的se ion超时,不然连不上。这个在实际应用中很容易出问题。服务不正常退出的情况发生几率很高。于是我做了一些改动,可以通过se ionid来注销其他进程。这样确实会造成一些安全问题。不过可以用防火墙或是其他方式弥补。总比之前要等超时好。
改动的地方分布在几个文件里面,就不挨个列举了。
本来我给jagentx的开发者发了个邮件,告诉他这些改动,不过被退信了。所以我就把代码放这里,有需要的可以
修改了这两处之后,这个东西很就好用了,jagetnx网站上的文档有demo代码,可以参考。
为了让我的山寨服务器正规点,我还是去申请了一个enterprise number。申请的方法是到iana 的
添一张简单的表格,几天之后能收到回复,如果顺利通过,就会分配你一个数字号码,以后这个号码的 mp消息就代表你的组织的了。全部企业的enterprise number可以在
这个页面查到(很大的文本文件)。可以看到,我们的
是33364。
所以我们的 mp消息就在1.3.6.1.4.1.33364这个节点下面,我用 mpwalk就可以获得所有节点,包括新增的,这样就达到了免配置的目的。当然,到目前为止,我们还只是自己用于服务监控。
一切就绪之后,就可以选择你喜欢的工具来收集监控数据和画图了。比如常见的cacti。
这里是一张隐去了部分信息的cacti做出来的图。数据是从前面写到的这套东西收集上来的。
总结起来,这种办法适应于:
1 你有一个长期需要稳定运行的服务程序
否则你根本不需要监控
2 该程序有大量实例在运行
否则你用脚本把数据输出到 mpd都可以,没必要和我一样希望免配置
3 你不希望通过http或tcp连接来干扰该程序运行
否则你没必要用udp
写完了这篇blog,我也很希望能够侧面证明ginkgotek在保护客户利益上做的比别人多一些,选择我们的服务是可以放心的。
Posted by virushuo at
1:26 AM
3, 2009
这次beta沙龙请了
的团队来讲他们的经验。本来我是希望老高讲,不过他说最近的系统主要是许超前在带人开发,所以实际的演讲人是许超前。
国内最早让大家意识到网站的发展阶段的文档大概就是于敦德翻译的LiveJournal发展历程的 t。这次许超前的演讲非常类似LiveJournal的那篇。
手机之家用了7年时间,发展到1000万以上用户,3000万以上帖子,1.1TB附件,每天780万以上的PV这个规模。这个数字虽然比不上大型互联网公司,但是对一个只有几个人的技术团队,已经是一个很令人骄傲的数字了。
LiveJournal在发展中一边用着开源软件,一边造轮子,最后造出来了memcached这个简单而强大的工具,最终成了这一代网站开发离不开的东西。
这次演讲有意思的部分就是从memcached相关的事情开始的。
一 关于memcached的应用和管理。
memcached确实是个简单,好用,见效快的东西。不过简单也有简单的问题,程序员各有各的习惯,结果导致key很不规范,用什么方式的都有。这个问题恐怕用过memcached的人都深有体会。当然,用开发规范来限制程序员的行为是一个办法,但这不是技术的方法。技术的方法,是增加一个层。于是手机之家开发了一个cache管理器,把程序员和memcached隔离开,由这个层来统一管理缓存。
这是个不错的思想。当key被一个中间层接管了之后,事实上就可以给被缓存的对象实现更复杂的结构了。memcached是扁平的,只有一层。数据保存的方法仍然可以保持一层,但是通过对key的结构设计,就可以实现多层的结构,甚至在层和层之间实现继承关系,或是树结构。手机之家称之为name ace。通过这种方式,可以批量的管理和控制缓存对象。
换言之,索引结构可以复杂,但存放对象本身的地方是个key-value型的。friendfeed关于mysql应用的文档也提到了这种方法。用这种方法,可以在一个比较小的索引库中进行各种操作,无论是遍历还是查找,甚至处理一个节点下所有的值。最终得到key-value库的key。这个思路应该可以用于很多地方。
手机之家在cache上下的功夫很多,演讲稿中很多页是在讲cache系统的演变。对他们的应用方式来说,如果cache被击穿了,所有的压力到达了数据库,那么性能就会急剧下降,所以对cache的管理变的尤其重要。手机之家的这种尝试确实解决了很多问题。
二 仍然和cache有关
完成了前面说的cache管理器,他们还想更近一步,把数据访问,缓存,尤其是对库的切分整个包装起来,给程序员一个透明的接口。这样程序员不用关心到底存在多少个库,怎么分布,是否需要从cache中取数据等等细节问题。
这也是个常见问题。所有从数据库取数据的地方都要先从memcached读一次,代码很难看,也很罗嗦。这个包装完成之后,这就是一个能提高生产力的工具了。直接有效,也确实节约了开发成本。这个被他们称做DAL,很俗的名字啊:D
三 这样用java
php用来做以上的2个部件,效果并不好,效率很低。事实上php就不是干这个用的。最后他们用java+nio实现了一个性能不错的服务。把所有问题都解决了。
用在网页上java/j 确实不如j ,但是用来做服务器还是很合适的。我询问过他们是否在GC的时候遇到性能问题,***是目前还没有。如果稳妥起见,对于这种方案,我更愿意采用C,不过考虑到团队情况,和java程序员比C更容易找到,手机之家用java来开发也是一个折中方案。
总结手机之家经验分享的意义,我觉得在于,我们很少有机会看到一个网站从0做到接近千万的PV。就算在一个大的互联网工作过,所看到也只不过是冰山一角,很难有操刀动手的机会。手机之家的成长用了7年,老高始终在带着团队做优化。这种经验很难获得。
我们常常讲,做网站好像爬山,一个陡坡,一个缓坡。我见过很多网站在50万pv之下就被技术卡住了。很多很多的公司,就在某一次上坡的时候死了。
沙龙结束后,晚上,我和老高在gtalk上又聊了很久。我觉得他们做出来的这套方案,对很多公司都有帮助。至少跨越几个困难阶段。这就好像memcached带来的,在没有memcached的时候,很多网站抗不住10万这个级别的pv,有了memcached,哪怕用的很糟糕,50万这个级别也能到了。老高这个方案或许能让很多网站进入"百万俱乐部"。
说起来做互联网,中国人比外国人难很多。我们面对的用户规模比他们大的多,但是广告价值小的多。我们做一个网站,可能在第一年就碰上了第一次性能极限,但这时候钱还没有影。外国人可能3年才到达,但是人家已经赚了不少钱,也有足够的资源来解决问题。对中国的互联网来说,有一些这种解决方案确实很有帮助。
当然,未来还是未知的。老高和手机之家是如何期待这个产品的未来的?是开源,还是做解决方案?不管怎么说,至少我相信,他们做一个不错的轮子,应该不至于只给自己用。
更细致的还是请看
手机之家还在招聘 PHP/Java 人手,有意者给老高发邮件: gaochunhui@gmail.com
其他相关的:
大辉的:
余晟的:
老高的:
Posted by virushuo at 12:26 AM
March 23, 2009
某一天,喝了半瓶大二。然后我就想,我这到底算能喝酒还是不能喝酒呢?前几天喝的还没这个多,怎么就把笔记本丢了呢(这故事回头有时间再写)?
很久以前,喝多了酒,我就喜欢随便找个不规则物体,用微积分来算体积玩。后来就不玩这个了。现在比较喜欢写点好玩的程序或是找个命题来算概率。
想起来
的blog,而csdn blog因为不输出全文,基本被我排除出了订阅列表。于是就顺手扒拉了一个小程序,用来把全文抓出来,塞在r 里面,好订阅用。
结果今天比较清醒的看了看那天扒拉出来的程序,竟然还真能用。
所以就放这了。
这东西是基于magpier 做的。没什么特别的,写了一个基于token的解析器来解析文章,把需要的部分抓出来。这种方法在做语法分析器的时候很常见。当然了,您不能对醉鬼要求太高,所以我这个解析器只分析了单层标签,如果想支持多层的,只要加一个栈就可以了。我暂时用不到,不加了。
说起来php真是个不错的语言,简洁有力。字符串处理很强大。计算机这个家族里面,很大部分的机器是在做字符串处理和数据库工作,还有很大的一部分在做排序工作。所以一个字符串处理功能强大的语言就是最容易流行的语言。
我做了几个我要订阅的r :
g9的: http://blog.devep.net/tool/magpier /r .php?url=http://blog.csdn.net/g9yuayon/r .a x
阿朱的: http://blog.devep.net/tool/magpier /r .php?url=http://blog.csdn.net/david_lv/R .a x
用法很简单,就在后面加上csdn blog的r 地址就行了。你可以下载代码回去自己搭一个玩玩。
代码在:
很简单,很粗暴,很粗糙,也没什么版权,拿去随便干点什么用吧。
Posted by virushuo at
3:07 AM
March 15, 2009
是一个不错的r 抓取/解析工具,我本来打算自己写一个php的r 解析工具,不过试了一下magpier ,觉得还不错,能满足需要。
顺便看了看代码,记点笔记。
1 乱码问题
magpier 过去时常出现乱码问题,从0.7版本解决了这个问题
Version 0.7
-----------
- su ort for i ut and output charset encoding
based on the work in FoF, uses iconv or m tring if available
0.7之后的版本可以指定输入和输出字符编码,然后使用iconv或m tring函数进行编码转换。这个工作在 create_parser 函数里面完成的,如果两个函数都不存在,可以在r _fetch.inc 中让MAGPIE_DETECT_ENCODING为false,不检测和转换编码,否则就会出错。
一切正常的情况下,把r _fetch.inc中MAGPIE_OUTPUT_ENCODING定义成你需要的输出编码,比如UTF-8: define('MAGPIE_OUTPUT_ENCODING', 'UTF-8'); 就可以获得正确的输出结果了。
2 抓取方法
magpier 用了
作为http客户端来抓取r 。这个库比较完善,支持htt ,支持gzip。
需要注意的是,Snoopy用exec命令调用curl,然后返回结果,而不是使用编译进php的curl函数。默认的路径是"/usr/bin/curl",如果这里没有curl或是没有执行权限,就可能失败。不过只有htt 需要用到curl,普通的http访问是用fsockopen的。
同时,Snoopy可以使用代理服务器,但是magpier 没有使用,如果需要可以在r _fetch.inc中的_fetch_remote_file函数里面添加$client->proxy_host 和$client->proxy_port。
3 缓存
magpier 设置了一个默认3600秒超时的缓存。在./cache下放了一堆文件,文件名是md5之后的url+MAGPIE_OUTPUT_ENCODING,格式是php的serialize。
所以cache目录要可写。超时时间在r _cache.inc的var $MAX_AGE
= 3600;这行设置,也可以在创建cache对象的时候设置。
综合起来,这个库还是不错的,优点很多,也考虑了主机的各种情况,兼容性很好。函数形式的接口,很容易调用。不过应该先用head来取r 的http header,根据Etag来判断是否抓整个页面回来,这样效率还能再有提高。这个改动之后,cache就可以存在更长的时间,而不是一个固定的3600秒。同时我比较想把文章保存起来,以便以后用,这就需要数据库了。
我将来应该会基于这个东西发布一个新版本,把我想要的功能加进来。
Posted by virushuo at
2:31 PM
9, 2009
第一次
邀请的是
来分享他们的技术和产品设计。阅读器这个东西听起来不大,但是技术含量并不低。
下面这个图是我根据当时听的情况随手画的,不一定很正确,但是应该基本能够看到产品的架子。简单说来就是前端,web server ,缓存,存储。当然了,任何网站都得这么设计架构。
大概可以分成几个部分:
存储(这里主要说的是文章的存储),是基于关系型数据库和key-value库的结合。这里可以简单理解为mysql+bdb,关系型数据库负责保存索引和基础信息,占用存储最大的文章全文在key-value库里面保存。使用的时候,根据查询结果,通过key到key-value库中取回全文。基本可以保证灵活性和效率,也是相对比较廉价的方案。
缓存直接使用了memcached,memcached现在已经成了网站标准配置,在谁的架构中如果看不到类似的东西存在,反而会有点奇怪。有道阅读采用了一组memcached作为缓存,特别值得一提的是,他们在缓存中保存了24小时内所需要用到的全部数据。据说是经过多次实践的结果。我估计这个缓存的尺寸也不小,而且未来还会增加,不知道未来会通过什么方式来处理。但至少目前的一段时间内是够用了。围绕memcached的相关解决方案和patch已经相当成熟了,看起来有道也没有进行特别多的定制和改动。
web的部分比较值得一说。为了保证升级版本的时候,服务失效时间尽可能短,web的处理部分被拆成了一系列的Service,每个Service至少有一对实例承担正常的请求,在升级或是对某些模块进行改动的时候,可以依次对一对(或更多)实例中的某一个进行操作。这样整个应用并不会因为对某个Service的操作而停机。新旧模块的切换只在很短的瞬间(有道称之为"影子服务")。这种思想很类似SOA,不知道实际用起来感觉怎么样。我觉得接口的定义难度还是很大的。否则新旧Service切换的时候,其他相关的Service数据结构一旦不兼容,后果可能很严重。SOA的标准那么复杂,主要就是为了保持兼容和接口标准吧。当然,在一个产品之内,这种接口的定义相对容易点,毕竟复杂程度还是有限的。
用户界面部分使用JQuery,实际用起来响应速度相当不错。JQuery也是成熟的标准产品了,还是值得推荐的。
最后就是备份,除了几层日常备份,全部数据还在网易的存储系统上有一个更全面的备份,目前已经有20T的数据。在大公司内做产品就是有这种好处,轻松的解决了最困难的问题,实在令人羡慕。
总体上看,这个结构很规矩,没什么奇怪的地方,大量采用了现有的开源产品和方法。很务实。成熟的开源产品确实让开发工作变的简化了很多。
时间关系,还有很多细节没有说清楚。比如Service接口怎么定义,如何标准化,公司内部怎么来管理这些接口和文档,每天大量的文章如何抓取回来,如何管理等等。将来有机会再学习吧。
下面是现场的Keynote:
。除了上面说的技术方面,在产品方面还有很多值得看看的。尤其是"12个有趣的发现",这些发现是

参考资料

 

随机推荐