2008-01-20 Sun
作者:三糊涂
中国历史不厚道,把岳飞整成了一个“高大全”,给人的感觉,英雄根本不是个人儿。其实,岳飞远没有那么可恶,他有很多侧面,这些侧面,足以证明,他不但是人儿,还是咱河南人儿。
第一,岳飞酒性不咋地,“使酒不检”。
“使” 在这里的意思是“放纵”、“放任”,“检”在这里的意思是“约束”、“收敛”。一句话,岳飞是个酒徒,不醉不休。更要命的是,这酒徒酒性不咋地,醉了还揍人,且往死里揍。江南兵马钤辖赵秉渊陪岳飞喝酒,酒后差点被岳飞揍死。岳飞因此还受到了降级处分。可能是酒性太差了,所以传到了赵构耳朵里。赵构为此批评了岳飞。岳飞也算有种,从此不再饮酒。
我估摸着,岳飞的酒性受了地方风俗的影响。众所周知,岳飞出生于俺们河南汤阴,但刚出世就遭遇不幸,家乡发了大水,而那时的赵宋王朝没有整“最可爱的人”之类的勾当,所以只能由母亲抱着,坐在一只大水缸里胡漂,漂到了河南内黄并在那里长大。直到如今,酒风数河南,河南数内黄。糊涂俺曾在内黄搞过“社会主义思想教育”,领教过他们的传统酒风。喝酒都是用碗不说,且喜劝酒。劝酒时都是头顶酒碗,单腿跪地,被敬者想不喝?没门儿。所以岳飞的酒性,除了个人特质以外,应该还有个河南习俗影响在内。
第二,岳飞的文采是有限的,但歌词则可能是一流的。
有人把岳飞称作儒将,这种称法,值得怀疑。众所周知,岳飞和母亲漂到内黄,除了一口水缸,啥家产也没有,家贫是一定的,而大宋那时候并没有什么“希望工程”,所以岳飞只能是个失学儿童。有人说岳飞自小“拾薪为烛,自学成材”。所谓的自学,并不确切,至少其母应是他最早的启蒙老师。能在儿子背上刻下“精忠报国”四字,想来还是识得一些字的,至少不只这四字,所以岳飞也就不是文盲了。史书载:凡密奏,皆鹏自书。也就是说,给皇帝上密折的事候,岳飞都是亲自动手,不劳幕僚秘书的。相形之下,刘光世、韩世忠两个大老粗就不一样。当然,岳飞文凭到底是夜大水准还是电大水准甚或是家大水准,我就说不准了。反正他的《出师表》基本被公认为别人代作,甚至《满江红》也遭遇诸多质疑。前一阵子媒体哄传:香港知名歌星李玟听到《满江红》这首歌后,问身边的人:歌词是谁写的?身边人回答:岳飞。李玟一听特激动:能不能请岳飞给我写几首歌词?可惜李玟生不逢时,要是生在南宋王朝可能还有戏,保不准岳飞就能给她写首“亲爱的你慢慢飞”或者“月朦胧鸟朦胧”呢。因为岳飞除了《满江红》,据说还写了比琼瑶奶奶还穷摇的《小重山》:“昨夜寒蛩不住鸣。惊回千里梦,已三更。起来独自绕阶行,人悄悄,窗外月胧明。白首为功名。旧山松竹老,阻归程。欲将心事付瑶琴,知音少,弦断有谁听?”
第三,岳飞做过佃客,还做过城管。
岳飞稍大些的时候,曾到邻县安阳(糊涂俺的家乡)韩琦子孙家中,给韩家充当种地的佃客。史无记载,不知这佃客做得如何。就我个人的看法,河南有两县,民风很有意思。这两县是林县和内黄。林县人小气,小气到刻薄自己、虐待自己,细水长流着过日子;内黄人很大气,大气到上顿撑死,下顿饿死的地步。打了粮食后,堆在院里,猪拱狗啃、鸡刨鼠偷,总之是人与兽共享。糟蹋完后,人兽共饿。所以,岳飞的大气(岳飞不但养将士,还养好多文客,更舍得往他们身上流水般的花钱,以致于有些官员不断的弹劾他,说他军中非战斗人员超过三分之二,花钱花得州县们敢怒不敢言云云)可能也是内黄风气的影响。所以他这佃客,我估计做得不咋地,应该是吃了上顿没下顿的。
岳飞还在安阳的商市上做过冶安巡查员,名曰“游徼”。大约略相当于现在的城管。好在那时的安阳,还不会玩世界旅游城市、全国文明城市、全国卫生城市的花俏活儿,所以,我敢保证,岳飞做城管的时候,应该不会砸过小商小贩的摊子。至于是否讹小商小贩的酒喝,就不敢保证了。
两种打工方式,应该都不适合岳飞,所以从小到大,数次投军,充当“效用士”,但一直无出头之日。建炎元年(1127年)投奔河北路招抚使张所,受到张所赏识,这才受到重用,冉冉升起。
第四,皇帝不急太监急:赵构不生儿子,岳飞急得直哭。
1127 年,北宋灭亡。赵宋皇室近亲宗室都到金国做“访问学者”去了,宋徽宗的庶子赵构匹马渡江、扁舟航海,惊吓过度,虽做了南宋的第一任皇上,但却成了阳痿患者,迟迟生不出革命接班人。岳飞为此忧心忡忡,并且为此常对着自己的家属哭泣。在家犯傻也就罢了,但岳飞面对赵构也老犯傻,北伐前,首建高宗立皇嗣之言。有关革命接班人问题,别说武将干预乃是犯赵宋家的大忌,就是文臣,也不敢多嘴啊。所以高宗当即对他喝斥:“握重兵于外,此事非卿所当预也”。但是岳飞以后并不为戒,还是哪壶不开提哪壶。似乎不引起赵构对自己的疑忌,他就心不甘似的。
第五,首倡“攘外必先安内”说。
后世的慈禧太后和蒋介石,都算是岳飞的高足。一个说“宁给友邦勿给家贼”,一个说“攘外必先安内”。这两高徒可能知道,“安内攘外说”乃是岳飞首倡的,岳飞是这样跟自己的统治者倡议的:“内寇不除,何以攘外?近郊多垒,何以服远?比年群盗竞作,朝廷务广德意,多命招安,故盗也玩威不畏,力强则肆暴,力屈则就招。苛不略加剿除,蜂起之众未可遽殄”。
除了“攘外必先安内”之外,看意思,岳飞还不主张对义民招安,所以讨伐国内农民起义,岳飞出力最大。高宗亲笔书写“精忠岳飞”四字,绣成一面军旗赐给岳飞。但岳飞认为此乃区区之功,战胜金军,那才是大功,他说:“痛念二圣远狩沙漠,天下靡宁,誓竭忠孝。赖社稷威灵,君相贤圣,他日扫清胡虏,复归故国,迎两宫还朝,宽天子宵旰之忧,此所志也。顾蜂蚁之群,岂足为功”。一句话,对岳飞来讲,灭农民起义,跟灭蜂灭蚁一样小菜、没劲!
第六,岳飞的崇拜偶像及人生理想。
岳飞喜欢关张二人,不喜欢曹操。把诸葛亮认做榜样,希望与关张齐名。曾对部下说:“使某得进退禀命于朝廷,何功不立?一死乌足道哉!要使后世书册中知有岳某之名,与关、张辈功烈相仿佛耳。”
有人据此认为,岳飞真的没文化,否则不会把关张当作偶像。我的感觉,除此之外,岳飞这人很在乎功名的。考证他的章句,他所谓的功业应该包括:扫清胡虏、收复故国、迎回二帝、置金为藩。结果这些都没完成。当然,完成后,高宗最大的敌人就不是金国而是岳飞本人了。众所周知老赵家的江山是怎么来的,众所周知赵老太爷当年也是挺厚道的一个人儿。所以,岳飞功业未完成,但功名有了—大大的民族英雄!站这个角度,他也算实现了自己的理想,比关张功名高出不只一截吧!?
第七,岳飞不够意思,岳飞老婆也不够意思。
岳飞不抱养二奶。但这并不意味着他是个好男人,顶多算是个好儿子。岳飞特孝顺母亲。俺们河南传统(也叫儒家传统吧),男人心里只有老娘,没有老婆,老婆不是内人,是外人。岳飞从军至北京时,岳母及儿媳刘氏留居俺们安阳。后来,岳飞把母亲接走了,却没有接老婆,也不知两人咋想的,反正“军功章有你的一半也有我的一半”这类歌他们没有对唱过,,刘氏竟改嫁他人了。人家都是家里红旗不倒,外头彩旗飘飘。岳飞这是家里红旗插外头。后来,韩世忠收留了刘氏,并谕令岳飞 “复取之”,岳飞给刘氏“钱三百千”。同志们,俺数学不好,不知南宋的三百千钱是个什么概念。但据此,岳飞被人评价为“事母至孝,于妻有义,于子甚严”。如此看来,岳飞应该是个好儿子、好丈夫、好父亲了。但是在我看来,岳飞对老婆不够意思,战乱期间只接老娘不接老婆;老婆对岳飞也不够意思,趁战乱期间就自己拾掇拾掇改嫁了。女人都这样,中国还咋不可战胜啊。可能这老婆没文化吧,不知大宋的“八荣八耻”明确规定“女人以守活寡等老公为荣,以不守节改嫁人为耻”呢。
第八,岳飞点兵,多多不益善。
韩信傻,傻就傻在他面对老大刘邦时的那句交待:韩信点兵,多多益善。最后被刘邦老婆给灭了。岳飞比上韩信,傻劲儿也不逊色。虽然嘴上不说,但行动却很明显,老想多捞俩兵。你说你捞兵是为了打金,那当年赵家老太爷领着全国兵马还说是为了打辽呢。所以,往事并非如烟,谁信谁呢?绍兴七年(1137年),刘光世由于畏敌怯战,沉湎酒色,在大臣中引起了公愤。高宗一时糊涂,也认为兵合则雄,遂决定解除刘光世兵权,将其军队交给岳飞统管。问题是高宗过后就后悔了,不知是想起了先祖的第一桶金—陈桥故事,还是身边的文臣提醒了他(这些文臣不见得是人家秦桧),总之,赵构不再把刘光世军队给岳飞了。岳飞愤然辞职,且不等高宗批准,就擅自上庐山,为亡母守孝去了。岳飞这一举动,在当时是明显的“抗上” “要君”。若放在明清,差不多够“凌迟”了。但高宗再不高兴,也无可奈何,三次写御札给岳飞,命其复出治事。并命王贵与李若虚往庐山敦请岳飞下山。说,请不出岳飞,你俩就死啦死啦的。两个人到庐山好说歹说,连哭带叫,岳飞拖了好几天才同意下山。你会说,不就几个兵吗?是啊,不说岳飞带兵多少,只说刘光世之兵,占全国兵力的五分之一呢。赵构敢给,有些大将还不敢接呢。因为对赵构来讲,宝座没坐稳时,对武将们很宽容,坐稳之后,就想削将权。所谓的岳家军、韩家军,仅听名称就有问题,说明南宋军队很私有化。军队私有化才有战斗力,问题是军队私有化对皇权威胁也最大。所以连当时的主战派李纲也上疏表示忧虑。为此,高宗专门对辅臣们表态说没事没事儿。但他心里是有事的,他也不傻,武将们越来越不把他当回事,他也不是看不出来。岳飞可能没有私心,但是一直要兵,赵构再不疑忌,那他就不适合干皇上了。问题是岳飞既不了解赵构的心病,又昧于大宋重文轻武的传统,刚跟赵构扛过这么一回膀子,绍兴八年二月即再次上奏请求增兵,高宗很老实的告诉他:“上流地分诚阔远,宁与减地分,不可添兵。今日诸将之兵,已患难于分合。末大必折,尾大不掉,古人所戒。今之事势,虽未至此。然与其添与大将,不若别置数项军马,庶几缓急之际,易为分合也”。一句话,不能再给你兵了,否则不是你完就是我完,奈何岳飞听不懂或者假装听不懂。所以朱熹对岳飞的评价是:有才,但也有些横!岳飞最横的表现是最后那一手:赵构让他不要轻举妄动,他偏偏北上迎敌;赵构连下十二道金牌,他都拒不班师。哪个哥们儿敢这么跟皇上横啊,其结果,当然是“一朝横死”了。绍兴十一年七月,秦桧党羽万俟呙弹劾岳飞公开放弃楚州等三条罪状,负责审计的御史中丞何铸审阅案件后,向秦桧表示,岳飞是冤枉的。桧说:“此上意也”。确实是上意,因为高宗亲自出面,咬定岳飞倡言楚州不可守,其意在“附下以要誉,……朕何赖焉”。有人说,岳飞是“以忠义挟皇上”,跟赵构所言的“附下以要誉”应该是一个意思。最后,赵构成全了岳飞,赵构臭遍了,岳飞则名誉满天下,人生理想实现,应该死也瞑目了吧!
大师说我的戒指在柜台里慢慢长大呢。因为他在我死缠烂打之下同意用3个月的工资给我买一个戒指。我先不提,等3年。
陈:你说我们俩哪个姓好听呢?
陈:要不看看历史上哪个名气大?
陈:冯?
冯:冯诺依曼
陈:陈?
冯:陈世美
陈:你怎么这样!
冯:其实我无所谓的
陈:那么当然是陈好听了,陈,陈硕鼠!


其实周6在睡觉的时候,就收到快递公司的电话,问我们周末是否上班,我就让她直接把书送到公司了.
书是从Itpub的贝贝哪里买来的,和同事一起买了两本,总共花了我156.01RMB,不算贵.
对了,书名是 Oracle 高可用环境,当然是Piner写的了,据说全国还未正式上市,先睹为快了.本来那天准备在Piner哪里去忽悠本书的,结果那家伙说要我请吃饭,请吃饭就请吃饭呗,还要带8个兄弟一起来,想了想,我靠,我好像没有那么多钱请吃饭.书总算到了.
印刷很不错,可惜今天早班没有时间详细阅读,只是翻开放在桌上,装装样子,有了书,相信晚上睡不着的时候,可以拿来催眠,好像我一看技术书籍就会睡着,坏习惯,一定要改过来.
无论如何,感谢作者将经验分享出来.
We believe all of the billing errors to have been corrected as of the morning of Friday, January 18, 2008. If your credit card was wrongly charged, the charges have been refunded. We saw some reports that an expected refund did not appear, but upon investigation the refund had indeed been processed on our side and had just not yet made its way to the bank. We have not seen any cases where a refund has not been issued. It can take several days for refunds to appear back on your credit card or in your bank account and that is unfortunately entirely out of our hands.
And remember…
If this/these erroneous charge(s) by us resulted in you having any sort of overdraft/bounced check/nsf fee from your financial institution, please contact our support team from the web panel. We’d just like to request that you include a copy of your statement with the necessary info showing the fees. It can be either a paper statement or a print out of your online statement, or even a screenshot of your online statement and it can be scanned and attached to your support message via our support form or faxed to us at 714-990-2600. If you fax it, please be sure to write your domain name or DreamHost account number on the fax. When we get this, we will put money on your credit card equal to the amount your bank charged you, as well as give you a DreamHost account credit for the same amount on top of that.
We will do our best to correct any problems stemming from this error.
In case you have not seen it, we have posted information about this situation in three separate blog posts on our official blog…
http://blog.dreamhost.com/2008/01/15/um-whoops/
http://blog.dreamhost.com/2008/01/16/the-aftermath/
http://blog.dreamhost.com/2008/01/17/the-final-update/
“你别吹这首曲子,这是首美国歌!”电影《虎口脱险》指挥先生跟那个英国飞行员在家里有这样一句对白。这首歌的名字叫《鸳鸯茶》(Tea For Two)。《虎口脱险》开头就交代了:一架英国皇家轰炸机,夜袭德国,哲次行动的代号:鸳鸯茶。
这首《鸳鸯茶》在电影中反复出现过几次,我一直想找到这首歌,后来我一查,有好多人演唱/演奏过这首作品,是一首很有名的爵士乐曲,不过我懒得去找这首歌的出处,找了好长时间才找到电影里说的“美国歌”,不知道是谁唱的。好吧,这次《音乐时间》就用这首歌开头吧。
我总希望用一首相对轻松的歌曲开头,然后再放一些难听的歌曲。
当然,接下去再来两首更轻松的,我突然想起来,唱片保存的时间问题,据说可以保存50年,后来又听说是20年,听到最悲观的说法是10年。如果是后一种说法,我有50%的唱片估计要完蛋了。于是我赶紧从唱片架上取下一张当初在地摊上买的盗版,放进电脑里播放,果然,后4首歌放不出来了。这张唱片的名字叫《荷东》,一张Disco舞曲唱片,想当年这是最流行的舞曲唱片,用它蹦迪和跳霹雳舞很合适,但我只会走两步太空步,由于姿势不协调,很像太恐怖。不过我手里这张其实不是当年的“荷东系列”,而是欧洲迪斯科,它基本上来自德国。有一首C.C.Catch演唱的Jump In My Car,歌手来自荷兰,当时她唱过很多在迪厅里走红的歌曲;还有一首是一个叫Silent Circle演唱的Touche In The Night,现在听起来,还是比较亲切的。当然,今天的你可能更喜欢什么鸡巴Trance、Techno、Breakbeat、Chill Out、Lounge……这类小资热衷的玩意儿,对当年流行的东西不感兴趣。
对了,去年有一件感动英国的事情,一个手机推销员唱了一首《今夜无人入眠》,结果不仅让自己一炮而红,而且还让全世界心比天高命比纸薄的人们无法入眠,他感动了全世界。这是一个从来都存在的灰姑娘的故事,只是这次改成了一个胖子,一个叫Paul Potts的小子,他现在出版唱片了,他不再去卖手机了,他手机里的彩铃已经变成了《今夜无人入眠》,不过我昨天给他打电话的时候,彩铃已经改成了这首Time To Say Goodbye。和一段人生说再见也是一种境界。
有感动英国就有感动中国,胡紫薇老师确实感动了我们——那些男秦香莲和女秦香莲们。最近接二连三有感动中国的事情发生,周正龙向全国人民普及了生物常识,他的执迷不悟从开始对他的批判变成了让人感动,我记得鲍勃·迪伦老师说过:“一个人要上多少次山,才能找到华南虎?告诉我,朋友。答案在他妈的风中飘荡。”那个史上最强的小三让人觉得做潘金莲也不错;还有那个从24楼上做自由落体状的姜岩也感动了很多网络暴民……如果秦香莲健在,看到自己徒子徒孙满堂,她还会是怨妇吗?我既不喜欢秦香莲,也不喜欢潘金莲,都他妈是道德紧箍咒。但鉴于胡紫薇老师的人体道德炸弹的原子弹效应,我还是想送她一首歌,Axelle Red的Rester Femme(能听明白的同学你大概知道在唱的是什么)。Axelle Red就是那个在1998年法国世界杯上跟那个塞内加尔歌手合唱歌曲的比利时歌手,比利时人我就认识三个:一个是撒尿拯救布鲁塞尔的于连,一个是大侦探波洛,还有就是这个女歌手。
去年我拍DV的时候,用过一首歌,Zillertaler Schuerzenjaeger的Appenzeller,好多人喜欢这首歌,这首歌的演唱方式叫“悠得尔”,什么叫“悠得尔”呢?就是演唱的时候运用一些颤音、滑音、假声作修饰,让你听着很好玩,据说这种唱法是从非洲传过来的(更具体内容详见即将再版的《来自民间的叛逆》)。这次再介绍一首歌,Mary Schneider的Cuckoo Yodel,这首歌你一定听过。Mary Schneider最擅长的就是把很多古典名曲“悠化”,比如《胸压力舞曲》《溜冰圆舞曲》,她的嗓音在这时候就是一件乐器。另一首歌是Alpentrio Tirol的Jeder Herzschlag ein Jodler。另外再介绍一首德奥地区的民歌,这个演唱者我查了一下,好像是德国的一对兄弟组成的团体,唱一些传统民歌,叫Die Amigos(相当于德国的侯耀文和石富宽),这首歌叫Dann Kam Ein Engel。由于大部分资料是德语,我的德语只限于说一句“我想跟你做爱”(ich will mit dir schlafen),其他都不会了。哪位同学德语比较好,简单介绍一下。
我现在很喜欢希腊女歌星Haris Alexiou,从上个世纪70年代开始,她就出版唱片,唱了好多好多,好多好多的歌液,这次推荐一首Koita Mia Nyxta。然后再推荐一首墨西哥歌手Julieta Venegas演唱的歌曲Limn y Sal,之所以推荐她是因为我觉得她的演唱跟其他墨西哥歌手的演唱方式不太一样。至于为什么不一样,我也不知道(这不是废话么)。然后我们再去澳大利亚,那个举办过奥运会的悉尼,有一个兄妹组合叫Angus and Julia Stone,Julia Stone是那种典型的小女生。我记得我很早以前听到Frente!的时候就开始怀疑过人生,外国女人都长得很彪悍,一个个都跟罗永浩老师一样,怎么唱起歌来那么温柔可爱?后来等我认识罗老师之后才知道,原来有一批女生都这样,长了一副徒有其表的彪悍外形,其实内心还是很小女生的。后来我又听到一句名言:“女生,只有小女生才能成为摇钱树。”祝罗老师好运。这首小女生的歌曲The Beast献给敬爱的罗老师。然后我们再去挪威,听一首Magnet和Gemma Hayes合唱的一首鲍勃·迪伦的名曲Lay Lady Lay,叫Magnet的人可真多,其实这家伙是挪威人,这首歌出现在电影《史密斯夫妇》中,如果你还记得,想想是在哪个场景里出现的,我没看过这部电影。好,现在挪步,到意大利,介绍一个意大利歌星Eros Ramazzotti给你,据说这位歌手在意大利跟帕瓦罗蒂齐名,如今帕瓦老师不在了,就剩他一个人跟自己齐名了。我听了他的几张专辑,确实好听啊,这次介绍一首Più Bella Cosa。然后再去趟南非,介绍一个叫Lucky Dube的歌手,以前我听过他的专辑,就是那种很典型的Reggae音乐,我一直觉得,Reggae听听鲍勃·马利就行了,听别人的也差不多,说的事情也是黑人与政治的关系,但是这次听到Dube去年的新专辑Soul Taker之后觉得很不一样,弄得很奢侈华丽,看来这位老兄最近发财了(他的唱片在南非一直很畅销),听听这首Re你妈ggae风格的歌曲Romeo。
妈的,带你们去这么多地方,其实我连香港都没去过。
最后这几首歌都是大路货,名单如下:
Andy Tubman:Quiet Inside
Miami Sound Machine:Words Get In The Way
Robert Plant and Alison Krauss:Rich Woman
The Beatles:Eleanor Rigby
The Clientele:Isn't Life Strange
Viktor Lazlo:Stories
作者:Fenng 发布在 dbanotes.net. 订阅 DBA notes
最开始看到和菜头对这本书的评论。看书名还以为是一本偏学术的书,看评论似乎又不是,心痒难当。偏偏在 Amazon.cn 订书之后,快递来公司送了几次,我都因加完班在家睡觉而不在,直到最后终于前台 MM 替我代收,算是好书多磨。
陈老先生一生经历独特,且身为名医,上至达官贵人、下至贩夫走卒,三教九流皆有接触;况且本人又有记日记的好习惯,所以回忆起来就好似一部老式黑白摄像机,替大家还原了一下银元时代的老上海生活。旧时的生活习惯、典故娓娓道来,非常过瘾。八卦一下,陈老先生还曾是老版《上海滩》特别顾问。
或许过去我们都太轻视传统了,读罢此书算是补了一课。最大的一个感慨是,民国时代是中华民族最差的一个时代,也是最好的时代。
这半年来看过的书里面,何兆武的《上学记》和这本《银元时代生活史》有的一比。接下来计划把《抗战时代生活史》买来看完。
--EOF--
相关文章|Related Articles
评论数量(0)|Add Comments
本文网址:http://www.dbanotes.net/review/life_history_about_silverdollar_era.html
最近作者还说了什么? Follow Twitter / Fenng
累積太久沒寫,有些議題剛好可以合併起來看…
第一個想到的是 MySQL AB 被 Sun 買下,以及在 Slashdot 上看到有人認為 Google 的 MapReduce 成功是 Computer Science 界的一大退步 (MapReduce — a Major Step Backwards?)。
把時間點再往前,拉到 Oracle 買下 Innobase Oy 及 Sleepycat Software (Berkeley DB) 兩家公司時一般的反應 (分別是 2005 年十月、2006 二月),以及買下後的進展…
Oracle 買下 Sleepycat Software 後推出的 Berkeley DB 4.5 多了 Replication 的功能,並且在 Berkeley DB 4.6 對穩定性及大幅度修正。InnoDB 則是不斷的改進穩定度及效率,仍然是目前 MySQL 裡最常被使用的 Transactional Engine。以現在看起來,其實 Oracle 並沒有打算要以這個手段打擊 MySQL。
話題回到 Slashdot 那篇 MapReduce,其實在 comment 有人講得很清楚了:簡單的東西並沒有什麼不好,重點在於能不能解決問題。如果能用簡單的方法解決問題,就不要拿複雜的方法解決,25 年前就發展出的技術並沒有什麼不好。
另外我提一下,最近寫過後才發現 Berkeley DB 其實相當好用 (支援 Transactional Operation 及 Replication),沒人用的原因是 PHP/Perl/Python/Ruby 上的 Library 都沒有把實做所有的功能,目前只有標準的 dbm operation 而已。換句話說,如果你要用這些好用的 Operation 得自己刻 C/C++/Java。由於開發上的問題,很多人寧可用 MySQL 放…
由於 Berkeley DB 看起來很棒 (傳言 Bloglines 與 Google 的使用者資料都是用 Berkeley DB 為底層架起來的),初期的目標是希望有個 Reliable DBM-style Database,類似 Amazon SimpleDB 的軟體放使用者資料,透過 TCP connection 與 PHP 端溝通…
幸运的是,在年前已经有一些订单开始签订。
昨天帮一个客户恢复了一个断电崩溃的数据库,是海量存储(T级以上的),对于用户来说,即使作一个临时的备份也不可能,无法找到足够的存储空间是一个问题,更重要的是,无法承受极长的停机时间。
而恢复的不确定性,采取手段的安全性也颇值得斟酌。
经过权衡,客户和我签订服务协议,委托Eygle.Com进行数据恢复服务。
整个恢复过程大约用了2个小时,处理一些后续的ORA-600错误也耗用了一些时间,最终数据库成功恢复到无故障状态,业务完全恢复正常。
顺便解决的另外一个问题可以说一下,另外一个数据库启动时报出ORA-03113错误,数据库无法启动。
ORA-03113 end-of-file on communication channel Cause: An unexpected end-of-file was processed on the communication channel. The problem could not be handled by the Net8 two-task software. This message could occur if the shadow two-task process associated with a Net8 connect has terminated abnormally, or if there is a physical failure of the interprocess communication vehicle, that is, the network or server machine went down.
先不理这个错误,我首先去查看alert文件,ls -al一下发现alert文件已经达到了2147483647大小。
2147483647是多大呢?
SQL> select 2*1024*1024*1024 -1 from dual;
2*1024*1024*1024-1
------------------
2147483647
正好是2G少1 byte,也就是说这个文件超过了OS的限制,最终导致数据库启动不了。
处理一下这个文件,数据库即刻恢复正常。
btw:这是一个附送的维护服务:)
目前加盟:北京弗洛格科技有限公司,提供对外技术服务,欢迎大家支持!。
-The End-
相关文章|Related Articles
- 恢复8.1.6的数据库 勿忘svrmgrl
- 用Rman的Plus archvielog选项简化数据库备份
- 丢失所有文件、拥有全备份,缺少后增加的文件
- 无文件备份、拥有所有归档的恢复
- 使用热备份进行分时恢复
评论数量(16)|Add Comments
本文网址:http://www.eygle.com/archives/2008/01/poweroff_recovery_case.html
网站: JavaEye 作者: robbin 链接:http://robbin.javaeye.com/blog/157731 发表时间: 2008年01月20日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
JavaEye网站从2006年9月11日上线基于RoR的2.0版本开始,到现在已经运行了将近一年半了。在这一年半的时间里,JavaEye网站的每日PV从最开始的5万,缓慢增长到了现在的60万。随着网站负载的不断增加,我们也在不断尝试和调整网站的性能,积累了不少第一手RoR应用性能优化的实战经验。虽然我们并不是RoR性能优化的权威专家,我们所积累的经验也许并不是最优实践,但是作为国内最早涉足RoR商业运营的互联网网站之一,我们非常乐意分享和交流我们的实战经验,以帮助后来者节省必要的摸索时间。
RoR惊人的开发速度恐怕是每个互联网创业者都梦寐以求的,但是随着网站流量的不断增大,可能大多数采用RoR的网站或迟或早会遇到RoR的性能瓶颈,我的一个朋友capitian说过一句很有意思的话:“RoR应用做到后来,总有自己修改底层的冲动”。就我所了解和掌握的情况来看,很多RoR网站都过早的遇到了性能瓶颈,一个很普遍的现象就是:RoR应用的CPU负载要远远高于数据库的负载。这是一个有点违背常理的现象,因为我们知道,硬盘IO速度要比内存慢得多,所以一般Web应用的性能瓶颈往往会出现在数据库IO上,因此优化数据库访问,进行对象缓存是非常有效的性能优化手段。但是一旦应用服务器负载比数据库还高的话,单纯的对象缓存就无用武之地了。下面我们从几个方面分别谈一谈如何进行RoR的性能优化:
应用的部署
RoR应用的部署包括操作系统,Web服务器,应用服务器和数据库四个方面:
一、操作系统
1、发行版本
RoR适合于部署在Unix类操作系统上面,通常比较多的人使用RHEL/CentOS/Ubuntu,我们比较偏爱SuSE Linux,对于我们服务器使用的AMD Opteron x86_64的CPU来说,SLES要比RHEL有更多的优化。另外应该尽量使用64位版本操作系统,以充分发挥x86_64 CPU的性能,并且x86_64的Linux很多Kernel参数也大很多,代价就是需要更多的物理内存。
2、文件系统
Linux最常用的文件系统是ext3,但我们使用的是Reiserfs文件系统。Reiserfs在读写大量小文件的目录性能非常高,即使处理目录下面直接存放10万个文件,性能仍然不会下降。我们知道默认情况Rails会对每个浏览器会话在硬盘生成session文件,一个繁忙的网站,临时文件目录下面有上万乃至几万个session文件是很常见的现象。对于这种目录下面几万个小文件的存取,reiserfs要比ext3性能高一个数量级。如果希望对session文件有更好的存取性能,可以把临时目录链接到Linux的内存文件系统/dev/shm目录下面,这样实际上session文件的存取都是直接内存操作了,这种方式唯一的问题在于不能支持群集部署。如果你已经升级到了Rails2.0,可以采取把session保存到Cookie里面的方式,既可以避免服务器处理session的开销,而且还支持群集部署,是大规模网站部署的首选方式。
3、内核的网络参数调整
对于流量很大的网站来说,默认的Linux内核网络参数偏小,因此如果你的网站流量非常大,或者上传下载大文件比较多,可以针对性的调整内核网络参数,扩大内核的TCP接收数据和发送数据的Buffer缓冲区大小,比方说:
net.core.wmem_default=262144
net.core.rmem_max=262144
net.core.wmem_max=262144
net.ipv4.tcp_rmem=4096 65536 524288
net.ipv4.tcp_wmem=4096 65536 524288
参数具体调整,可以Google相关的Linux内核参数的文档,这里不展开详谈。
二、Web服务器
Web服务器首选Lighttpd,因为Lighttpd在和后端的应用服务器通讯方式上做了足够的优化:当POST大数据量的时候,Lighttpd在完整的接收客户端浏览器的数据之后,才会一次性发送给应用服务器;同样的,Lighttpd也是一次性把应用服务器处理的页面数据全部接收,不设置Buffer Size的限制。因此Lighttpd能够尽最大可能的减轻应用服务器的负担,减少应用服务器用于处理数据传输的延迟,更加有效的利用应用服务器资源。这方面的详细的论述请看:RoR部署方案深度剖析。
关于Lighttpd的安装可以参考在Linux平台上安装和配置Ruby on Rails详解,这里仅谈Lighttpd的性能优化的几个要点:
1、网络IO调度方式
Linux Kernel 2.6支持sysepoll方式调度网络IO,能够处理极高的并发连接请求,Lighttpd可以通过配置文件打开sysepoll支持:
2、网络IO传输方式
Linux Kernel 2.6支持sendfile方式传输数据,Lighttpd可以通过配置文件打开sendfile支持:
此外Lighttpd还支持应用服务器参与的文件下载控制X-sendfile,详细的论述请看:RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能
3、文件状态缓存
Lighttpd通过stat()调用获得文件被修改的信息,来决定当请求同一个静态文件资源的时候,是否需要再次读取硬盘文件。但是每次stat()调用也有一定的开销,Lighttpd支持通过Fam Server来减少stat调用。即每次当文件被修改之后,Kernel会发送一个消息通知Fam Server,而Lighttpd会通过进程间通讯连接Fam Server,可以知道文件是否被修改的信息,不必再每次调用stat()。
4、限定POST Size
为了避免黑客恶意的攻击服务器,伪造超大Post数据包轰炸Web服务器和应用服务器,可以限制Request请求的大小,例如限制为10MB:
5、日志文件
Lighttpd是单进程单线程的服务器,调度网络IO性能是极高的,但是在某些极端情况下,单进程服务器也有风险,即一旦被某操作系统调用挂住,整个服务器就没有办法响应请求了。比方说服务器其他进程导致的IO WAIT很高,操作系统的buffer又不够的时候,Lighttpd在大量的写access log就有被挂住的可能性。因此如果Lighttpd日志对你的参考价值不大,可以考虑关闭掉。像JavaEye网站每天Lighttpd产生430万条log,对硬盘IO也是一个不小的负担,既然已经开着Rais的production.log,那么Lighttpd的access log没什么参考价值了,那就关掉它。
Lighttpd的性能优化请看其作者写的文章:
http://trac.lighttpd.net/trac/wiki/Docs%3APerformance
三、应用服务器
Ruby的应用服务器可以使用FastCGI,或者Mongrel,如果我们使用Lighttpd的话,FastCGI是最好的搭配。
1、FastCGI和Lighttpd的通讯方式
如果FastCGI和Lighttpd是在同一台服务器,那么建议采用Unix Socket通讯,这种通讯方式比TCP要快一些,FastCGI可以通过Lighttpd自带的spawn-fcgi命令行工具启动,创建socket文件,而Lighttpd监听socket文件。如果两者不在同一台服务器,需要群集部署,那就必须采用TCP Socket通讯,方式是一样的。
2、FastCGI进程应该开多少个合适?
Rails是单进程方式运行的,理论上来说,开几个FastCGI进程,就只能并发响应几个请求。对于繁忙的网站来说,峰值期间每秒有几十个动态请求是很正常的事情,但实际上FastCGI进程并不需要开那么多。这是因为前端的Web服务器在处理用户浏览器连接,发送Request请求需要相当长的时间,在FastCGI处理完请求释放该连接以后,Web服务器还需要相当长的时间才能把页面数据完整的发送到客户端浏览器。用户在点击一个链接以后,等待1-2秒,页面内容就显示出来,这对用户的感觉来说已经是非常快的了,而FastCGI用于处理该请求可能只需要0.1秒,那么一个FastCGI进程虽然并不能够真正的并发运行,但实际上的效果是他可以在1秒之内处理10个请求,让10个用户在同时访问网站的过程当中感觉不到明显的延迟。
因此FastCGI需要开多少个,取决于你的网站峰值期间每秒有多少个用户请求过来,而你的FastCGI又能够以多快的速度处理请求。比方说你的网站峰值期间每秒有50个动态请求,FastCGI在峰值期间处理每个请求需要0.2秒,那么实际上你只需要开10个FastCGI进程就足够了,为了应付突发的峰值请求,你可以在这个计算量上面增加一些余量,比方说15-20个进程,肯定是绰绰有余了。
关于FastCGI的性能优化,可以参考Lighttpd作者的文章,虽然他是针对PHP跑FastCGI写的,但对RoR也有参考价值:
http://trac.lighttpd.net/trac/wiki/Docs%3APerformanceFastCGI
四、数据库
JavaEye网站使用MySQL5.0.XX版本,数据库引擎是InnoDB。关于MySQL数据库的调优,推荐大家看MySQL Performance Blog,作者是一个MySQL性能调优方面的专家,并且提供MySQL咨询服务。他的博客上面有很丰富的关于MySQL调优的文章和演讲文稿,特别是关于InnoDB方面,非常深入。JavaEye的数据库调优就是根据他的InnoDB演讲文稿来调整的,一般说来,有几个需要调整的参数:
innodb_buffer_pool_size
这个参数很重要,越大越好,对于专用的数据库服务器一般建议开服务器内存的50%以上。
query_cache_size
查询缓存,对于查询的性能提高有很大帮助,但不宜开得过大,查询缓存的过期可能很频繁,过大查询缓存反而降低性能,增加服务器开销
innodb_flush_method = O_DIRECT
针对InnoDB的数据文件,关闭操作系统的文件缓冲,由于InnoDB自己有巨大的Buffer Pool,操作系统对文件的读写缓冲功能反而会降低MySQL的InnoDB的IO性能。
最后针对数据库的SQL优化来说有两点原则:
1、对数据库表要适当的创建索引
特别是出现在where查询条件当中字段,和关联查询当中的外键,要高度注意。
2、尽量避免大表的全表扫描和数据库的硬盘IO
查询比较慢的SQL要explain一下,看看是否发生了全表扫描,采取各种措施减少或者避免大表的全表扫描问题,例如拆分表等等。
最后针对MySQL数据库运行情况,我们可以用show status; 和 show innodb status\G 来监测。
Rails应用程序的优化
Rails应用程序优化包括ruby解析器的优化,缓存的使用,以及应用代码级别的优化。Stefans Kaes曾经在Railsconf 2006有一个Rails应用程序优化的演讲,他的演讲PPT是极好的Rails性能优化指南,可以在这里下载:http://www.javaeye.com/topic/24508。他还编写了一个用于Rails性能测试的软件包RailsBench,大家可以参考。由于Stefans Kaes的代码优化文档已经写的非常详细了,因此我就不在一一复述,只提出几点对性能影响比较大的方面:
一、ruby解析器的优化
ruby的解析器性能是很糟糕的,ruby早期的主要用途是取代perl写批量处理的脚本的,并不是为服务器应用编写的,因此在内存分配策略上非常不适合服务器应用。Stefans Kaes编写了一个ruby GC的补丁文件,在railsbench下载包里面提供了。虽然当前Railsbench提供的GC补丁只有针对ruby 1.8.4和1.8.5版本的,但是在ruby 18,6上面使用1.8.5的GC补丁也完全没有问题。GC补丁的作用主要是针对Rails应用开大了ruby的内存堆,可以有效提高内存堆的利用率,降低GC的频率。根据Stefans Kaes提供的测试数据,打补丁并且调整参数以后,GC的频率下降到只有原来的1/10还不到。降低GC频率尽管并不能够提高单个请求的执行速度,但是可以增加整体应用的负载能力。
我们在JavaEye的服务器上也使用了GC补丁,并且根据推荐参数进行了调整。在使用GC补丁之后,Web服务器的CPU负载下降了大概15%左右,效果非常显著。当然开大内存堆的代价就是ruby进程会多消耗内存,在我们的服务器上,ruby打补丁之后多消耗了50%左右的物理内存。
二、缓存的使用
1、对象缓存
JavaEye上面关于对象缓存的讨论很多,我们也提供了JavaEye这方面很多数据,因此不展开了。RoR可以使用两个对象缓存,一个是CachedModel,类似Hibernate,比较简单,对Model的CRUD操作自动进行缓存;另外一个是cache_fu,需要自己编码来添加对象缓存,但提供了更多高级机制,目前我们使用的是cache_fu。在使用对象缓存的情况下,应该把查询方法的:include去掉,避免关联查询无法利用缓存的现象。
2、查询缓存
对于统计类耗时查询,如果不要求实时性,那么可以使用memcache-client将查询结果缓存到memcached里面,例如博客排行榜之类。
3、页面局部缓存
对象缓存和查询缓存都是降低数据库访问负载的,但如果RoR的负载很高,那么只能依靠页面局部缓存了。传统的互联网web1.0网站很流行采用动态页面静态化技术来提高网站的负载,但是对于web2.0网站来说,每个页面都带有登陆用户的个人信息,页面的很多部分需要实时更新,例如投票,点击统计,digg,显示用户在线状态等等,动态页面静态化非常困难。当然如果你非要采用动态页面静态化,技术上也不是实现不了,可以通过AJAX请求来处理静态页面的动态部分,但是这种解决方案的开发成本过高,而且性能未必会有明显的改善,大家看看新浪和搜狐博客就知道这种技术被应用的有多糟糕了。
web2.0网站比较常用使用页面局部缓存,一种情况是页面不需要实时更新的,那么只需要设置一个合理的过期时间就行了,这种情况我们目前使用的比较多;另外一种情况是虽然不需要实时更新,但是会在用户执行某些操作后需要缓存过期,比方说博客个人主页的很多页面,这种情况下缓存过期策略会比较复杂,考虑到合理的开发成本,我们尚未对这样的页面使用局部缓存。
此外,Rails的页面局部缓存有一个缺点,就是和页面查询结果对应的Action当中的查询语句要放在View里面,否则每次action里面的查询还是会被执行,但是这样做会破坏程序代码良好的MVC结构。这种情况下,也可以采用另外一个Cache插件: better rails caching,在缓存页面的同时可以缓存Action当中的查询语句。
三、应用代码的优化
Stefans Kaes的文档里面对应用代码的优化进行了非常详细的介绍,因此我这里只提两个比较重要的注意事项:
1、link_to
Rails的link_to是非常慢的,它的代码实现过于复杂,特别是Rails1.2引入了REST以后,大量的命名路由被使用,这些命名路由还需要通过一次method_missing,那就更加缓慢了。因此对于被频繁使用的内部URL地址,一定要自己用字符串拼接方式改写,可以很明显提高View的render性能。此外类似的helper还有很多,例如button_tag,image_tag啥啥的,如非必要,尽量不用他的helper
2、正则表达式
ruby的正则表达式也是极慢,例如auto_fix这个helper的正则表达式就比较复杂,造成的结果就是一但大量使用auto_fix,View的render就明显变慢,类似依赖正则表达式进行字符串过滤的helper有很多,如果需要频繁大量使用,请先自行做benchmark。
Rails应用程序的内存泄漏问题和解决
内存泄漏是服务器端程序经常遇到的,有时候内存泄漏问题会让人很头疼,总体来说,Rails的内存泄漏问题比Java要少得多,这是因为Java内存泄漏最常见的三种情况在Rails当中不存在:
1、HttpSession导致的内存泄漏
Java程序员喜欢往session里面丢很多东西,最糟糕的是竟然有很多框架软件也肆无忌惮往session里面丢状态数据,但Rails的session是不放在内存里面的,所以无此烦恼。
2、数据库连接释放不彻底
Java的数据库连接池释放不彻底,以及查询游标释放不彻底,都必然导致内存泄漏。Rails没有数据库连接池,而是每个进程持有一个长连接,因此不存在这个问题,而且由于持有长连接,也不存在Java里面的OpenSessionInView的烦恼。
3、用静态变量持有全局共享数据
Java程序员很喜欢通过静态全局变量来持有共享数据,但共享数据忘记清理的话,也很容易导致内存泄漏,Ruby是SNA架构,多进程服务器模式,进程间无法共享数据,反而避免了全局共享数据带来的麻烦。
但是Rails应用有一种情况:在Ruby代码中调用C写的第三方ruby类库的时候,很容易导致内存泄漏,但这种内存泄漏反而在Java中极其罕见。Ruby本身有GC来管理内存堆,但是代码一旦调用C写的第三方ruby类库,内存堆的分配权就掌握在第三方C库的实现上面了,如果这个C库的代码质量不够好,内存泄漏就不可避免。由于ruby本身性能很差,因此计算量大的功能往往依赖底层的C库来实现,这下内存泄漏的潘多拉魔盒就打开了!而Java性能比较好,功能都是纯Java编写,基本上看不到需要依赖第三方C库的情况,因此比较安全。
JavaEye也面临着内存泄漏的困扰,这方面困扰主要来自于Rmagic。Rmagick调用ImageMagick的C库来完成图片的操作,从我们的监测来看,RMagick大多数情况下会缓慢的泄漏内存,在某些特定的图片操作上会急剧的泄漏内存。解决办法就是用mini_magick替代Rmagick,mini_magick是直接调用ImageMagick的mogrify命令,另起一个进程来操作图片,操作完进程就结束了,绝无后患,由于Linux的fork进程开销不大,因此也不必担心性能问题。
此外,调用第三方C库的ruby代码编写都需要高度小心,比方说JavaEye使用ferret实现全文检索,根据应用的需要调用ferret的API来编写自己的analyzer,其中在实现token_stream方法上面使用了XXXAnalyzer.new和XXXToken.new,XXXFilter.new,结果内存急剧泄漏,经过检查发现是Analyzer对象不能被反复创建,改成创建后缓存该对象就好了,但是Filter和Token对象却必须每次创建,此外ferret的PerAnalyzerFilter也有内存泄漏问题。由于类库是用C编写的,单纯看API文档或者看源代码片断一般无法判断出里面的内存泄漏陷阱的。
当遇到了难以解决和定位的内存泄漏问题,Ruby也有类似Java的内存Profiler工具:
1、Memory Profiler
一个纯ruby编写的内存探测器,原理很简单,就是用ruby的对象引用计数器ObjectSpace.each_object去遍历内存堆中的每个ruby对象,进行统计和分析。用起来很简单,非常适合于开发环境下侦测内存泄漏问题,但不能用在生产环境下,极度影响Rails性能。
2、Bleak_house
Bleak_house给Ruby解析器打了补丁,插入相关的指令,可以从底层探测整个ruby内存堆中对象的情况,然后你可以定期dump出来完整的内存堆里面的所有对象,再用bleak工具去分析dump文件,他比上面的工具分析的信息要全面,可以在测试环境和预发布环境下使用,但在生产环境下,也会对应用的性能产生很大的影响,要慎用。
JavaEye网站在RoR性能方面的经验就全部分享给大家了,也希望做RoR的朋友都拿出来自己的经验和大家分享,共同学习和促进RoR的应用和普及。
本文的讨论也很精彩,浏览讨论>>
JavaEye推荐
深圳金蝶中间件公司招聘Java工程师
网站: JavaEye 作者: robbin 链接:http://robbin.javaeye.com/blog/157731 发表时间: 2008年01月20日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
JavaEye网站从2006年9月11日上线基于RoR的2.0版本开始,到现在已经运行了将近一年半了。在这一年半的时间里,JavaEye网站的每日PV从最开始的5万,缓慢增长到了现在的60万。随着网站负载的不断增加,我们也在不断尝试和调整网站的性能,积累了不少第一手RoR应用性能优化的实战经验。虽然我们并不是RoR性能优化的权威专家,我们所积累的经验也许并不是最优实践,但是作为国内最早涉足RoR商业运营的互联网网站之一,我们非常乐意分享和交流我们的实战经验,以帮助后来者节省必要的摸索时间。
RoR惊人的开发速度恐怕是每个互联网创业者都梦寐以求的,但是随着网站流量的不断增大,可能大多数采用RoR的网站或迟或早会遇到RoR的性能瓶颈,我的一个朋友capitian说过一句很有意思的话:“RoR应用做到后来,总有自己修改底层的冲动”。就我所了解和掌握的情况来看,很多RoR网站都过早的遇到了性能瓶颈,一个很普遍的现象就是:RoR应用的CPU负载要远远高于数据库的负载。这是一个有点违背常理的现象,因为我们知道,硬盘IO速度要比内存慢得多,所以一般Web应用的性能瓶颈往往会出现在数据库IO上,因此优化数据库访问,进行对象缓存是非常有效的性能优化手段。但是一旦应用服务器负载比数据库还高的话,单纯的对象缓存就无用武之地了。下面我们从几个方面分别谈一谈如何进行RoR的性能优化:
应用的部署
RoR应用的部署包括操作系统,Web服务器,应用服务器和数据库四个方面:
一、操作系统
1、发行版本
RoR适合于部署在Unix类操作系统上面,通常比较多的人使用RHEL/CentOS/Ubuntu,我们比较偏爱SuSE Linux,对于我们服务器使用的AMD Opteron x86_64的CPU来说,SLES要比RHEL有更多的优化。另外应该尽量使用64位版本操作系统,以充分发挥x86_64 CPU的性能,并且x86_64的Linux很多Kernel参数也大很多,代价就是需要更多的物理内存。
2、文件系统
Linux最常用的文件系统是ext3,但我们使用的是Reiserfs文件系统。Reiserfs在读写大量小文件的目录性能非常高,即使处理目录下面直接存放10万个文件,性能仍然不会下降。我们知道默认情况Rails会对每个浏览器会话在硬盘生成session文件,一个繁忙的网站,临时文件目录下面有上万乃至几万个session文件是很常见的现象。对于这种目录下面几万个小文件的存取,reiserfs要比ext3性能高一个数量级。如果希望对session文件有更好的存取性能,可以把临时目录链接到Linux的内存文件系统/dev/shm目录下面,这样实际上session文件的存取都是直接内存操作了,这种方式唯一的问题在于不能支持群集部署。如果你已经升级到了Rails2.0,可以采取把session保存到Cookie里面的方式,既可以避免服务器处理session的开销,而且还支持群集部署,是大规模网站部署的首选方式。
3、内核的网络参数调整
对于流量很大的网站来说,默认的Linux内核网络参数偏小,因此如果你的网站流量非常大,或者上传下载大文件比较多,可以针对性的调整内核网络参数,扩大内核的TCP接收数据和发送数据的Buffer缓冲区大小,比方说:
net.core.wmem_default=262144
net.core.rmem_max=262144
net.core.wmem_max=262144
net.ipv4.tcp_rmem=4096 65536 524288
net.ipv4.tcp_wmem=4096 65536 524288
参数具体调整,可以Google相关的Linux内核参数的文档,这里不展开详谈。
二、Web服务器
Web服务器首选Lighttpd,因为Lighttpd在和后端的应用服务器通讯方式上做了足够的优化:当POST大数据量的时候,Lighttpd在完整的接收客户端浏览器的数据之后,才会一次性发送给应用服务器;同样的,Lighttpd也是一次性把应用服务器处理的页面数据全部接收,不设置Buffer Size的限制。因此Lighttpd能够尽最大可能的减轻应用服务器的负担,减少应用服务器用于处理数据传输的延迟,更加有效的利用应用服务器资源。这方面的详细的论述请看:RoR部署方案深度剖析。
关于Lighttpd的安装可以参考在Linux平台上安装和配置Ruby on Rails详解,这里仅谈Lighttpd的性能优化的几个要点:
1、网络IO调度方式
Linux Kernel 2.6支持sysepoll方式调度网络IO,能够处理极高的并发连接请求,Lighttpd可以通过配置文件打开sysepoll支持:
2、网络IO传输方式
Linux Kernel 2.6支持sendfile方式传输数据,Lighttpd可以通过配置文件打开sendfile支持:
此外Lighttpd还支持应用服务器参与的文件下载控制X-sendfile,详细的论述请看:RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能
3、文件状态缓存
Lighttpd通过stat()调用获得文件被修改的信息,来决定当请求同一个静态文件资源的时候,是否需要再次读取硬盘文件。但是每次stat()调用也有一定的开销,Lighttpd支持通过Fam Server来减少stat调用。即每次当文件被修改之后,Kernel会发送一个消息通知Fam Server,而Lighttpd会通过进程间通讯连接Fam Server,可以知道文件是否被修改的信息,不必再每次调用stat()。
4、限定POST Size
为了避免黑客恶意的攻击服务器,伪造超大Post数据包轰炸Web服务器和应用服务器,可以限制Request请求的大小,例如限制为10MB:
5、日志文件
Lighttpd是单进程单线程的服务器,调度网络IO性能是极高的,但是在某些极端情况下,单进程服务器也有风险,即一旦被某操作系统调用挂住,整个服务器就没有办法响应请求了。比方说服务器其他进程导致的IO WAIT很高,操作系统的buffer又不够的时候,Lighttpd在大量的写access log就有被挂住的可能性。因此如果Lighttpd日志对你的参考价值不大,可以考虑关闭掉。像JavaEye网站每天Lighttpd产生430万条log,对硬盘IO也是一个不小的负担,既然已经开着Rais的production.log,那么Lighttpd的access log没什么参考价值了,那就关掉它。
Lighttpd的性能优化请看其作者写的文章:
http://trac.lighttpd.net/trac/wiki/Docs%3APerformance
三、应用服务器
Ruby的应用服务器可以使用FastCGI,或者Mongrel,如果我们使用Lighttpd的话,FastCGI是最好的搭配。
1、FastCGI和Lighttpd的通讯方式
如果FastCGI和Lighttpd是在同一台服务器,那么建议采用Unix Socket通讯,这种通讯方式比TCP要快一些,FastCGI可以通过Lighttpd自带的spawn-fcgi命令行工具启动,创建socket文件,而Lighttpd监听socket文件。如果两者不在同一台服务器,需要群集部署,那就必须采用TCP Socket通讯,方式是一样的。
2、FastCGI进程应该开多少个合适?
Rails是单进程方式运行的,理论上来说,开几个FastCGI进程,就只能并发响应几个请求。对于繁忙的网站来说,峰值期间每秒有几十个动态请求是很正常的事情,但实际上FastCGI进程并不需要开那么多。这是因为前端的Web服务器在处理用户浏览器连接,发送Request请求需要相当长的时间,在FastCGI处理完请求释放该连接以后,Web服务器还需要相当长的时间才能把页面数据完整的发送到客户端浏览器。用户在点击一个链接以后,等待1-2秒,页面内容就显示出来,这对用户的感觉来说已经是非常快的了,而FastCGI用于处理该请求可能只需要0.1秒,那么一个FastCGI进程虽然并不能够真正的并发运行,但实际上的效果是他可以在1秒之内处理10个请求,让10个用户在同时访问网站的过程当中感觉不到明显的延迟。
因此FastCGI需要开多少个,取决于你的网站峰值期间每秒有多少个用户请求过来,而你的FastCGI又能够以多快的速度处理请求。比方说你的网站峰值期间每秒有50个动态请求,FastCGI在峰值期间处理每个请求需要0.2秒,那么实际上你只需要开10个FastCGI进程就足够了,为了应付突发的峰值请求,你可以在这个计算量上面增加一些余量,比方说15-20个进程,肯定是绰绰有余了。
关于FastCGI的性能优化,可以参考Lighttpd作者的文章,虽然他是针对PHP跑FastCGI写的,但对RoR也有参考价值:
http://trac.lighttpd.net/trac/wiki/Docs%3APerformanceFastCGI
四、数据库
JavaEye网站使用MySQL5.0.XX版本,数据库引擎是InnoDB。关于MySQL数据库的调优,推荐大家看MySQL Performance Blog,作者是一个MySQL性能调优方面的专家,并且提供MySQL咨询服务。他的博客上面有很丰富的关于MySQL调优的文章和演讲文稿,特别是关于InnoDB方面,非常深入。JavaEye的数据库调优就是根据他的InnoDB演讲文稿来调整的,一般说来,有几个需要调整的参数:
innodb_buffer_pool_size
这个参数很重要,越大越好,对于专用的数据库服务器一般建议开服务器内存的50%以上。
query_cache_size
查询缓存,对于查询的性能提高有很大帮助,但不宜开得过大,查询缓存的过期可能很频繁,过大查询缓存反而降低性能,增加服务器开销
innodb_flush_method = O_DIRECT
针对InnoDB的数据文件,关闭操作系统的文件缓冲,由于InnoDB自己有巨大的Buffer Pool,操作系统对文件的读写缓冲功能反而会降低MySQL的InnoDB的IO性能。
最后针对数据库的SQL优化来说有两点原则:
1、对数据库表要适当的创建索引
特别是出现在where查询条件当中字段,和关联查询当中的外键,要高度注意。
2、尽量避免大表的全表扫描和数据库的硬盘IO
查询比较慢的SQL要explain一下,看看是否发生了全表扫描,采取各种措施减少或者避免大表的全表扫描问题,例如拆分表等等。
最后针对MySQL数据库运行情况,我们可以用show status; 和 show innodb status\G 来监测。
Rails应用程序的优化
Rails应用程序优化包括ruby解析器的优化,缓存的使用,以及应用代码级别的优化。Stefans Kaes曾经在Railsconf 2006有一个Rails应用程序优化的演讲,他的演讲PPT是极好的Rails性能优化指南,可以在这里下载:http://www.javaeye.com/topic/24508。他还编写了一个用于Rails性能测试的软件包RailsBench,大家可以参考。由于Stefans Kaes的代码优化文档已经写的非常详细了,因此我就不在一一复述,只提出几点对性能影响比较大的方面:
一、ruby解析器的优化
ruby的解析器性能是很糟糕的,ruby早期的主要用途是取代perl写批量处理的脚本的,并不是为服务器应用编写的,因此在内存分配策略上非常不适合服务器应用。Stefans Kaes编写了一个ruby GC的补丁文件,在railsbench下载包里面提供了。虽然当前Railsbench提供的GC补丁只有针对ruby 1.8.4和1.8.5版本的,但是在ruby 18,6上面使用1.8.5的GC补丁也完全没有问题。GC补丁的作用主要是针对Rails应用开大了ruby的内存堆,可以有效提高内存堆的利用率,降低GC的频率。根据Stefans Kaes提供的测试数据,打补丁并且调整参数以后,GC的频率下降到只有原来的1/10还不到。降低GC频率尽管并不能够提高单个请求的执行速度,但是可以增加整体应用的负载能力。
我们在JavaEye的服务器上也使用了GC补丁,并且根据推荐参数进行了调整。在使用GC补丁之后,Web服务器的CPU负载下降了大概15%左右,效果非常显著。当然开大内存堆的代价就是ruby进程会多消耗内存,在我们的服务器上,ruby打补丁之后多消耗了50%左右的物理内存。
二、缓存的使用
1、对象缓存
JavaEye上面关于对象缓存的讨论很多,我们也提供了JavaEye这方面很多数据,因此不展开了。RoR可以使用两个对象缓存,一个是CachedModel,类似Hibernate,比较简单,对Model的CRUD操作自动进行缓存;另外一个是cache_fu,需要自己编码来添加对象缓存,但提供了更多高级机制,目前我们使用的是cache_fu。在使用对象缓存的情况下,应该把查询方法的:include去掉,避免关联查询无法利用缓存的现象。
2、查询缓存
对于统计类耗时查询,如果不要求实时性,那么可以使用memcache-client将查询结果缓存到memcached里面,例如博客排行榜之类。
3、页面局部缓存
对象缓存和查询缓存都是降低数据库访问负载的,但如果RoR的负载很高,那么只能依靠页面局部缓存了。传统的互联网web1.0网站很流行采用动态页面静态化技术来提高网站的负载,但是对于web2.0网站来说,每个页面都带有登陆用户的个人信息,页面的很多部分需要实时更新,例如投票,点击统计,digg,显示用户在线状态等等,动态页面静态化非常困难。当然如果你非要采用动态页面静态化,技术上也不是实现不了,可以通过AJAX请求来处理静态页面的动态部分,但是这种解决方案的开发成本过高,而且性能未必会有明显的改善,大家看看新浪和搜狐博客就知道这种技术被应用的有多糟糕了。
web2.0网站比较常用使用页面局部缓存,一种情况是页面不需要实时更新的,那么只需要设置一个合理的过期时间就行了,这种情况我们目前使用的比较多;另外一种情况是虽然不需要实时更新,但是会在用户执行某些操作后需要缓存过期,比方说博客个人主页的很多页面,这种情况下缓存过期策略会比较复杂,考虑到合理的开发成本,我们尚未对这样的页面使用局部缓存。
此外,Rails的页面局部缓存有一个缺点,就是和页面查询结果对应的Action当中的查询语句要放在View里面,否则每次action里面的查询还是会被执行,但是这样做会破坏程序代码良好的MVC结构。这种情况下,也可以采用另外一个Cache插件: better rails caching,在缓存页面的同时可以缓存Action当中的查询语句。
三、应用代码的优化
Stefans Kaes的文档里面对应用代码的优化进行了非常详细的介绍,因此我这里只提两个比较重要的注意事项:
1、link_to
Rails的link_to是非常慢的,它的代码实现过于复杂,特别是Rails1.2引入了REST以后,大量的命名路由被使用,这些命名路由还需要通过一次method_missing,那就更加缓慢了。因此对于被频繁使用的内部URL地址,一定要自己用字符串拼接方式改写,可以很明显提高View的render性能。此外类似的helper还有很多,例如button_tag,image_tag啥啥的,如非必要,尽量不用他的helper
2、正则表达式
ruby的正则表达式也是极慢,例如auto_fix这个helper的正则表达式就比较复杂,造成的结果就是一但大量使用auto_fix,View的render就明显变慢,类似依赖正则表达式进行字符串过滤的helper有很多,如果需要频繁大量使用,请先自行做benchmark。
Rails应用程序的内存泄漏问题和解决
内存泄漏是服务器端程序经常遇到的,有时候内存泄漏问题会让人很头疼,总体来说,Rails的内存泄漏问题比Java要少得多,这是因为Java内存泄漏最常见的三种情况在Rails当中不存在:
1、HttpSession导致的内存泄漏
Java程序员喜欢往session里面丢很多东西,最糟糕的是竟然有很多框架软件也肆无忌惮往session里面丢状态数据,但Rails的session是不放在内存里面的,所以无此烦恼。
2、数据库连接释放不彻底
Java的数据库连接池释放不彻底,以及查询游标释放不彻底,都必然导致内存泄漏。Rails没有数据库连接池,而是每个进程持有一个长连接,因此不存在这个问题,而且由于持有长连接,也不存在Java里面的OpenSessionInView的烦恼。
3、用静态变量持有全局共享数据
Java程序员很喜欢通过静态全局变量来持有共享数据,但共享数据忘记清理的话,也很容易导致内存泄漏,Ruby是SNA架构,多进程服务器模式,进程间无法共享数据,反而避免了全局共享数据带来的麻烦。
但是Rails应用有一种情况:在Ruby代码中调用C写的第三方ruby类库的时候,很容易导致内存泄漏,但这种内存泄漏反而在Java中极其罕见。Ruby本身有GC来管理内存堆,但是代码一旦调用C写的第三方ruby类库,内存堆的分配权就掌握在第三方C库的实现上面了,如果这个C库的代码质量不够好,内存泄漏就不可避免。由于ruby本身性能很差,因此计算量大的功能往往依赖底层的C库来实现,这下内存泄漏的潘多拉魔盒就打开了!而Java性能比较好,功能都是纯Java编写,基本上看不到需要依赖第三方C库的情况,因此比较安全。
JavaEye也面临着内存泄漏的困扰,这方面困扰主要来自于Rmagic。Rmagick调用ImageMagick的C库来完成图片的操作,从我们的监测来看,RMagick大多数情况下会缓慢的泄漏内存,在某些特定的图片操作上会急剧的泄漏内存。解决办法就是用mini_magick替代Rmagick,mini_magick是直接调用ImageMagick的mogrify命令,另起一个进程来操作图片,操作完进程就结束了,绝无后患,由于Linux的fork进程开销不大,因此也不必担心性能问题。
此外,调用第三方C库的ruby代码编写都需要高度小心,比方说JavaEye使用ferret实现全文检索,根据应用的需要调用ferret的API来编写自己的analyzer,其中在实现token_stream方法上面使用了XXXAnalyzer.new和XXXToken.new,XXXFilter.new,结果内存急剧泄漏,经过检查发现是Analyzer对象不能被反复创建,改成创建后缓存该对象就好了,但是Filter和Token对象却必须每次创建,此外ferret的PerAnalyzerFilter也有内存泄漏问题。由于类库是用C编写的,单纯看API文档或者看源代码片断一般无法判断出里面的内存泄漏陷阱的。
当遇到了难以解决和定位的内存泄漏问题,Ruby也有类似Java的内存Profiler工具:
1、Memory Profiler
一个纯ruby编写的内存探测器,原理很简单,就是用ruby的对象引用计数器ObjectSpace.each_object去遍历内存堆中的每个ruby对象,进行统计和分析。用起来很简单,非常适合于开发环境下侦测内存泄漏问题,但不能用在生产环境下,极度影响Rails性能。
2、Bleak_house
Bleak_house给Ruby解析器打了补丁,插入相关的指令,可以从底层探测整个ruby内存堆中对象的情况,然后你可以定期dump出来完整的内存堆里面的所有对象,再用bleak工具去分析dump文件,他比上面的工具分析的信息要全面,可以在测试环境和预发布环境下使用,但在生产环境下,也会对应用的性能产生很大的影响,要慎用。
JavaEye网站在RoR性能方面的经验就全部分享给大家了,也希望做RoR的朋友都拿出来自己的经验和大家分享,共同学习和促进RoR的应用和普及。
本文的讨论也很精彩,浏览讨论>>
JavaEye推荐
深圳金蝶中间件公司招聘Java工程师
2008-01-19 Sat
2008-01-18 Fri
AnySQL.net
DBA notes
Oracle & Starcraft
eagle's home
给你点color see see
AnySQL.net English
Oracle Scratchpad
Oracle Life
OracleDBA Blog---我不在江湖,江湖却有我的传说!
Photos from dbanotes
Chanel [K]
xzh2000的博客
Oracle Security Blog
ERN空间
Eddie Awad's Blog
MySQL Performance Blog
The Tom Kyte Blog
del.icio.us/fenng/oracle
AIXpert
O'Reilly Databases
Red Hat Magazine
DBASupport
DB2 Magazine 中文版
developerWorks : AIX 专区的文章,教程
Pythian Group Blog » Log Buffer
车东[Blog^2]
blue_prince
玉面飞龙的BLOG
此生 今世
人生就是如此
Orange Tiger 木匠 的 移民生活
生活帮-LifeBang
Hey!! Sky!
dba on unix
Oracle Notes Wiki
Welcome to brotherxiao's Home
柔嘉维则@life.oracle.eng
Fenng's shared items in Google Reader
jametong's shared items in Google Reader
缥缈游侠-logzgh
Tanel Poder's blog: Core IT for geeks and pros
DBA Tools
ilonng
yangtingkun
NinGoo@Net
Oracle & Unix
Inside the Oracle Optimizer - Removing the black magic
Ricky's Test Blog
DBA@Taobao
存储部落
Think in 88
