Google App Engine 开发总结

May 19th, 2011 § 2 comments § permalink

我的毕业 project 是在 Google App Engine 上完成的。

当初选这个平台有很多原因。曾经也考虑过其他平台,比如 Amazon Web Service,但是后来考虑到开发速度,还是使用了 GAE,毕竟 AWS 还需要自己去搭建一个完整的 web 服务。而且 V2EXLivid 也给了我很大信心。

而在 GAE 上,一切都准备好,需要做的只是写好代码,部署,job done。

当然,便捷就意味这有很多约束,需要根据 Google 制定的规则来玩。这也是写这篇的文章原因。还有一个原因是因为我明天要 viva,算是对这个平台技术细节的复习。

部署在 GAE 上的应用在国内是全部访问不了的,这确实带来了一些麻烦。但我现在已经基本不考虑这个因素了,翻墙应该成为一个公民的生存技能。不过为了方便我国内的朋友们,我最终还是使用 nginx 和 AWS 用反向代理解决这个问题。

我在 project 里使用了 GAE 提供的 以下服务:Images, Memcached, Task Queue, Blobstore,当然还有每一个 web app 都无法不用到的 GAE datastore。

Images 的 API 很简单,其实 Google 提供的这一系列服务,还包括其他的诸如 Mail, Users, Channel 都能很快上手。文档写得也很清楚。即便有疑惑,去相应的 Google 小组也很快能获得答案。回到正题,GAE 提供了一套工具能完成剪裁、旋转、缩放等操作。对于储存在 Blobstore(Binary Large Object)里的图片还能调用一个函数直接获得图片 URL 并同时进行剪裁和缩放。Project 里的所有头像因此都采用这种方式,用户上传,放在 Blobstore 里,app 读出来,根据相应的尺寸进行缩放。曾经图片服务考虑使用 Yupoo(又拍),但是考虑到他们数据中心在国内,和 GAE 通信很难通畅。最终作罢。

Blobstore 的 API 稍微复杂一些。Blobstore 最多支持用户上传 2G 的文件,所以叫 Binary Large Object。类似的课题其实已经在很多学校的 database 课程里提到过了。在 GAE 里,用户使用 POST 方式将文件直接传到 Blobstore 里(因此在生成上传页面的时候,需要先调用 createUploadUrl() 这个函数,生成一个动态的 Blobstore 地址),Blobstore 收到数据后,存储数据,重写收到的 HTTP request,将原来 request 里的文件变成对应的 BlobKey 然后传回对应的 handler。Handler 再做相应的处理。我用 Blobstore 主要是用来存储头像,如上段所说,Images service 和 Blobstore 有很好的整合。所以直接将 BlobKey 储存,下次调用即可。

Memcached 或者类似的中间缓存机制已经成为每一个 web app 的出家旅行必备了。我很惊讶的是,Twitter 最早的网页端没有使用 cache ,当然现在他们已经严重依赖 cache 了。新浪微博则使用了 与 Memcached 类似的 Redis 作为 cache 实现工具。使用 cache 的最大原因是,数据是存储在内存而不是硬盘中,所以读取速度要快很多。我对 GAE Memcached 的理解是,它是一个巨大的分布式 HashMap。这其实也能用来理解大部分 Key-Value 式的数据库。Livid 的 V2EX 已经证明了使用 Memcached 后访问速度的巨大提升,更重要的是,使用 cache 节省了很多 CPU 资源。所以到后来在写代码的时候,我发现,架构上的优化不仅是一种精神洁癖的表现,更直接的是,省钱。(如果超过免费额度,Google 会收费。其中 CPU 资源是最容易超的,而且为了使用 Blobstore,我的银行卡已经绑定了,所以未来的某一天是一定被扣钱的。)

如何使用和何时使用 cache 是一门大学问,这个问题包括 Twitter,新浪微博和豆瓣相信都在持续研究。所以也不就不在这讨论了。但是有一个小窍门是,由于 GAE 是分布式架构,如果有一个常量你的 app 会经常用到,可以放在 Memcached 中,然后用到的时候读出来。而不是将这个常量使用 static 储存。

最后一个是我的最爱,Task Queue。每次写到它,我都觉得内心幸福的像开花一样。实在是太爱 Google 提供这个服务了。为什么?因为它实在解决太多的问题。一一列举,1)在传统 Computer Science 领域,有一个问题是不管什么应用都会遇到,concurrency。而队列是一个解决这问题很好的方式,synchronised => asynchronised。也就是说,别抢,大家排队来做事。Task Queue 可以用来解决这个问题。2)有些时候,用户发起请求后,app 需要计算大量数据。如果不用 Task Queue,用户就一直在那傻等着等结果而且有些时候这些结果并没有实时的要求。使用 Task Queue 则可以解决这个需求。3)这一条和 1) 很类似,那就是使用 queue 缓解大量的并发请求。Twitter 的数据是,在奥巴马就任的那天,他们平均每秒收到成百上千的 Tweet,正是他们用 Scala 设计的 Message Queue 解决了这个问题。

Task Queue 的 API 并不是很复杂,简单一句就是将 task 传给一个 handler,剩下的就是 app 的事了。

说完这些其实还没到核心。GAE Datastore 才是重点。

与传统的 Relational Database 不同,datastore 是 Key-Value 型的 NoSQL,也就是一个大型的分布式 HashMap。很多思维方式都与传统的 RDMS 不同。

比如,在传统的 RDMS 中,每一个 table 都遵循一个 schema,而 datastore 不需要。每一个 column 里的值都必须 atomic,而在 datastore 里,可以允许 List 和 Set。在 RDMS 里,你可以使用 join 将两个表联系在一起,但是 datastore 不允许 join。(不过这个有办法 work around,使用 List)。在传统 RDMS 里,比如豆瓣、新浪微博都用的 MySQL,没有 explicit hierarchy,datastore 确有。

而这些都是在进行数据库设计时必须考虑到的,有些时候错误的理解会带来很大麻烦。

比如接下来讨论的问题,Transaction。

在 datastore 里,每一个 data object 称为 entity,每一个 entity 可以有若干 properties。比如,一个 member entity,可以有性别、家庭住址这些 property。之前说 datastore 可以存在 hierarchy,所以 member 也可以属于某一个 department entity。这个 department entity 也就和 这个 member entity 组成一个 entity group,department 是 parent。(如果 entities 不属于任何一个 parent,他们自己就组成了自己的 entity groups。)

Transaction 的存在也是为了解决 concurrency 的。而 GAE 的 transaction 原则是,每一个transaction 只能修改一个 entity group。在最开始的时候,没有充分理解 GAE 关于 entity group 的概念,所以很不解:当时我以为,所有 member entities 都属于一个 group,更新其中一个 member 会导致同时更新另外一个 member 的操作失败。当时我觉得这设计太傻逼和不合理,仔细一查,才发现,这是与 RDMS 的 table 概念混淆了。事实上,每一个 entity 都组成了自己的 entity group。如果 member 有 1000 个 entities,那就有 1000 个 data entities groups。所以当 app 更新 A 时不会导致 B 的数据不能更新。不过当 app 更新用户 A 的性别(比如他去泰国了)时,就不能再同时更新他的女朋友性别。所以这也提醒了所有开发者,如果某些 entities 很热门,经常更新,他们需要减小 entity group size,essentially, shard oft-written entities。

使用 Transaction 就必然带来了另外一个问题,Transaction isolation。这是一个蛮有意思的东西。

Isolation level 的定义是,when the changes made by one operation become visible to other concurrent operations。

一句话,Transaction 导致的数据变化什么时候能被其他并发请求读取或者操作。

在 datastore 里,每一个 transaction 都有两个 milestone,第一个 milestone 是改变 value(比如某一个 member 的身高),第二个 milestone 是改变 indices。如果有两个 request 几乎同时到达 app,一个是 transaction 更新数据,一个是读取数据。读取数据的 request 如果在两个 milestone 之前,则不会得到更新后的数据。如果在两个 milestone 之间,因为 index 仍然没有更新所以采用 predicate(「where」clause in SQL)来读取的话也得不到更新结果,而使用 getEntityByKey则能读到最新修改的数据。

这个概念比较复杂,Google 员工也专门写了一篇文章来解释这个问题。

刚才说到 sharding 的问题,其实这已经成为优化数据库性能的重要方式。FriendFeed 就使用了这种办法解决了 MySQL 在面对大数据量和 schemaless 遇到的困难。相信 Facebook 也才采用了这种方式。

说的有点远,我其实只是想说 sharding counter 的问题。Concurrency 确实是很讨厌的东西,用 trasanction 来保护也只是下策,如果遇到频繁更新的 entity,整个 app 就近乎没法工作了。比如某一个 counter 可能每秒更新 3 次。这时候就只能使用 sharding counter 了。原理很简单,多存储几个 counter,每次更新的时候随机选一个,最后统计的时候加起来就行了。

我一开始觉得这个概念很爽,便想采用。但是仔细一算,发现自己太自恋了,我们假设如果有一个 entity 能有每秒 3 次更新的频率。这是一个什么的访问量?假设 app 每天的活跃时间是 10 小时,这个 app 每天至少能获得 108,000 的访问量。

算完后,我就乖乖的去写 transaction 了。

其实我挺喜欢 schemaless 的数据库,至少维护数据库的时候太方便了。而且新的 feature 更新也很方便。

但是 datastore 有一个特性很讨厌,它其实有挺多讨厌的特性,不过都被我躲过去了,但是这个没法躲。那就是分页。

我一开始觉得分页很简单,无非就是 start = size – (page – 1) * PAGE_SIZE – 1,bla bla。但是 datastore 比较操蛋的是,一个 query 只能返回 1000 个结果(如果你不使用 primary key 进行 query)。一开始,我为了完美解决这个问题,想了很多方法。包括使用 datastore cursor,可以用,但是 it was pain in the ass。我动用了无数资源去完成这件事。后来 stackoverflow 上一位大侠敲醒了我,你 Google 的时候,会翻到第 50 页去看结果吗?

于是我又乖乖的去用笨方法了。

总体上说,Google App Engine 上开发很轻松,技术上没有太多需要担心的事情。文档很全面,而且 Google 非常重视这个项目,有很多 Googler 都参与到这个项目中,包括 Python(豆瓣使用的语言) 作者也有参与。今年 Google I/O 之后(我必须要吐槽一下,我他妈的因为签证没去成,可能是全世界唯一一个有票但是没去的人),又增加一堆新特性和新的语言,Go。

当然唯一需要担心的事是如何让国内人访问。不过这个问题也不是难事,找一个没被封的 VPS 做反向代理就行了。

这段时间在缓慢的读 Chris Anderson 的名著 Long Tail,一本其实是经济类型的书却说的我很激动。这个世界在慢慢的变成一个 niche 的世界,有头,更有长长的尾巴,而对于每一个 computer scientist/engineer 来说,我们的目标是让更多的人接触以前从来见不到的尾巴,让信息比以前更流畅更有组织的流到你的眼前。

谢谢 Amazon,谢谢 Google,还有许多其他,让这一切变得简单。

三年

May 12th, 2011 § 0 comments § permalink

现在什么事都如一阵烟,还没反应过来就过去了。很多事都如昨天,所以都在感叹,白马,为什么你跑得这么快呢。

唯独三年前发生的事我觉得好像已经过去很久很久了。

手动历史上的今天:

2010:两年

2009:一年

2009年的文里有张照片因为图片托管商已经不做了,看不到照片,我上传到这里,这张照片拍摄于 2008 年 5 月 10 号

Mark一下

May 4th, 2011 § 0 comments § permalink

今天交了一万字的 Final Report。不过还没完,还有期末考试。

把想法变成设计图,再从设计图变成代码,这两个过程有痛苦,但是大多数时候能得到幸福结果。从代码再变成一万字的 report,还是洋文的,就是有苦也 express 不出来。

对于不少人来说,report 交了这个事也就完了。不幸的是,我不是。

现在这个 project 已经把我心中第一个阶段的设想完成了。不过还不是拿出来的时候,孩子还长得太丑。

从开始这个 project 俺就清楚,这是一条贼船,上去就下不来。其实干什么事都一样,能找一个美丽港口歇会儿就是最大恩惠。

这不,明天下午去喝茶,晚上看 「速度与激情 5」。这一个月来唯一一次出门娱乐活动。

我还在等美国签证,但是估计实现不了美国梦了。我无数次幻想过走到那个公寓楼下的咖啡厅摆出数字 6 的手势,更想过他妈千万次站在 SF 的 Moscone Center 里和全世界开发者讨论一些有意思的问题。但是谢谢我那绿色小本儿,他天生就是用来拒绝主人的。

大致如此,n年求学之路,以一个我深爱的玩意暂作了结。未来还有几个坑已经想好如何去挖,明年这会我们再走着瞧。

oops。

北京城

April 5th, 2011 § 4 comments § permalink

前几天,妹妹她老人家说要去北京实习。我的某跟筋瞬间短路一下,然后说,不然我写一份攻略给你吧。说到做到。当然俺是不可能写什么校内体的,比如:去北京怎么能错过这些景点和小吃,超过三千人分享!

给她老人家写所谓攻略,其实是私心写北京。不过终究这篇文章是写给妹妹你老前辈的。

用钱钟书先生那句被用到烂俗的话来形容北京在中国人民心中的地位想必是最合适不过了:北京是一座围城,里面的人想出来,外面的人想进去。我在无数人的博客和Twitter和其他各种场合看到他们对北京的抱怨,也在无数人的博客和Twitter和其他各种场合里看到他们对北京的向往。

城外人的我当然属于后者。而且近乎是无限向往。从08年初到现在,我一共去过北京4回,往返8趟,全是火车。中间只有两回是不到10个小时的硬卧,其余25小时以上的火车全是硬座。我特别喜欢火车缓缓驶入北京城内的感觉,尤其是快到西站的时候。站起来,看出窗外,挂着京B牌黄绿相间的北京出租车在不远的马路上奔驰,会有一种非常强烈的信号告诉你:到北京了,你在北京。

我衡量一个城市首先从公共交通开始。北京的拥堵举世闻名,但是北京的地铁便宜也是举世无双。所以纵然我也在北京停车场呆过,北京地铁还是弥补许多—两块钱可以带着你从北京地铁线上任何一点到另外任何一点。08年我看苏打绿在大陆的第一场演唱会,我住在Garry家,天坛东边一点。演唱会在北展,西直门。下午去,晚上回,把北京城中心横跨两遍。花费4块。我手里拿着地铁票的时候,感叹如此不真实。

如同现在我花70块人民币在英国买了两张公交车票一样。

说到天坛。看苏打绿演唱会那天是星期天。演唱会在晚上,下午无事可做我便去溜天坛。却不想让我提前透支了兴奋度。星期天的下午,天坛的长廊里有各式各样的大爷大妈,下象棋的,唱京剧的,遛鸟的,搞中老年合唱团的。在我去的那个下午,正好有一个美国乡村歌手Rivers Rutherford也带着吉他来这遛弯(我后来去他官网,他官网说他去哪都带吉他,我可以验证,这是真的,哥们去天坛都带了)。他看着中老年合唱团技痒,便询问能否加入。当时大爷大妈们唱《英雄儿女》正他妈抗美援朝high着呢,突然一个美国人加入了,我现在想想都觉得好笑。Rivers问,你们会唱哪些西洋歌曲。指挥不知道从哪抽出一个曲谱,然后指了指,用纯正的京片子答:Hey Jude。Rivers笑了笑,通过翻译和指挥聊了几句,开始合唱。我发誓,那是我经历过最激动的一个音乐现场。不仅我不能自已,合唱队里的一个小伙子也已经完全迷失自己,在Hey Jude后半段高音中飙到宇宙去了。跟Rivers一起来的其他美国人除了鼓掌和叫好也不知道做什么好。只有唱完后纷纷与飙去了宇宙的小伙子击掌。平静下来后,Rivers说,他从来没想到会遇到这样的情形。之前自我介绍的时候他说了自己是一个音乐制作人,所以唱完Hey Jude后,大爷大妈就起哄让他唱歌。Rivers老师摆好pose,望着身边的老婆然后说,这首歌叫Ain’t Nothing ’bout You,是写给我妻子的。

那会的北京很燥热,奥运前的北京更是聒噪不安。那三分钟里,长廊里很安静,只有吉他和演唱者的声音。

这首歌我总觉得耳熟。回来一查才发现,却是牛逼。这首歌曾经在Billboard乡村排行榜上排过第一,由Brooks & Dunn演唱。可能他们的名字有些陌生,后来在演唱会中,Taylor Swift也唱过这首。

我想在几百年前天坛的建造者们一定不会相信,唱着《英雄儿女》的人们在听美国乡村音乐。

这是最好的国际化。至少比和上海香港攀比名牌店数量靠谱多了。我希望妹妹能在北京见到更多这样的场景。

09年在北京的一个晚上,我坐在一个胡同口,喝着啤酒吃着羊肉串,就点饺子。远处一个小男孩什么衣服也没穿,就这么裸露着小鸡鸡,在邻居家门口乱转。坐我对面的是一对男女,他们和这家老板很熟,我猜本身就是邻居。他们在不在吵架我已经记不清了。我只记得,这家店有一个招牌,上面写着“烤”,用类似霓虹灯管做的,斜挂着,大约和屋檐成78度夹角。

我一直对一个大城市里这样的小细节感到深深的着迷。

此外,我很喜欢站在北京的天桥上或者就这么站在街边,看着一辆辆车从我面前消逝。因为这个城市太大,太多的可能性。这辆车从哪来?要开哪去?这一路上他经历了什么?他是做什么的?他有什么故事?

就离那个胡同口不远,在上回我去的时候,有一个阿姨,留着平头,在弹手风琴。60贝司的。我和她聊了几句(因为我小时候也是弹60贝司的,还记得不?),她说想去广东弹,但是一听到我说广东在三月很潮湿便说不去了,她说手腕受不了。

如果再早几年在海淀的画家村,类似的场景,或许就在和周云蓬聊着类似的话题。

北京太大了。但是决定它如此巨型的是无数细节。一个越大的城市会有越多的细节。而这样的细节只有慢慢的走和观察才能看到。所以穿上人字拖,去观察这个城市,去聆听这个城市的语言。

—————–One More Thing———————————

不列些吃货清单是不行的嘛,先给店名,地址就一下就找到就给啦。

北京市东城区安定门内大街252号 这家的饺子好吃的很。我的北京朋友猫婶带俺去的,馅很足,花样多,还不算贵。

北京市丰台区西四环南路30号院四号楼,金轮宾馆餐厅(兰铁驻京办), 这个是我前年收藏的拉面馆,可是很多原因一直没去。但是看到是兰州的驻京办,就应该知道靠谱。

在鼓楼附近有一家涮羊肉店,店名一下想不起来了。隔日再给。

北京大槐树烤肉店,在中国美术馆后门。五花肉那是好吃的一逼。

东兴楼东直门店,猫婶推荐。我也觉得好吃。昔日北京八大楼之首。吃鲁菜。爆三样和糟熘鱼片都很好吃。

护国寺小吃。猫婶说,北京人以前吃面食吃腻了。就把面食扔进去炸了。所以煎炸东西不少,不过就着味很足的羊杂汤还是挺爽的。

陈记卤煮。在前门但是附近不好找,猫婶带我去的。但是我强烈推荐,因为很好吃。

深夜,写不下去了。要崩溃了。

睡觉去。

Miscellaneous

March 28th, 2011 § 1 comment § permalink

我对不少英文单词都有拼写恐惧症,miscellaneous是其中翘楚。还有另外一个也得说,因为在写代码的时候经常写到,但是一写就怕拼错,exist。现在确是从容打出来了,可之前对自己智商怀疑的心慌只有我知道。

最近有点儿累。明明没有厌倦的事情也无力去做。于是开始想找个地方自虐一下。可是仔细一想,很难说是累了,更多是一个妇男的心思又活络了吧。西班牙已然去不成,我又可耻的把这地儿拖到明年,传说中的世界末日年。历史上已经数不清有多少个世界末日年了,当年哈雷发现彗星,都造成世界末日的恐慌。那会归咎于信息的不顺畅和对科学缺乏了解。不过都21世纪了,世界是平的,大家都知道牛顿三大定律,世界末日的传言依然不绝于耳。

这个心思的活络在周五的下午达到顶峰。在lab写不下去代码,上QQ正好看到润琦童鞋在线。抓住聊。结果,结果,这孩子说,她要去尼泊尔走15天的EBC(Everest Basic Camp)线。这是两年内我认识的第二个人要走这条心中的dream trail。如果之前我还是临近沸点的水,听到她的计划后,立刻沸腾。

于是内心仔细盘算一番,希望计划顺利。如果能成,当然幸福死掉。

刚才迈出去计划第一步,这一步有点儿大,跌倒的可能性大到我都不好意思说。^_^

话题生硬的一转,明年奥运会Ian Thorpe(索普)会复出。这是一个完全改变我对游泳看法的人。初中看到他的自由泳时,我第一次意识到原来印象中无比暴力的短距离自由泳可以这么优雅。前几天看菲尔普斯教练讲自由泳,他提到,在98年的时候索普就可以做到在400米全程中每左右手两次划水间完成6次脚打水。我上星期特地试了一下,难度不是地球人可以接受的。所以2012年自由泳他和菲尔普斯的对决可能是游泳史上最好看的,可惜波波夫早了10年,不然200米自由泳能好看成啥样哩?

幸运的是,明年有机会现场看。

再生硬的一个结尾,

好久没写这种吊儿郎当的blog。听着陈升吊儿郎当的声音。

夏令时莫名的剥夺了生命中的一个小时,这是夏天逼近的唯一坏处。当然,冬天不请自来的唯一好处是还给你一个小时。

是时候去做我的「纯情青春梦」了,晚安。

我欲乘风归去,又恐琼楼玉宇

March 18th, 2011 § 2 comments § permalink

写下这个标题把我自己都雷了半天。

半天后,等雷过去,说说苏东坡老师。

林语堂在《苏东坡传》里是这么评价苏东坡的:“他是道地的中国人气质,从佛教的否定人生,儒家的正视人生,道家的简化人生,这位诗人在心灵识见中产生了他的混合的人生观。”

正如标题,这样的气质事实上困扰了古往今来所有的有识之人。仿佛内心有两个小人,一个叫老庄,一个叫孔孟。孔孟推着他入世,老庄诱惑着他无为而成仙。入世后于世间不满,出尘后心有不甘。两个小人总是在打架,却没有输赢。心中总是不安稳,于是求教于佛,修禅去了。结果给这帮古人一搞,禅宗也变成了孔孟与老庄的融合。在苏东坡后期,他有一个闲云野鹤般的道士朋友叫吴复古(唉,都古时候的人了,还给自己起这个名是想穿越到哪去呢?),他行无影去无踪,如仙人般。苏东坡很是羡慕。可是他却从来做不到,事实上他有很多这样的机会,可是每当朝廷再次征召,他的孔孟小人便暂时打赢老庄,又踌躇满志的应召了。

苏东坡一次对弟弟子由说:“我上可以陪玉皇大帝,下可以陪卑田乞儿,在我眼中天下没有一个不是好人。” 所以我觉得林语堂对苏东坡评价还不准确,应该再加上一条,他还有墨家的无阶级兼爱。

这个林语堂笔下近乎是完人的苏东坡来自四川眉州。我对那没有什么印象,唯一的印像是一个好朋友学眉州话”呦喂,哥发的呦”把我们笑滑丝。看完《苏东坡传》我特地查了一下眉州,当然现在已更名为眉山市。和所有其他出了名人的小城市一样,眉山也恶俗的划了一片区起名并东坡区。很可惜,他们没弄清楚一个事实,东坡居士的号来自湖北黄州。苏东坡当年被贬至黄州,在山的东坡上有一片田,故而自封为东坡居士。

苏东坡是一个全才。诗词散文无须多说,我中考甚至都被害过一次。《记承天寺夜游记》本是带星古文,我便侥幸认为不会考到,没有认真复习。结果拿到试卷后就立刻骂起出卷老师,当然也不忘唠叨一下苏老师,您老夜游就夜游,为什么还要写一篇文章刁难呢。当然这回再读到,却是完全不同感受。

不过真正震撼我是重新读到《江城子》:“

十年生死两茫茫,不思量,自难忘。千里孤坟,无处话凄凉。纵使相逢应不识,尘满面,鬓如霜。

夜来幽梦忽还乡,小轩窗,正梳妆。相顾无言,唯有泪千行。料得年年断肠处,明月夜,短松冈。”

苏轼的妻子在24岁去世,这是他在妻子10年忌日时写作。所以当林语堂说到这里,他便潇洒的扔出这首词,“十年生死两茫茫”,我忍不住要怀疑人生:没有什么比“茫茫”更能形容生死之别了,看得见又看不见,摸不着又摸得着。在那里又不在那里。绵绵无绝期。

苏轼写得一手好字,他在世期间,求他字的人数不胜数。也因为卓越的笔法和学识,开创了文人画的学派。我很喜欢林语堂在这里的解释,摘抄如下:“在中国是书画同源的,在技巧,在工具材料,在批评的精神与原理,都是如此。若不懂中国书法中的美学原理,就不能了解中国画南派的起源。书法为中国绘画提供技巧与美的原理,诗则提供画的精神与气韵情调的重要,以及对大自然的声色气味泛神性的喜悦”

不过我喜欢苏东坡不是因为他的完美与全才,而是他的人生经历。

我读过的名人传记不算少,但是像苏东坡这样经历如此多起伏却很是罕见。苏东坡曾官至礼部尚书翰林学士,也被下放过在东坡种田。久居张择端笔下的繁华都市汴梁,也流放过天涯海角海南。在北方密州干庶之地做过地方官,也当过风景秀丽杭州太守。30岁前丧妻,50岁丧幼子。一生爱过三个女人,都去世的比他早。除了书画造诣,还给杭州人民留下了苏堤和三潭印月这样的景色工程,他修过桥,疏通过水利。和写《资治通鉴》这样巨著的司马光共过事,和尝试进行国家资本主义的王安石做过政敌。20岁前便坐船穿越了三峡,50后甚至从中原步行到广州。

经历过如此多事的人,文笔已经不重要了,字里行间都是故事。

那天看到张晓舟说巴黎的好,歌词大意是说,一个城市如果永远只有阳光,那里的人是做不出来什么有深度东西的。

以苏东坡的一个诗句结尾吧:猿吟鹤唳本无意,不知下有行人行。一句话近似破千机,不是吗?

—————————————One more thing————————————————

话说刚才写到汴梁,看着古人和林语堂描写的这座古城,让俺特别装逼的想起了卡尔维诺的《看不见的城市》。可真想有一个Time Maching穿越回去看看。

其实我身边有一个Time Machine,1TB,不过好久没备份了。^_^

今天早上一上网,就给齁死了。都你妈的盐荒子孙。

我打了电话给妈妈,好都没问就说:“妈,买了盐没?”

我妈一阵乱晕,茫然回道:“阿?!”

我说:“不是闹盐荒吗?”

我妈特别自豪答:“非典我都没抢过醋,还去抢什么盐。而且你奶奶春节买的盐我们都吃忘识的了。”(这里有安徽话,就是家里盐太多,都吃忘记的意思。)

我妈在回答这种问题的时候一向给力。08年我问,“谷歌和百度您用哪个?” 妈妈不假思索答:“谷歌,百度那玩意我不信。”

今天在房间里偶然瞥见一包花椒,是去年暑假妈妈和我在吉之岛买的。

Random(recently)|梦一则

February 24th, 2011 § 2 comments § permalink

梦始于蔡依林。这样的开头平时让我瞎编千万次也想不出来。

她在做关于太空旅行的演讲,我是一个普通听众。很快见到大屏幕上一架航天飞机飞离地球。蔡依林连开头都没有就非常激动的说,我进入太空了!现实中陀螺会倒地的我记得很清楚,因为我被接下来的演讲震惊了,也被自己的梦震惊了:蔡依林十分淡定的解释了她在绕地球过程中,航天飞机进行的两次精确变轨。这是一个只有火箭科学家才会在意的玩意,她轻描淡写的说了出来,并且附上了示意图和需要变轨的原因。

不过到这会,我固然震惊,但还是不想从睡梦中醒来。于是继续听蔡依林说。

到了降落的时候原本梦里的航天飞机突然变成了类似俄罗斯的联盟号飞船(也就是神舟系列)。我也从听众变成了着陆场的一名工作人员。我第一个发现降落的飞船,打开船舱,蔡依林对着我笑。但是我还没反应过来怎么回事呢,「Prison Break」里那个一直和Michael斗智斗勇的FBI侦探出现在我面前。丫说我因为接触了刚从太空回来的人,得了一种病,需要逮捕我。还没来得及感叹匪夷所思,就开始奔跑。一边奔跑还不忘怀疑人生对自己说:“唉,要被抓了,比起拥有而失去的,我更讨厌不能实现当下所梦想的。”跑的时候都这么不认真,当然终于还是给逮着了。我被丢进一个压力舱,感到千钧压身,再不醒就他妈要憋死了。

果断睁眼,早上7:30,怒吼一句:我靠,和同伴阿乐约好的游泳时间错过了。

在赶去学校的路上回想起这个梦,感叹,弗洛伊德听到这个梦也会在风中凌乱的。

今天和阿乐一次性游了2000米,中间没有休息。25米的短池,40个来回的自由泳,用时大概只有50分钟。

(这篇Blog的标题用到了一个Random函数,和Linux里的pipe symbol,if you know 「it」, you know 「it」.)

哪怕你穿过白色9号

February 15th, 2011 § 0 comments § permalink

这里的第二篇文章其实本已心有所属。而且现在我也应该在写代码而不是在这码字。更何况,美国作家斯坦贝克说,“人们90%的时间都是在想过去的事。别回头看,不然你就会被撵上呢。”但是,所有这些阻止我写这篇blog的理由都被昨天的一条新闻击碎:

罗纳尔多退役了。

就像你永远感谢父母把你带到这个世界一样。我们这一代的很多人会永远感谢他把我们带入足球世界。甚至,他2003年在曼联主场Old Trafford上演的帽子戏法征服了当时在现场看球的一个叫阿布拉莫维奇的俄罗斯富商,这场比赛之后,他买下了英超另外一家球队,切尔西。

我在8岁初识罗纳尔多,那时他在一家叫巴塞罗那的俱乐部踢球。我想,当时会有很多和我类似的孩子,在看完罗纳尔多踢球后,第二天便抱着个足球到操场上开始模仿他的动作。也总以为自己学的很像。于是进完球后再开始模仿他的庆祝动作。我换了牙后,门牙间有点缝,这本是缺陷,我却引以为荣。每次妈妈唠叨说叫你换牙的时候舔,我就回她:罗纳尔多也是这样的。

这么多年过去,我已经不再像过去那样疯狂踢球。巴塞罗那俱乐部和那座城市成为终身至爱。罗纳尔多也把欧洲转了一圈,从一个清瘦少年变成了媒体口中的”肥罗“,拖着没有一块健康肌肉的双腿回到了巴西,终于在昨天选择退役。

那个最开始称他为“外星人”的英国白发老人罗布森,也是巴萨的前主教练,在两年前,因为癌症去世。

不知道为什么,我想到了杜拉斯《情人》的开头(王小波在《我的师承》里也提到过):

“我已经老了。有一天,在一处公共场所的大厅里,有一个男人向我走来,他主动介绍自己,他对我说:“我认识你,我永远记得你。那时候,你还很年轻,人人都说你美,现在,我是特为来告诉你,对我来说,我觉得现在你比年轻时更美,那时你是年轻人,与你那时的面貌相比,我更爱你现在备受摧残的面容。”

巴西人能把足球变成一种跳舞的游戏。所以罗纳尔多不在乎巴萨和皇马的世仇,也不在乎米兰的同城之恨。对于他,足球是一个好玩简单的游戏。在他职业生涯的最后,我也喜欢看着这个胖仔还在球场上用他的体重欺负别人。

与你那时的风驰电掣相比,我更爱你现在呼啦圈一样的肚子。

他老了,再见,罗纳尔多。谢谢过往的15年,很多人最美好的15年。

Here I Am

February 12th, 2011 § 3 comments § permalink

拥有自己的一片自由天地是很幸福的事。