- 录音/幻灯来自作者,版权当然属于他们
- 文字听录来自 Zoom.Quiet,一切文字问题都是我造成的,与原著无关
- 因为本人技术有限,仅通过幻灯和录音,记错的地方负责在我,与原著者无关
- 任何不满和意见,请直接与我联系以便改进
青年学人聚合的 1217俱乐部 发起者之一,
杨早 1973年生于四川富顺。中山大学文学学士,北京大学文学硕士、博士,现为中国社会科学院文学研究所助理研究员.
- 不知道什么机缘,进入 IT 技术农民为主要成份的北京 OpenParty
- 而且,直面如日中天般从USA空降QQ的技术副总裁,刚刚连续出版两本好书的 吴军博士,如何拉票,获得发言权?!
- 早哥的主题简述,极利的,值得学习!
谢谢各位,
我想,今天,我是和诸位人生轨迹最不相同的一个,
刚刚吴军老师很谦虚的介绍自己説最不会写书,
那我要説是刚好相反,意思是写书是我的专长,但是除了写书,我没有任何专长!
所以説,我是个非常纯粹的文科生,
可以説,各位懂的,我都不懂,
我懂的各位都懂,所以,所以,在此我算是非常弱势的群体,
但是,今天作为弱势群体我们也要发言,不论是草根屁民屌丝都是要发言的!
今天,是主要目标在交流的活动,嗯;
我个人的愛好呢,应该同人人差不多,喜欢旅游/阅读/聊天儿,
那么,呃,打羽毛球也很喜欢,每周打两次,所以,
我感觉在所谓专业之外,我们还是有相同之处的,
所以,过会儿希望能同大家再聊一聊...
- 很民国范儿吼!
- 断句,怎么听,怎么象台湾的文学博士兼相声大师
馮翊綱 !
昨天 ,昨天我在北大见到了白先勇先生,先生从台湾来是来为他的新书作宣传的.
他问我:听说你们这儿最近 杜甫很忙 , 民国很热 ? 你觉得这种情况会持续下去嘛?
我跟他說: 杜甫很忙 这事儿很快就会过去了,现在已经是 包大人忙 ,
民国热 反而会持续下去,为什么呢? 因为我觉的,对民国的一种喜欢或説 眷恋 或是迷恋,
实际上是对我们当下社会焦虑的反馈...
(看现场反响一般,立即切话题!-)
呃,在这儿,先跟大家分享一个自己的往事吧...
刚才説过,我的专长是写书,使用电脑进行写作,还算比较早的,大約从1992年开始有第一部电脑.
就在各位才几岁时,那时候电脑还很贵,也很容易坏,而且維修的地点也不多,
那时你会刻意的! 就象现在你 要努力认识几名医生 一样,
你会刻意的认识一些 IT 人士,来帮你修电脑.
这些IT朋友呢,当然修电脑是免费的,比如电脑蓝屏了,黒屏了,点不亮了,请他来修,
虽然不用給銭,但是多少总得请頓飯什么的,
那么我为了节省这个成本 ,我就坚持每次帮我修好了:ok, 你能否告诉我,为什么坏,怎么处理,下次就不用再麻烦了嘛.
我每次都坚持问一下,但是, IT 朋友们每次都很生气: 你问的这个问题,比如説 windows 蓝屏了,
就算是 bill gates 本人也回答不出来!
那我就很奇怪,你能修好,为毛回答不出它为什么会坏?
再后来,我到北京大学读了7年书,感觉最大的收获呢,就是在中国的硅谷学会了 攒机 ;
学会了后, 才发觉朋友的问答是有一定道理的:
- 因为,每一个毛病出的部位都不相同
- 虽然,电脑内部就那么几十样部件
- 但是!排列组合一下,可能情况那是非常的多
- 然而,你的目的是最后把电脑修好,而不是要找出错误的根源!
- 所以,你想找出错误的根源,或是説,你想从错误的经验中获得教訓从而以后避免
- 其实,比你修好它,要花更多更多时间的一种事儿,,,
所以,我就是那种很想很想从历史中得到帮助的一种人,
我很希望,修电脑的历史能帮助我获得以后可以判定电脑为什么坏的经验!
但是,事实上,历史经验对我有没有帮助呢?!
这其实是个问题,值得怀疑的问题.
然后,我不知道在坐多少人看过一部英剧:叫作 IT 狂人的,
里面的主人公是一家公司电脑部的技术人员了,
他每当收到一个报修电话,回答的第一句话,一定是:
- 你有没有试过
重启 ?
- 那,这就是经验,很多时候,重启就可以解决不知道为什么发生的问题!
其实,很多时候,在社会的历史发展过程中,这句话也挺管用的...
比如说: 1976年,有个人对中国就説: 你有没有試过重启? 这人的名字是:邓小平
所以! 有的时候,如果不知道这个社会出了什么问题,或是什么的时候,
你也許就只能想办法重启,重新获得一个途径来解决.
但是,这时,你是不知道原因何在的.
那,更深一步的,就是只能将硬盘低格化了,
我们转换成社会术语就是,我们 革命吧 ,换种政治体制吧,我们就重新开始一个社会历史进程吧!
但是,你不知道,其实你也不知道,这个全新的历史进程是否能带来更好的效果.
米兰.昆德拉 在 "生命中不能承受之轻" 里举过一个例子:
- 捷克这个小国家哪,非常的为难
- 因为在历史上,她遭遇的第一次大侵略的时候,选择了英勇的抵抗! 但是,抵抗后,被征服了,然后被奴役了好多年
- 第二次再被侵略时,就不抵抗了,就投降,然后,被征服,又被奴役了好多年
- 变成説,不论抵抗或是不抵抗,总是要被奴役好多年
- 那他就説,所謂面对历史事件的时候,我们这种沉重而艰难的决心有什么用?
反正都是被奴役好多年!
(~5:06)
我刚才説的这些,其实是想説,同科学不一样:
- 数学这类科学,追求目标是简单! 越简单的东西,可能是最有效的
- 但是,历史是相反的,历史有的时候,追求的是复杂!
- 因为,凡是把历史説的跟 小葱拌豆腐~一清二白的,我觉着都挺不靠谱的!
- 当然,这种比较受欢迎 ,但是,我感觉真的是不靠谱的!
呃,咱们今天时间有限,能讲哪儿算哪哈...
(听出来了,不给限制,早哥想讲多长时间都厚的住的!-)
我们向历史要什么 的起源,是来自于这个年初,我们出的一本书,
书名是: 《 话题2011 》
- 那么,首先,我们在书中作了个判定
- 説: 2011年,是被历史大规模征用的一年
- 那么大家都知道,去年是:
- 辛亥革命100周年,引发了很大的争论
- 也是清华的校庆 100周年,也引起了很多争论
- 还有民国教材热,卖的很好,,,
- 还有一些名人/媒体,提出了 "民国范儿"
- 象这样一些种种的社会现象,合到一起呢
- 我们开始对历史进行反思
- 但,问题是,当我们对历史进行
反思 或是 要求 时
- 我们,究竟是
想要什么?!
- 我们是不是想借助历史的镜像,就是将历史当作一面镜子,来看清自己,呢?
- 还是我们希望或是规避历史的重演.呢?
其实,我想,在我们向历史想要什么的时候,基本上就是这么三条:
- 我们想要一个什么样的社会
- 我们要作什么样的(社会)人
- 我们要培养什么样的后代
- 第一个问题,决定了我们为什么要重新思考100年前的辛亥!
- 第二个问题,决定了我们为什么讨论是否要民国范儿的问题.
- 第三个问题,其实我们不论是讨论清华校庆,还是对民国教材进行描述或是重构的时候,都在讨论这个问题!
这些是不论我们什么专业,不论我们在何时何地,都避免不了要讨论的这三个问题...
所以,我説,你热衷历史的时候,实际上反应的是你内心的欲望与焦虑!
这是我们的一个判断!
呃,顺便介绍一下,我们从2005年,就一直在做的事情:
- 我们每年,会出版一本书,叫作 "话题20XX"
- 我们每年会探讨当年的社会热点
- 但,我们为什么要做这个,我们做这个,和一般的媒体又有什么区别!?
(~7:41)
話題 的最高目标是,追求新闻的历史化!
- 我们刚刚説了,历史是靠不住的
- 而新闻大家会比较认为可能是比较明确的
- 比如说,你会坚定的认为:
药家鑫 该不该死, 钱云会是不是被谋杀的,你也会坚定的认为,韩寒有没有抄袭或有没有代笔
- 这些问题,可能是你会坚决认为的,因为它们是新闻
- 但是,如果你把他们放到一个历史框架里的话,你就会发现事情,远远没有那么简单!
話題 有简单的三个宗旨,我简单的介绍一下:
- 第一点,
播新知 ,意思是我们想告诉大家一些,你可能不知道的事情,有些事情你知道的话,就会觉得,其实就是这样的,有句老话説:"太阳底下没有新鲜事"
- 比如説,我们有一期作过一个話題,説是,有一年,不是特别对女博士特别歧视嘛
- 呃,赵薇有次上期节目时,有人问她説: 你还读博嘛? 我才不读博呢!
- 大家都知道,有种划分法: 男人,女人,和女博士
- 那么实际上对女博士构成了一个很大的歧视和伤害
- 那么,我们裏面有篇文章,就会告诉你説,这个东西,其实不是从现在开始的
- 自从,中国有了现代化以后,女性开始登上第一流的学术平台以后
- 对高知女性的这种看法就没有停止过!
- 只不过,最早,比如说,晚清的时候,他们对女学生有看法
- 到了民国以后呢,他们觉得女中学生有问题
- 再往后呢,是女大学生,比如说,七几八几年的时候,女大学生刚刚宿舍的时候,女大学生有问题
- 再后来,就是女研究生有问题,到现在,又升高了,女博士有问题
- 所以,整个社会对高知女性的,这种凝视和妖魔化从来没有停止过!
- 只不过,这个学历在上调而已
- 这种,算是我们告诉大家的新知的东西
- 第二点,
列谱系 刚刚这已经反映到了
- 要再举个例子,就是,大家都知道 08年的时候,有所谓
四月青年
- 就是传递火炬在国外受到阻碍时,国内有抵制法国货的运动,围攻家乐福的这么个浪潮
- 另外,抵制日货的运动更加是从来没有停止过,差不多一两年就会搞一次
- 呃,那年,我们也作了一篇话题,叫作:"抵货运动103年"
- 因为抵制外货的运动,是从 1905年抵制美国货正式开始的!
- 那么,在这么长的时间里,我们抵制了差不多有,40次的外国货
- 但是,数据会告诉你,每一次抵制外货,并没有对所在国的经济造成任何可见的影响
- 而且,一般在第三年对他们的进口量会增加
- 换句话説,抵制运动更多时候只是一种情绪的宣泄,而对实际经济,嗯嗯嗯,
- 08年,有人作过图表,説我们只要抵制家乐福,就会对法国造成影响等等
- 这实际上算是一种 YY 吧,因为实际上这种情景从来没有出现过
- 这种,算是我们告诉大家的一种往事吧
- 第三点,
破虚妄 ,这种问题往往产生于什么呢?
- 比如说,外国媒体怎么样看待中国,中国人又怎么看待外国媒体,外国人又怎么看待中国人怎么看待外国媒体,然后,又是中国人怎么看待外国人怎么看待中国人怎么看待外国媒体...
- 这样一种循环往复的过程,每一次,都会造成新的误解
- 比如说,他们又説中国人又在反 CNN 了,中国人就説,是他们在抺黑我们了
- 他们又説你们还在继续誤解
- 就是説,越來越多的这么个压制,大家应该记得今年 "泰坦尼克号 3D版" 的笑话吧
- 有那么个网络謡言传到美国,居然
卡梅隆 也相信了
- 説中国政府之所以删掉 Rose 那个露点的片段,是因为3D 画面下,中国男人会忍不住伸手去摸那个,,,她的裸体!
- 大家肯定看的出来,中国人肯定知道这是个笑话
- 但是! 为什么
卡梅隆 相信了这个,呢? 謡言!
- 是因为,美国对中国的报道中,被压抑,是他们特别主题的一个词儿
- 所以,他们所有人都认为,中国所有人都是被压抑的
- 那么,一个长年被压抑的中国人,在面对如此高科技忽悠的清晰的触目的画面的时候,他伸出手去又有什么奇怪的呢?
- 所以,这就是我説的想象的错位,会造成,呃,,问题!
- 那么,这个时候,需要有一些,对两边都比较了解的人出来,告诉我们一下
- 説:到底里面是不是有一些真实可以是被把握的
- 或是說,有什么样的法则是我们可以去运用的
(12:51)
那么这些,就是 話題 的三个宗旨吧
其实,我想說的是,新闻和历史在我的眼中,是没有什么区别的!
我们来讲一个例子吧:
- 就是
泰坦尼克号 ,大家知道, 泰坦尼克 是1912年4月12号撞沉的
- 所以,她在今年是100周年
- 那么,在这100年当中呢,她经历了不断的被叙述被扭曲,被变化的过程
- 这三幅图片代表了大致的三个归类:
- 右上角那个图片呢,实际上説的是这个,现实的
泰坦尼克 她是一个工业社会的一个顶尖的结晶作品,她同时也是一个工业崩溃的一个象征!
- 当
泰坦尼克 撞毁了,大家知道,1912过后两年, 1914年,一战就爆发了
- 而一战的爆发就象征着所有的工业革命带来的成果,特别是在人性方面,社会方面的成果,在几年之内毁于一旦!
- 连续的一战,二战,基本上,我们説,人类社会经历的一次电脑重启!
- 而
泰坦尼克 就是重启前的最后一次輝煌!
- 这算是
泰坦尼克 本身的一个历史角色
- 那么左边这幅图呢,代表的是当时对
泰坦尼克 諸多的叙述
- 下面我们会讲到,因为
泰坦尼克 事件中有一些非常感人的故事
- 比如说,他们会让妇女先走哪,再比如说,船长会最后同船一起殉难哪,还有大家可能都記得,乐队会演奏到最后一刻哪
- 就这么奇怪,一次沉船事故,会被描写成这么一个伟大的故事
- 那么第三个,大家都很熟悉,就是
卡梅隆 拍的,15年前拍的那部惊天之作
- 他把
泰坦尼克号 变成了一个,举世皆知的一个,呃,伟大的,嗯,伟大的爱情故事
- 这就是另外一种书写方法
- 就是,我想說的是什么呢? 单纯的事实不是历史,历史是对事实的阐释
泰坦尼克号 沉没是个事实
- 但是,这个事实,不是历史!历史是对它的不同阐释!
- 所以,基本上,基于
泰坦尼克号 沉没的这个事实,已经衍生出了各种不一样的历史
- 大家注意! 当你使用它的时候,你会发现,在使用什么样的历史
- 比如,今天依然在争论的一个話題,虽然都已经100年了,
- 到底!是妇女儿童优先,还是等級优先?
- 大家都知道,这里有一组数据: 头等仓有乘客319人,幸存了200人,幸存率63%
- 二等仓的幸存率43%,三等仓的幸存率25%,从这个看起来,是不是就能說其实
泰坦尼克 的救援是等级优先,如果你在头等仓,就可以得到更好的救助呢?
- 那看旁边的表格告诉我们説:一二等仓一共32个儿童,最后死亡一个,三等仓一共75人,最后死亡15人,把这两个东西結合起来,我们是不是可以得出结论說:
泰坦尼克 的救援是在等级优先的前提下,儿童优先呢?!
- 就是説上等人买得起上等船票,我们知道票价差别很大! 头等舱最贵的达到300多英镑,而最便宜的三等舱,只有8英镑
- 呶,这个价格差别真的很大!
- 那么,从这个数据,我们是否可以説上等人更加照顾儿童?而三等舱的这些人,就更加无视儿童
- 这就是从
泰坦尼克 浩如烟海的数据中得出的一个结论
- 但是,这个结论是否可靠? 其实很危险的!
- 我可以再换个角度告诉你吼,这个数据幻灯里没有列
- 大概,
泰坦尼克 中英国人的死亡率,大约超过 75%
- 但是,美国人的死亡率低于 60%
- 所以,他们有人开玩笑說,你要想在
泰坦尼克 中生还吗?
- 第一,你需要有张一等仓的船票,第二,你需要是妇女或是儿童,第三,你需要是个美国人!
- 为什么需要是个美国人?! 那后来,有一些反思,告诉我们說,因为英国人他们更讲秩序,讲礼仪,而美国作为一个,脱离蛮荒不久的国家,他们更加强求个人的生存问题,所以,美国人相比会活的更久一些
- 这也只是其中一种説法,这种説法也不一定靠得住!
(17:44)
那还有些説法的:
- 比如说,我们可以看到,这是
泰坦尼克 最早的中国报道啊
泰坦尼克 是4月12号沉没的,左边这个是 4月19号上海申报的报道,很短,只有40多个字,就46个字
- 它告诉我们說,有一个船,它同冰山互撞,然后就沉没了,但,它在上面就已经谈到了說:船中女子己如救生艇!
- 最早的报道,就已经出现了这一特色!就是对妇女的尊重,这就已经是
泰坦尼克 的一个特色了!
- 那么右边儿呢,是1913年,商务印书馆,出版的 "共和国教科书" 裏面,就已经刊载了这个故事!
- 那么,裏面也是强調說: 男子让女子先
- 也是这么个故事,是不是靠的住?有一个反面就是,我们知道
泰坦尼克 上有8个华人
- 而这8个华人,有人説是逃票的!也有人說,不是逃票,而是经过船上的同意,然后8个人买了两张票上船,这个具体情况,已经不知道了
- 问题是,这8个人的表现如何呢?有报道説,这8个华人,表现非常糟糕:
- 第一,他们完全不懂得救助妇女儿童;第二,他们其中有两个人,很早,自己就钻到了救生艇的底部,没被发现!
- 然后第二天,也就是隐含的意思說,这两个逃票的,他们上船后,为躲避检票,就钻到了救生艇下藏着
- 第二天,船要沉了,所有人住救生船上涌的时候,到了船划到岸边,才发现下面还有两个人,两个华人,已经被上面的乘客,都压烂了,,,
- 那么,这个报道,被西方媒体传播过来,就完全被中国媒体接受,并报道
- 甚至于,到1936年的时候,有篇报道說,
泰坦尼克 是中国人之耻!
- 但是! 问题是,这个説法,大家知道当时 ,那个救援场面非常混乱,到底有没有这样一个事情,到现在,也没有被证实!
(20:00)
另外有报道説,还有3个印度人,想抢着上救生船,結果被船长开枪击毙!
- 但,同时也有两名英国乘客,他们发誓説: 整个救援过程中,没有任何人开枪
- 那,请问,我们应该相信誰的話?!
但是,有趣的是,全世界媒体,都相信第三世界的人在 泰坦尼克 救援过程中表现的很差!
甚至于,连我们自己都相信这东西....
这就是期中有意思的地方,在这样一个简单的历史事实面前,尽管其中有些细节没有做到证实
- 但是,由于我们惯常的一些心理,比如说,认为东方人的教育水平比较差,他们素质比较差,他们就肯定不会,这么在乎妇女儿童的生命
- 那我刚才説, 英国人美国人是一样的,就是說,换句話說,在救援过程中,每个人,每个人种是分了等级的
- 但是,事实上我们知道,在这种灾难面前,个人的选择,有的时候,会远远超越种族哪,性别哪,国别哪,这些东西
- 但是! 如果公众想了解一个事实的时候,他需要媒体把这个事实简单化,他需要很清晰
- 就象我们认识一个新的人,首先会问,你哪儿人哪?或是説:你是什么学校的哪?
- 你只要了解了几个信息,你就可以很快的在心里勾勒出一个可能跟他完全无关的一个形象来
- 比如說,你是,是那个...河南人!是吧?
- 或者説你是哪里哪里人...更广点儿,如果你遇到国际友人,哪,你是日本人,或是你是肯尼亚人,或是哪儿人...
- 你就会自动的把一些,你心目中的文化印象,叠加到这个陌生人身上从而,可能会给他一些,他完全不具备的一些素质印象
- 所以,这就是,我们在接受一些信息的时候,会陷入一些很多的思維誤区!
然后,最后我们再說一下那个 泰坦尼克 电影的问题:
- 对这电影,我得承认,我是很不喜欢的,
- 因为,我认为它只是满足了好莱坞经典的
三一律 ,就是:
- 而它借助这个灾害片,把这个灾害变成了爱情因素,是因为,它认为在这个极限情景当中,爱情会经历最大的考驗!
- 而,相反,我认为是,在极限经历中,爱情最不需要去考驗!
- 因为爱情! 有种理论說,呃,,,催生爱情的那种荷尔蒙,大概只能维持1000天,就是説爱情只能维持1000天
- 换句話説,对爱情最大的威胁是平凡的生活,和日复一日的重复! 这才是最大的考驗,而不是惊心动魄的同生共死
- 因此,
泰坦尼克 实际上是給了爱情一种最好的环境,就是你跳我跳嘛
- 那时,作出一个选择有多难呢? 反正也都是亡命之徒!
- 一个屌丝爱上了一个白富美,为了她去死,有多奇怪呢?!
- 所以,我觉得到了
卡梅隆 的电影里,他虽然花了很大力气,嗯,我承认电影本身是一个非常伟大的MOVIE
- 但是从电影本身来說,它其实上传达的是一个,呃,非常单面化,或是說非常简单的,就象我们把一个经济学的东西,我们把它画成了一个简单的模式来运行一样! 但是,你完全没有考虑到各种复杂的层面.
- 所以,这电影,説老实话,我感觉是把
泰坦尼克 的这个复杂事件给,最!简单化了,简单到我们几句话,就可以把这事儿説完的地步,凡是一个故事几句话,就可以說完的话,那我刚才就説了,这种故事,一定是不可信的...
- 但是,同时,王国维有句话也說:可信者不可爱,可爱者不可信!
- 不可信的往往是可爱的,所以,它才能拿到这么多票房,而且贏得这么多的眼泪!
呃,由于时间关系,下面的例子,我就不举了,有机会的话,我们再交流,然后,我们留点时间給大家提问好不好?
謝謝!
问: 其实我们向历史要了一个角度的见解嘛? 您感觉,我们可以向历史要到更多什么嘛?
答: 呃,谢谢,我这題目未来准备的是2个层面的内容
- 一个是,我们正在向历史要什么,刚才已经說的很清楚
- 另一个,是想説,我们能够向历史要什么?!
- 其实,其实我们有一个观点是說,其实是同上次有人问历史有没有用的问题一样的
- 基本上,我的看法是說,
历史是,没有什么用的...
- 就是,我刚才說了嘛,你上次发生的事情,下次你用同样的方式应对,一样可能錯
- 历史上正确的方法,也可能导致錯誤的結果
- 而且,何况,它本身就没有什么錯誤之分,对于一个很复杂的系统而言
- 那为什么,我们还要,还需要历史?为什么历史在我们生活当中,还属于不可缺的位置,呢?
- 我觉,这基本上是人类的一个
本能 ,就說,人类作为一个有知识,有记忆的一个物种,必然有一种回溯过往的本能!
- 她需要知道,我是怎么过来的,而这个回忆,是你把自己在这样一个大千世界包括时间,的这样一个四維空间内,你可以将自己安放在什么位置的这样,呃,一个必要的元素!
- 换句话説,如果你不记得,历史的话,你的世界将去掉一维,就象
三体 里的降维攻击一样
- 你变成只有三維存在,但是你作为一个不知道自己过去的人,,,
- 大家想一想,有很多电影和小说,都在讲述,当人患了失忆症以后,会导致一个什么样的結果!
- 你就变成一个历史完全空白的人,
- 作为人类本身,也有同样的问题,如果人类的历史完全被抺掉,就象硬盘被格式化了一样
- 那人类,会变成一个什么样的状态呢?
- 我觉得,我很难想象!
- 其实象空气一样,我们可以說历史没有用,历史对于我们的人生没有指导,我们不可能从历史中得到一些具体的指导原則
- 但是!你想想,如果你的所有的记忆都被抺掉了以后,大家可以想象一下这个场景
- 如果,我们整个人类的历史都被抺掉了以后,会是个什么样的状态!?
謝謝!
整体感受哈:
- 文科生都这么发自内心的逗乐嘛?
- 台湾腔就是文艺腔的正式状态嘛?
- 早哥要是出台 talk show,徳纲就危险了哪!
- 对历史这种态度的话,真心很冷漠了...
只是社会心理的需要,
是我们作为四维生物的必须
- 但是,俺喜欢! 完全的 SiFi 物种视角呢!
最后 Ada 和 笔者合説的 如何从0创建社区+FLOSS社区如何联合 ,
幸运的放在了大厅,有超过40人听到结束,
检查录音才知道是超过一小时的大 Discuss ... 但是,感觉并没有展开説些什么哪...
ada:
- 从自身的体验出发
- 分享从公司立场出发,如何兼顾技术社区同公司部门间的期望
- 以及,应该以什么样的态度来引导外部成员
1 。宣言
2 。公开透明
3 。核心成员
4 。成员间的相互连接
5 。耐心
笔者:
- 个人/社区/公司 的关系图景
- 现有的 TopGeek 模式
- 倡议,帝都人民联合起来
(来自盘古搜索的,陈越,最后进行了非常正统的总结,很条理性的将当前中国技术社区的发展原则进行了总结,心有戚戚,郑重听录下来:-)
总结談不上哈,我本身也不是搞技术的,所以,在这儿,也算弱势群体!
但是我想的話,大家讲了很多社区这块的事儿,自己有些想法,
所以,要跟大家分享一下最近在看的一本书,就是: "共产党宣言"
- 其中有句话就是:
全世界无产阶段联合起来!
- 社区也一样,需要我们所有成员联合在一起
- 那么联合起来作什么呢? 作一个联合体,而我们每个人,有联合体中,又都是自由的
- 从而形成一个半封闭状态下的,小共产主义社会!
- 在这种社会中,我们每个人贡献自己的聪明才智,包括我们的知识,
- 而这个联合平台呢,可以按需分配,就是說,我们需要什么,自己去取就好
这就是重新学习 150年前的, 所謂的名著哪,这样一个我自己的初衷!
- 因为,我一直认为,马克思,他不是政治学家,他基本上应该算是心理学家
- 这位同学(指笔者),刚刚在白板上画的三个层次,刚好,或是是説反映了我们当前社区里面需要在聚合性方面考虑的一些问题
- 首先是个
.me ,对吧,就説,我们每个人参与到社区里,作为相对孤立的,就象原子一样,进入到社区
- 随即,我们进入到一个
.org , 成为一个非贏利性组织的,虽然叫非贏利组织,其实,还是有共同目标的,只是不以贏利为目标而已,更多是种公益的心态,获得一些收益,而收益的形式,更多时候不是以金钱的形式存在的,比如说更加丰富的人生哪,更多的知识哪,或是更多关系的沉淀哪,,,
- 那么到最后,总是形成一个
.com 的形式,就象 CSDN 就是一个很典型的例子
- 这种趋势,也是我们作社区的应该的考虑
而,这三种形式,其实本质要求不同的制度性!
- 在
.me 阶段, 可能更多是种小团队形式 ,都是平时相互间就很熟悉的一种聚合,这其中可能就需要英雄! 需要有一两个,所谓的 20/80 这样一个原则,会更加有效,通过 其中 20% 的核心成员,作为矛,将大家都定住,这时的凝聚力,多数是由这 20% 的成员提供的
- 而到了
.org 的层面时,就可能需要另外一种机制来管理了,这种机制,刚刚也説过了: 可能需要一些封装,正如 Ada 讲的,如果每个人都有具体奉献的話,他会对社区产生感情,同时他对社区的位置也会更明确
- 到了
.com 形式时,可能,分工就会更細,分工会更加明确,再然后,就有收入模式,收入模式再转化为商业模式!然后变成贏利模式.
- 最后,我想,最后每个社区都会变成一个平台
想起,在 YouTube 上看过一段视频:
- 有一群人,在海滨啊 (其实是一山坡)
- 突然有一个人,光着膀子,穿着短裤,跑出来,以奇怪的姿势,在舞蹈
- 然后 ,这一个人是否能激发起大家一齐来嘛? 不见得
- 所以,它有第二个人,唉! 他看到这个情景,他也一把将上衣脫光了穿着短裤,跟头个人,一样的姿势,在奇怪的舞蹈
- 第二个人上去之后呢,就有很多人加入进来了! 結果,最后形成这么一个群魔乱舞的情况,形成了共振!
然而,我们作社区的話,可能也需要这种人物,他第一个,第二个,进行各种无私的奉献!
我看完视频后的思考是什么呢?
- 就群魔乱舞的这么个行为,或是状态,它可以持续多久?
- 这种依靠激情发起的都不长久 ,就象刚刚杨老师讲的一样,爱情荷尔蒙,最多只能持续一千天,之后的话,肯定就归于平淡了!
- 那么我们如何让社区可以长期的,有这么种生命力,持续发展下去呢?
- 我们是否要进行一个郑重的区分?
- 还是根据
20/80 法则,对于其中 20% 的人,他考虑的事情是完全不一样的
- 比如说,他可能更加关注名声,就象 weibo 中的fans ,fans 来加我,或是 blog 中的点击率增加了,或是得到更多的演讲机会,对个人品牌的这种影响,就可以象那誰去美国参加开发者大会
- 而对于社区更多的大多数,其实才是一个社区的成员基础,因为一个社区,他不可能靠 20% 的人去运行
- 还是靠那 80% 的成员来参与
- 而这种参与的流动性是很大的,而这种流动,我认为是符合规律的
- 因为你想,象 BLUG 每天就总是这4,5十人聚会聊天 ,談了一段时间后,大家对彼此的新 idea 什么的,就没了
- 这样的話,社区的流动性,对于社区的发展是必要的
- 但是,这也是个双刃剑,如果每次来的都是不认识的人,每次会议上,都要将所有人激发起来,也是很困难的事儿!
- 而对这 80% 的人的述求,肯定是不同的,他更加需要一些工作机会,一些知识,至少今天我来了,听到了从未听过的,新东西,那才感觉值,特别是在北京哪,两个小时的成本,让要感觉值!
- 否则下次肯定不会再来了
- 另外的話,可能是想来建立一些关系,比如说,今天我认识了吴军,认识了 Ada ,认识了你,这样的关系,对我来說是很有价值的!
- 这样,我可能在将来将这种关系转化为合作伙伴!
所以,我想,要想把社区作好:
- 第一,要根据社区目前的组织形态,类似前面說的
.me /.org /.com 设计一些不同的机制
- 第二,在不同层面的社区组织,都需要对
20/80 的成员,作好区分,提供不同的激励机制
之前哪,也曾经和一个老师作了一些研究, 自组织
- 现在的社区里,大家都是根据兴趣聚焦起来的
- 那么这种兴趣可以形成组织化,结构化的形式,就可以产生比较好的
- 这里我们其实可以引人一些民主原则:
- 比如说,我们可以进行选举
- 不是大选举,因为社区这么大,不可能所有人都认识你,熟悉你
- 所以,是否可以采用一种小范围的,5,6人,或是7,8人一个小组,小组里选出组长,再从组长里选出几个大组长...
- 这样,根据人数多少,你可以将层級无限住上叠加!
- 我们曾经测算过,中国13亿人,最多13级也就够了!已经可以选择出一名主席出来了
- 那对于一个社区来讲,可能3,4层,就已经可以管理一个非常大的组织了!
以上,是我的一点看法,也許能提供給大家作个借鉴哪.
所以,以后有机会再深入交流了!
謝謝!
最后的自底向上式的集中民主制度
- 其实在1991年秘密出版的,入选了
二十世纪中文小说一百强
的 王力雄 政治科学幻想小说:
"黄祸" 中就提出了
- 同现代,信息论中的自组织,不是同一概念,,,
当然,陈越 指出社区有不同的发展阶段
- 每个阶段都需要配合对应的管理机制
- 以及,永远要给不同的成员,提供配套的激励机制
都非常正确,,,
- 只是,落到实处,就是各家有本儿难念的经了,,,
- 从目前看来,中国技术社区主要缺乏的是:
- 有效沟通
- 持续的新人加入
- 稳定的外部资源支持
- 以及,最要命的社会认同感
好在,或是有不安份的行者们,义无反顾的跳出来,带领应该带领的不断联合前进!
其实,我想説的:
- 作社区,最好在你自个儿成功以后
- 什么叫成功?
有房,有车,有存款!
- 学习 Ubuntu 的 Mark,随便丢个 3KW 刀出来,大家才愿意追随哪!
- 坊间有説:
怎么説,在哪儿說,何时説,説什么,都不重要! 重要的是:誰来説!
不过,真心有人不尿这些的,安心研究自个儿喜欢的,分享自个儿学到的,齐活儿!
- 只是,这种生活态度,不是社会主流哪
- 所以,社区也同江湖一样,立山头,拉名人,,,,
不說矣,不説矣,俺就一热心大妈,作能作的,忽悠能忽悠的,齐活儿!
- t2t渲染:: 2012-06-06 04:58:02
- 动力源自::txt2tags
- 在各种想象不到的地方,有各种隐士在快乐的学习以及使用 Haskell
- 甚至于,图书都有慢慢在翻译的,,,
但是,到底有多少中国人,在学习,使用 Haskell ?
真心不知道,好象也没有人知道...
- QCon北京2012大会 "编写显然正确的代码" ~ 黄毅,已经首次,公开吼 Haskell 了
- 当然,其实,以前在沙龙就吼过... Haskell介绍
- 好象,各种媒体,慢慢的因为多核,因为并发,重新关注起来了 Haskell
- 豆瓣小组里终于:
- 好事儿呢! 相关 Google groups 也创立几年了,只是一定没有什么热闹的讨论
- 因为没有什么大家都可以掺合的 hs 实践,除了自学,写点片段自娱自乐...
- 有了社区,就聚集了人
- 有了人,就应该有很 COOL 的项目
- 有了项目就有了代码,将代码运行起来,服务我们自个儿,,,
- 社区就活跃了呢...
然后? 我们需要什么社区功能?!
动力源自::txt2tags
- 活动: Tech-Club技术沙龙(2012年2月)活动小结
- 幻灯: ngx_openresty: an Nginx ecosystem glued by Lua
- 录音: 120306_ngx_openresty.mp3
- 笔录: Zoom.Quiet <zoomquiet+[email protected]>
- Chnangelog:
- 131213 fixed losted http://vdisk.weibo.com/s/2Qcon
- 120312 fixed as s/hhttp/http/g ,thanx muxueqz
- 120309 fixed kindel->kindle, thanx for milel liu;
- 120308 fixed ahcking->hacking,thanx weakish
- 120306 fixed agentzh ID name,thanx himself alert
- 120305 finished
- 120301 init.
很早就一直关注 agentzh 对 nginx 的给力 hacking,这次总算有个阶段性的说明,虽然无法现场交流,
好在有录音,为了其它没有时间听的人们,以及给搜索引擎更好的搜索数据,俺义务听录全文;
- 录音/幻灯来自作者,版权当然属于他们
- 文字听录来自 Zoom.Quiet,一切文字问题都是我造成的,与原著无关
- 因为本人技术有限,仅通过幻灯和录音,记错的地方负责在我,与原著者无关
- 任何不满和意见,请直接与我联系以便改进
很高今天和大家进行分享,之前,在北京进行过相关的分享;
今天我们的話題是 Nginx 也可以說是关于 Lua 的;
介绍过去3年以来我们的工作,
工程名字是,openresty,可以追溯到2007年,那会儿,我刚刚进入 Yahoo! 中国,
第一份工作就是架构一个开放平台, Yahoo! 自个儿的开放平台,
系统作到后来逐渐偏离了初衷,
我们开始为大型的互联网公司作一些和web 前端打交道的系统支持;
我在 Yahoo!和 TaoBao 分别工作了两年,就辞职了;
主要因为,我们的开源作品,越来越多人使用了,
而我一方面,要应付所謂业务需求,另方面要响应来自国内外积极开发者们的要求或是bug;
所以,干脆辞了专心作事儿;
本来,我想搬到厦门,可是我老婆在福州找到了工作,于是,,
现在,我不拿工资,义务为全球的愛好者开发 ;-)
现在,已经在福州呆了7个月,这是我老婆给拍的照片;
我习惯,先在纸上写好代码,然后输入电脑,
前面放的是 kindle ;
这台 kindle 的来历比较有意思,
- 在TaoBao 的时候,我打算将 openresty 重写,因为一开始是用 Perl 来写的
- 而在Yahoo! 的时候虽然已经使用 openresty 統一了搜索功能,但性能的确一般
- 当时,本想基于 Apache 来改写,不过一位师傅跟我讲:"你就直接拿c 写吧,基于 Apache 写没有前途的!"
- 俺很郁闷,就问,那怎么整? 师傅回答,你研究一下 nginx 的源代码吧,然后就没再理我
而看代码是很累的,所以,俺一到 TaoBao 就买了台 Kindel 来看代码...
刚刚提过, openresty 在开发过程中逐偏离了原计划;
再面对后来,更加具体的公司业务后,
这时,已经可以看出所謂 Ajax/Servise 化了,
在我接触过的各种繁忙的互联网公司,都有种趋势,就是:
对看起来是个整体的web 应用
习惯在后台拆成很多 Service
有些Service 是供給客户端发起請求来访问的,
而有些Service 根本就是为其它服务而服务的,也使用了 http 协议进行发布
这种结构,导致整体系统变得非常分散
- 由多个部门,分别实现一部分系統
- 而每个部门,暴露給其它部门的,都是 http 协议,resful 形式的接口而已
比如说, 去哪儿 网,就是非常非常松散的服务组合成的;
- 一个請求进入后,立即分解成各种請求分别进行
- 而有些就在 Service 之间进行了
既然,http 协议如此常见,我们就需要强大的实现基础;
nginx 是我们调研的各种平台中,最不烂的一个!
- 其它真心都特别烂,,,
Apache 最大的问题是其 I/O 模型,无法完成非常高效的响应;
但是优点是:开发接口规整,基于它来写 mod 非常方便;
Lighttpd 正好相反,其 I/O 非常高效,但是开发接口不怎么友好;
而 Nginx 融合了两者的优点 ;-)
<<< 5:11
- 一方面使用了 lighttpd 多路复用的 I/O 模型
- 另一方面以借鉴了 apache 的模块开发支持
在(openresty)开发过程中,经常有人问,为什么 nginx 如此之快?
- 我们知道 nginx 是单线程的,
- 而单线程的模型,为什么可以承担上万甚至上几十万的并发請求?!
因为 nginx 的工作方式,如动画所示,这是我刚刚用 perl 生成的一个简单 git 动画:
- 这其实是操作系统线程作的事儿
- 前面3个,分别对应不同的 http 请求
- 每个方块代表一个读或是写操作
- 最后的 epoll_wait 就是 linux 系統中最高效的一种事件接口
也就是説 nginx 内部其实是种事件驱动的机制
- 只有相关事件发生时,才处理具体数据
- 如果当前接口没有数据时,就会立即切换出去,处理其它请求
- 所以,虽然只有一个线程,但是,可以同时处理很多很多线程的請求处理
那么,这种形式的 web 系統,可以很轻易的将 cpu 跑满,即使带宽没有跑满的情况下;
而 apache 这类多进程多线程模型的服务器,则很难将 cpu 跑满:
- 因为并发达到一定量时
- 内存首先将耗尽
- 因为在 linux 系统中,线程数是有限的,每个线程必须预分配8m大小的栈,不论是否使用!
- 所以,线程增加时,内存首先成为瓶颈
- 即使挺过内存问题,当并发请求足够多时,cpu 争用线程的调度问题又成为系統瓶颈
<<< 8:31
所以,nginx 这样简单的单进单线模型,反而被 memcached 等高性能系统定为I/O 模型;
那么,我们作了什么呢?
- 主要是为 nginx 提供了很多补丁,进行了 bugfix
- 同时利用 nginx 提供的开发者接口,贡献了很多模块
- 我们还将之前提及的 Lua 嵌入 nginx ,使其具有全功能的交互能力
- 更加把 Lux 一些常用库,也放进去了
- 然后打成一个大包,命名为 openresty
...这是使用 Tiddlywiki 随便作的一个 主頁: http://openresty.org
nginx 本身有个很重要的特点,这在维基百科的条目中也强調过:
- 其配置文件记法是非常灵活,并可读的
- nginx.conf 配置文件,本地其实就是个小語言
比如:
1 2 3 4 5 | location = '/hello' {
set_unescape_uri $person $arg_person;
set_if_empty $person 'anonymous' ;
echo "hello, $person!" ;
}
|
这段配置,对于 apache 用户来説,也很熟悉
- 我们首先使用类似正则表达式的形式来约定一个响应的 url
- 然后,可以使用各种 nginx 的指令对内部变量进行到系列操作
- 变量也是配置文件的一部分,很象一种编程語言
- 比如,这里,我们就将 person 这个变量使用 arg_person 进行赋值
- 然后,用 'anonymous' 作为空值时的默认值给 $person
- 最后直接使用 echo 将結果输出
这样,我们就可以使用 curl 模拟浏览器访问,给 /hello 提供一个utf8 编码的字串值,
以 ?person= 的GET 方式变量,
就可以获得預期的反馈: hello, 章亦春
不給参数的話,刚刚的 anonymouse 就起作用了;
所以,整体上,我们期望在 nginx 中实现服务接口,就这样写点配置就好,不用写什么认真的c 代码;-)
而跑起来就象飞一样,因为,这么来写,实际和用c 现实没有什么区别;
事实上,全世界的开发者都在使用 nginx 的开发接口,在拼命丰富这种配置文件小語言的词汇表!
- 而真正决定其表达能力的是:"vicabulary"
- 比如说,我们看这个例子,这是我写向第2或是第3个nginx 模块:
- 用以直接访问 memcached 的所謂上游模块
- nginx 有自个儿的一套术语,在其后的各种服务比如memcached ,在nginx 而言就是上游
- 对应的,那些访问 nginx 的浏览器等等客户端,就视为下游
1 2 3 4 5 6 7 8 9 | # (not quite) REST interface to our memcached server
# at 127.0.0.1:11211
location = /memc {
set $memc_cmd $arg_cmd;
set $memc_key $arg_key;
set $memc_value $arg_val;
set $memc_exptime $arg_exptime;
memc_pass 127.0.0.1:11211;
}
|
- 这样简单的配置一下,通过 set 将url 上的各种参数映射给几个变量,
- 然后通过 memc_pass 连接到远端一个memcached 服务,当然后面也可以是个集群
- 立即,我们就得到一个,应该說是种伪 restfule 的 memcached 的使用接口服务
- 我们可以使用 curl 来操作目标 memcached 了
- 比如说,著名的 flush_all 命令,就可以直接通过 url 来执行
- 通过这种形式,我们可以快速扩展成对memcached 集群的简洁管理服务,进行各种操作
- 这样作的好处在于::
- 不論其它相关应用使用 php 什么乱七八糟的語言写的,都可以統一包装成 http 接口
- 令整个业务系统变成http 协议,这样系统的复杂度就能够有效降低
- 同样可以这样对 MySQL 等等其它集群服务进行包装
- 包括大家知道的 taobao 集群,对外部开发来說,好象是专门为外部扩展发布的服务,
- 其实在 taobao 内部各种服务也是以两样形式組合起来的
- 大家知道 taobao 是java 系的,它很多服务是通过定制 jvm 完成的
- 所以,对于ali 原先业务,以及合作方的业务,还有我们数据统计部门的业务,对于jvm是无法直接使用的
- 怎么办?所以,通过开放平台业务,将各种内部服务,封装成一系列 http 接口方便使用
- 包括taobao 的登录,其实也封装成 http 接口,供给,taobao 子域名应用来使用
- 不论使用什么开发語言,总是可以对http 协议进行访问的
- 而且 http 协议本身非常简单
- 我们可以方便的获取许多现成的工具进行调试/追踪/优化,,,
- 另外,由于选择了 nginx,这使得http 的开销,代价变的非常非常的低
- 记得 去哪儿网,原先有业务使用了几十台 MySQL
- 前端使用 java 的jodb 进行连接
- 而因为代码写的比较糟糕,因为业务部门嘛,写的时候不会注意连接池的效率,
- 所以,每台主机的负载都非常 非常 高
- 而,我们后来改为nginx 作前端,結果一台nginx 就将以前几十台java 主机的业务抗了下来
- 通过封装成 http 接口,业务代码随便长连接/短连接,随便它搞,都撑得住了!
- 于是,被他们java 程序员描述成不可能的任务,被一台 nginx 主机就解决了
<<< 17:00
(插入提问): 封装具体作了什么?为什么比原先的方式效率高? 虽然改成了 http 实际连接MySQL 时不同样要消耗?
- 因为,封装成 http 接口的数据库,我们内部使用了连接池
- 已经优化的高效数据库连接池,而一般工程师不用关注连接池的技巧,专心完成业务代码就好,不容易出错
- 而且,使用语言专用中间件的话,牵涉到其它问题:
- 中间件本身是否稳定?高效率?
- 中间件本身是否易于扩展好维护?
- 等等一系列问题,远没有統一成 http 服务于所有語言实现的应用来的干脆简洁
- 甚至于,我们后来引入了完整的 Lua 語言,它基本足够完备,可以支持我们直接完成业务
- taobao 的数据魔方,就直接使用脚本在 nginx 中完成的
- 相比原先php的版本,仅仅这一项,就提高响应速度一个量級!
- 所以,不论 memcached 还是什么数据库,我们可以統一到一个中间件
- 而且 http 协议的中间件,还有个好处是可以直接公开給外部使用
- 因为 http 上的访问控制很好作,复杂度也低
- 我们的量子統計,就是直接和taobao 主站服务通过 http 良好整合在了一起
- 可以简单的一个参数处理就发布給外部或是内部来安全使用
通过模块,我们可以建立应用和 MySQL 间的非阻塞通訊
- 这点非常重要!
- 因为,当前端访问后端很大的数据集群的时候,其本身的并发能力就成为瓶颈
- 设想后端有近百台 MySQL 时,后台本身的并发量就已经非常大了
- 而前端类似 php 技术根本无法将后端所有主机的能力都应用起来
- 所以,我们非常需要非阻塞技术
- 需要一种数据库代理,就象很高能的网关一样,将后端所有MySQL 服务器的能力都激发出来
- 而不用期待前端应用来自行完成并发调度
基于以上认知,我们开发了各种数据的非阻塞上游模块:
- 包括对 MySQL/Postgres/redis 等等
- 也尝试过对 Oracole ,但是,其官方的 c 驱动有些限制,虽然也提供了非阻塞接口,但是不完整
- 在建立连接和銷毁连接时,只能以阻塞方式进行,所以,很纠结
- MySQL 官方的 c 驱动也只提供了阻塞方式!
- 那只好寻求第三方的驱动,我们选择了 Drizzle 这个驱动,并整合进来
成为 ngx_drizzle 模块
1 2 3 4 5 6 7 8 | upstream my_mysql_backend {
drizzle_server 127.0.0.1:3306 dbname=test
password=some_pass user=monty
protocol=mysql;
# a connection pool that can cache up to
# 200 mysql TCP connections
drizzle_keepalive max=200 overflow=reject;
}
|
- 我们这样简单配置:
- 通过 drizzle_server 配置连接口令和协议,因为模块可以连接 MySQL 和 drizzle 两种数据源,所以,要声明协议模式
- 使用 drizzle_keepalive 建立一个连接池,限定上限为200,当超过连接限制时就 reject,相当对数据库的简单保护
- 然后这样定义一个 cat 接口
1 2 3 4 5 6 7 8 9 | location ~ '^/cat/(.*)' {
set $name $1;
set_quote_sql_str $quoted_name $name;
drizzle_query "select *
from cats
where name=$quoted_name" ;
drizzle_pass my_mysql_backend;
rds_json on;
}
|
- cat 之后是这猫的名字,使用 set 获得,这是 nginx 本身的功能
- 然后使用 set_quote_sql_str 对查询语句进行转义,以防止SQL注入攻击
- 通过 drizzle_query 组合成查询語句
- drizzle_pass 来完成对后端数据集群的查询,因为前面的 drizzle_server·可聲明一组 MySQL服务器
- 甚至于,我们为查询返回的結果集,定制了一种格式,叫 rds_json
- 这种格式是面向各种关系型数据库的
- 我们针对这种格式,开发了一系列过滤器可以自由输出 csd或是json格式
- 这样,几乎所有报表接口,都通过这种方式实现的
- taobao 直通车就使用了 csd 格式,因为他们是将这当成中间件来使用的
- 而我们是直接通过 json 以 Ajax 形式对外的
- 这样,通过 curl 访问 cat 接口查詢 Jerry ,就可以获得名叫Jerry 的猫的相关数据
- 这里json 的输出,可以通过一系列方式,进行自由的调整
- 比如说,有的要求每行数据都是 key/value 的格式,有的要求紧凑格式,第一行包含key之后,以后的全部是数据等等,,,
那么 portsgres 访问接口模块名叫:ngx_postgres
- 这是一位波兰的 hacker 在我们的ngx_drizzle 基础上完成的
- 因为它仿造了我们的接口形式
- pg 的官方模块是无法使用的,于是他花了两个月的时间,完成了这个模块
- 去哪儿网,有很多地方就使用了这一模块
- 我们可以看到如何使用 Lua 来调用这个标准模块
因为在 web 开发中,每向上一层,速度会下降一级,但是,功能会丰富很多
- 但是,使用 nginx 模块来完成,速度损失很有限
1 2 3 4 5 | upstream my_pg_backend {
postgres_server 10.62.136.3:5432 dbname=test
user=someone password=123456;
postgres_keepalive max=50 mode=single overflow=ignore;
}
|
- 这里,我们配置 overflow 时 ignore ,忽略,就是説,连接超过限定时,直接进入短连接模式
1 2 3 4 5 6 7 8 9 | location ~ '^/cat/(.*)' {
set $name $1;
set_quote_pgsql_str $quoted_name $name;
postgres_query "select *
from cats
where name=$quoted_name" ;
postgres_pass my_pg_backend;
rds_json on;
}
|
- 这样定义一个 pg 版本的 cat 接口
- 注意,进行SQL 转义时问的是 set_quote_pgsql_str, 因为pg 的SQL转义和其它的不同
然后,去年的时候,我为了好玩,写了个 redis 的模块: ngx_redis2
- 依然是100%非阻塞,去哪儿和天涯也都大量使用了这一模块
1 2 3 4 | upstream my_redis_node {
server 127.0.0.1:6379;
keepalive 1024 single;
}
|
- 同样使用 upstream 定义一个或是多个连接池
- 使用 keepalive 定义并发策略,这种场景中 tcp 在 http 的连接消耗是非常低的
1 2 3 4 5 6 7 | # multiple pipelined queries
location /foo {
set $value 'first' ;
redis2_query set one $value;
redis2_query get one;
redis2_pass my_redis_node;
}
|
- 这里,我使用 redis2_query 定义了两个请求
- 通过流水线形式,一次請求发送了两个命令过去,响应时,就有两个响应,按照顺序返回
ngx_srcache 是个很有趣的通用缓存模块
- 之前为 apache 写过一些模块,其中一个比较有趣的,就是针对mod_cache 模块,写了个 memcached 的模块,就可以通过 memcached 对apache 中任意的响应进行缓存!
- 这模块当初是为 Yahoo! 的搜索业务中,爬虫的抽取系統进行設計的
- 当然我就发现,apache 里对 memcached 进行阻塞访问时,有点虚焦? 随着并发数增加,响应速度极速下降
- 所以,在nginx 时,就不会有这种问题,保证所有处理都是非阻塞的!包括访问 memcached
- 所以,我们可以在配置文件中自行决定使用什么后端来存储缓存
1 2 3 4 5 6 | location /api {
set $key "$uri?$args" ;
srcache_fetch GET /memc key=$key;
srcache_store PUT /memc key=$key&exptime=3600;
# proxy_pass/drizzle_pass/postgres_pass/etc
}
|
- 这里我们定义两种调用,所謂 fetch 是在 apache 中一种模板,c級别的调用但是,技法和 http 的 get 一樣
- 这样声明的 location,我们可以同时即对外提供调用,也可以对配置内部其它 location 进行调用!
1 2 3 4 5 6 7 | location /memc {
internal;
set_unescape_uri $memc_key $arg_key;
set $memc_exptime $arg_exptime;
set_hashed_upstream $backend my_memc_cluster $memc_key;
memc_pass $backend;
}
|
- 这样,其实就是在收到請求时,实际调用了 /memc 接口,访问后端缓存
- 收到結果后,再使用 srcache_store 接口整理put 回请求的入口 location, 設置相应的格式
- 而 /memc 接口通过 internal 标记,成为仅仅对内服务的接口
- 后面我们通过一系列指令,从 url 参数 ;-)
- 即使是内部调用,依然是个标准的 http 請求界面
- 然后使用 set_hashed_upstream 对 memcached 的集群.进行基于鍵的模的 hash 将結果放到 $backend
- 最后使用 memc_pass 完成对集群的查询
- 这里的 my_memc_cluster 是怎么定义的呢?
1 2 3 4 5 6 7 | upstream memc1 {
server 10.32.126.3:11211;
}
upstream memc2 {
server 10.32.126.4:11211;
}
upstream_list my_memc_cluster memc1 memc2;
|
- 使用 upstream 定义两个服务,使用upstream_list 声明为一个集群
- 这里其实也有限制的:
- 在我们动态追加主机时
- 我们要重新生成配置文件,然后使用 touch 命令通知 nginx 重新加载
- 而这一限制,我们将看到,在基于 Lua 的实现中会不存在 ;-)
前面我们看到,经过简单的配置,我们就可以获得一系列强大的 api 服务;
<<< 29:51
实际使用中,还有一个重要的需求就是字符串编码:
- 因为,有的业务是基于 gbk的,有的又是 utf-8 的
- 一般我们可以在数据库层面进行处理
- 但是,对于一些功能弱些的产品,比如说,memcache/redis 等,就没办法了
- 所以,我们完成了自己的动态编码转换模块:
ngx_iconv
- 不管大家在访问 MySQL 时,使用的什么途径,比如习惯的反向代理什么的
- 都可以通过 iconv_filter 对响应体进行编码转换!
- 而且是流式的转换,也就是說,不需要 buffer,来一点数据就立即完成转换
1 2 3 4 | location /api {
# drizzle_pass/postgres_pass/etc
iconv_filter from=UTF-8 to=GBK;
}
|
- 以上这是从 utf-8 到 gbk 的转换
<<< 30:54
后面我们化了很大力气将 Lua 嵌入到了裏面:
- 这样使得,可以实现任意复杂的业务了
1 2 3 4 5 6 | # nginx.conf
location = /hello {
content_by_lua '
ngx.say("Hello World")
' ;
}
|
- 这样我们就完成了一个 hallo world
- ngx.say 是 lua 显露給模块的接口
- 另外当然也可以调用外部脚本
- 如同我们写php 应用时,习惯将业务脚本单独组织在 .php 文件中一样
1 2 3 4 | # nginx.conf
location = /hello {
content_by_lua_file conf/hello.lua;
}
|
- 通过 content_by_lua_file 调用外部文件:
- 这里的脚本可以任意复杂,也可以使用Lua 自己的库
早先,我们非常依赖,ngninx 的子请求,来复用 nginx 的请求模块:
- 比如说,我们一个模块,需要同时访问 memcached/mysql/pg 等許多后端
- 这时,怎么办? 这么来:
1 2 3 4 5 6 7 8 9 10 11 12 13 | location = /memc {
internal;
memc_pass ...;
}
location = /api {
content_by_lua '
local resp = ngx.location.capture("/memc")
if resp.status ~= 200 then
ngx.exit(500)
end
ngx.say(resp.body)
' ;
}
|
- 先在 /memc 中建立到 memcache 的连接,并声明为内部接口
- 然后,在 /api 中使用 ngx.location.capture 发起一个 location 請求
- 就象发起一个正当的 http 请求一样,请求它,但是,其实没有http的开销,因为,这是c 级别的内部调用!
- 而且是个异步调用,虽然我们是以同步的方式来写的
- 然后我们可以检验响应是否 200,否则访问 500
- 最后就可以将响应体输出出来
这里为什么可以同步的写?
- 写过 javascript 前端程序的朋友,应该知道要实现异步效果,我们很多时候,要使用回调
- 而在 Lua 中我们可以这么来,因为 Lua 支持协程,即,concurrent
- 这样,我们可以在一个 Lua 线程中分割出多个Lua 用户级的逻辑线程
- 这种伪线程,可以实现比操作系统高的多的多的并发能力,因为系统开销非常的小
- 近年有一些技术,也都支持了 concurrent 的技术,可以象http 请求顺序一样,顺着写
- 不用象js 程序员那些纠结倒着写,在需要顺序操作时,又必须借重一些技法,而应用技法的代码,又实在难看,无法习惯
所以,我们当初选择 Lua 一个很重要的原因就是支持 协程
- 这里我们假定,同时要访问多个数据源
- 而且,查询是没有依赖关系的,那我们就可以同时发出请求
- 这样我总的延时, 是我所有请求中最慢的一个所用时间,而不是原先的所有请求用时的叠加!
- 这种方式,就是用并发换取了响应时间
1 2 3 4 5 6 7 8 9 | location = /api {
content_by_lua '
local res1, res2, res3 =
ngx.location.capture_multi{
{"/memc"}, {"/mysql"}, {"/postgres"}
}
ngx.say(res1.body, res2.body, res3.body)
' ;
}
|
- 这里我们就同时发出了3个请求
- 同时到 memcached/mysql/pg
- 然后全新响应后,将結果放到 res1/2/3 三个变量中返回
所以,这种模型里,实现并发访问也是很方便的 ;-)
<<< 35:20
这是我去年,花力气完成的 nginx 共享内存字典模块: lua_shared_dict
- 因为 nginx 是多 worker 模型,可以有多个进程
- 但是,其实 workder 数量和并发无关,这不同于 apache
- nginx 多worker 的目的是将 cpu 跑满,因为它是单进程的嘛
- nginx 实际只跑了操作系统的一个线程,所以,多核主机中,如果有8核心,我们一般就起8个 worker 的
- 如果业务有硬盘 I/O 的操作时,我们一般会起比核数略多的 worker 数
- 因为在 linux 中,磁盘很难有非阻塞的操作
- 虽然有什么 aio 的模型,但是有很多其它问题
- 所以,本质上 nginx 多 worker 是为了跑满 cpu
- 那么,一但多进程了,就存在满满的共存问题
- 比如説,我们想在多个进程间共存配置/业务数据
- 所以,基于共存内存来作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | lua_shared_dict dogs 10m;
server {
location = /set {
content_by_lua '
local dogs = ngx.shared.dogs
dogs:set("Tom", ngx.var.arg_n)
ngx.say("OK")
'
}
location = /get {
content_by_lua '
local dogs = ngx.shared.dogs
ngx.say("Tom: ", dogs.get("Tom"))
' ;
}
|
- 这有个例子:
- 首先,使用 lua_shared_dict 分配一 10M 的空间
- 然后,使用 OOP 方式,来定义两个接口:一个 /set 一个/get
- 然后,不论哪个 worker 具体调用哪个操作
- 但是結果,是終保存一致的
- 使用 curl 先set 一下,再 get 就变成了 59,因为内部进行了自增
- 共存的实现是通过紅黑树+自旋鎖来达成的:
- 紅黑树的查找类似 hash 表查找的一种算法
- 为保持读写的数据一致性,使用 自旋鎖来保证
- 所以,当并发增大或是更新量增大时, 自旋鎖可能有问题,未来我们准备进一步修改成报灰的模型
- 其实,共享内存的方式,在鎖开销非常小时,效率是非常高的,在腾讯单机并发跑到20万都是小意思;
另外,在 Lua 中,我们需要对大数据量的一种非缓存的输出:
- 因为,在很多 web 框架中或多或少都有缓存,有的甚至使用了全缓存
- 那么,当你输出体积很大的数据时,就很易囧掉
- 而,在 Lua 中,我们就很容易控制这点
1 2 3 4 5 6 7 8 | ngx.say( "big data chunk" )
ngx.flush( true )
ngx.say( "another big data chunk" )
ngx.flush( true )
|
- 比如,这里我们先 ngx.say ,异步的输出一个数据
- 这段数据不一定刷得出去,如果网卡没来得及输出这投数据的话,这会在 nginx 的进程中缓存
- 如果,我想等待数据输出后,再继续,就使用 ngx.flush ,这时,只有数据真正刷到系统的缓冲区后,才返回
- 这样保证我们 nginx 的缓存是非低的,然后我们再处理下一个数据段
- 如此就实现了流式的大数据输出
这样,有时网络很慢,而数据量又大,最好的方式就是:
- 既然你发的慢,那我也收的慢: 你一点点发,我就一点点收
- 这样我们就可以使用很少的资源,来支持很多大数据量的慢连接用户
然而,还有些慢连接就是恶意攻击:
- 我可以生成很多 http 连接,接进来后,慢的发送,甚至就不发送,来拖死你的应用
- 这种情况中,你一不注意,服务分配给太多資源的话,整个系统就很容易被拖垮
所以,去年年底,今年年初,我下决心,完成了一个 同步非阻塞的 socket 接口:
<<< 40:50
这样,我就不用通过 nginx 的上游模块来访问http 请求:
- 我们就可以让 Lua 直接通过 http,或是 unix socket 协议,访问任意后端服务
1 2 3 4 5 6 7 | local sock = ngx.socket.tcp()
sock :settimeout ( 1000 ) -- one second
local ok, err = sock :connect ( "127.0.0.1" , 11211 )
if not ok then
ngx.say( "failed to connect: " , err)
return
end
|
- 象这样,建立 socket 端口,并可以设定超时
- 我们就可以进行非阻塞的访问控制,当超时时,nginx 就可以自动挂起,切入其它协程进行处理
- 如果所有连接都不活跃,我也可以等待系统的 epoll 调用了
就不用傻傻的完全呆在那儿了
1 2 3 4 5 6 7 8 9 10 11 12 13 | local bytes, err = sock :send ( "flush_all\r\n" )
if not bytes then
ngx.say( "failed to send query: " , err)
return
end
local line, err = sock :receive ()
if not line then
ngx.say( "failed to receive a line: " , err)
return
end
ngx.say( "result: " , line)
|
- 或是使用 sock:send 直接返回,就可以继续其它请求了
- 使用 receive 来接收查询的返回,读失败有失败处理,成功就打印出来
一切都是自然顺序
1 2 3 4 5 6 7 | local ok, err = sock :setkeepalive ( 60000 , 500 )
if not ok then
ngx.say( "failed to put the connection into pool "
.. "with pool capacity 500 "
.. "and maximal idle time 60 sec" )
return
end
|
- 这是连接池的调用
- 通过 sock:setkeepalive , Lua 模块,就会将当前连接,放入另一连接池中以供其它請求复用
- 也就是說,如果其它請求,請求到同一个url 时, nginx 会直接交給它原先的连接,而省去了开新连接的消耗
- keepalive 的参数比较少:
- 头一个是,最大空闲时间,即,一个连接放在连接池里没有任何人来使用的最大时间
- 这里是60秒,因为维持一连接的代价还是很昂贵的,如果一分钟了也没有人来用,我就主动关闭你节省资源
- 对于负载比较大的应用,这样可以减少浪费
- 第二个参数是,最大连接数,
- 这里是500,如果连接数超过限制,就自动进入转移连接的模式
Unix 域套接字 是 Linux/Unix 系统独特的进程接口
- 虽然不走 http 协议,但是调用形式和 tcp 的 socket 完全类似
1 2 3 4 5 6 | local sock = ngx.socket.tcp()
local ok, err = sock :connect ( "/tmp/some.sock" )
if not ok then
ngx.say( "failed to connect to /tmp/some.sock: " , err)
return
end
|
- 一樣通过 ngx.socket.tcp 来建立连接
- 然后,使用 sock:connect 来指定一个特殊文件,接入套接字
- 就可以进行各种日常的操作了
这个模块是基于 concurrent 的:
- 写是顺序写,但是执行是非阻塞的!
这点非常重要!
- 协程技术诞生也有些年头了,
- 但是,至今 99.9% 的 web 应用依然是阻塞式的
- 因为早年,基于阻塞的应用开发太习惯了
- 而基于异步的开发,对于工程师的思維能力要求太高,这也是为什么 node.js 工程师在开发时的主要痛苦
- 因为,要求改变思維方式来考虑问题,我们的程序员多是 php 的,要求他们改变思维是很痛苦的
所以,不仅仅是为了推广我们的平台
- 更是为了兼容工程师的阻塞式思維,同时又可以利用协程来提高系统性能,达到单机上万的响应能力
- 我们引入了 Lua 的协程,并称之为:
"cosocket"
- 即,concurrent based socket
- 而一位资深的 python 粉丝告诉我,python也有优秀的协程库:
- 是基于 greenlet 的 Gevent
- 当然,类似我们的系統,都是可以支撑非常高并发的响应
但是,我们当初选择 Lua 还有个很重要的原因是:
- cpu 的执行效率
- 当你的并发模式,已经是极致的时候
- cpu 很容易成为瓶颈!
一般情况下是 带宽首先不够了,然后 cpu 被跑满
- 而在 apache 模型中,反而是内存首先不足
- 经常是24个进程,swap 8G/24G 不断的增长,卡住什么也玩不了了
- 而cpu 光在那儿进行上下文切换,没有作什么有意义的事儿
即,所謂内耗
当我们将应用从 I/O 模型解放后,拼的都是 CPU:
- 因为,内存一般消耗都不太大
- 我们经常在 256M 内存的虚拟机,或是64M 内存的嵌入式设备中跑生产服务
内存,真心不应该是问题所在,,,
但是,要进行計算时就一定要快!
- 而 Lua 近年发展编译器到什么地步?
- 有种编译器,可以运行时动态生成机器码
- 在我们的测试中,高过了末启用优化的 gpc
- 而启用优化的 gpc ,消耗资源又高过 Lua
所以, Lua 的性能没有问题
- 然后我们实际,按照 ruby 社区的説法,就是直接基于Lua 扩展出了一种专用小語言
- 业务团队实际并没有直接使用 Lua 来写,而是使用我们为业务专门定制的一种专用脚本(DSL)
- 所以,代码量非常的少
而且,我们的定制小語言,是强类型的:
- 强类型語言有很多好处
- 而且,可以在小語言中,定义对业务領域的高层次約束
- 你就可以很方便的查找出业务工程师常范的错误,转化成語言特性包含到约束中,在编译器中实现!
- 最后编译成包含优化的 Lua 代码,让它跑的象飞一样!
而且! 哪天,我高兴了,也可以让它生成 C 代码让它跑到极致!
- 这样,业务不用改一行代码,但是,系统效能可以提高几倍
- 等等,这些都是可以实现的,,,
要,实现这些,要求我们的基础必须非常非常的高效,同时又非常非常小巧!
- 这样我们才能在上面搭上层建筑
- 即,所謂的: "勿在浮沙筑高台"!
- 在这一过程中,我们也吃过很多苦,,,好在有 nginx ...
再有,我们发现 socket 模型,一样可以用来读取下游,即客户端请求数据!
- 当请求体很大,比如说,上传一个很大的文件时
- 也需要异步处理 ,就省的我操心了
- 所以,我就对下游請求,包装了一个只读的 socket,可以对請求数据进行流式读取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | local sock, err = ngx.req.socket()
if not sock then
ngx.say( "failed to get request socket: " , err)
return
end
sock :settimeout ( 10000 ) -- 10 sec timeout
while true do
local chunk, err = sock :receive ( 4096 )
if not chunk then
if err == "closed" then
break
end
ngx.say( "faile to read: " , err)
return
end
process_chunk(chunk)
end
|
- 这样,建立一个下游 socket 后,以 4096 字节为一个块(trunk)进行读取
- 然后检查是否结束,即使没有结束,我也可以一块块的进行处理
- 比如,读一块就写到硬盘上,或是写到远程的一个 tcp 连接,这连接也是非阻塞的!
- 象这样,我这层就非常非常高效!
进行各种高层次的实现就非常方便了
- 以前我用几年时间才能实现纯 Lua 的 MySQL 的连接模块
- 现在用几百行 Lua 脚本就实现了: lua-resty-mysql
- 而且是非常完备的实现
- 支持多結果/存储过程等等高級功能
- 而且性能非常接近纯 C 写的模块,我评测下来,也就差 10~20% 的响应
- 如果未来,我用C 改写其中计算密集型的处理模块,那性能可以进一步大幅度提升!
lua-resty-memcached 也就500多行就搞掂了!
- 是完整的 memcached 协议的支持
所以,用这种技术,可以很方便的实现公司里固定的或是全新的后端服务;
redis协议本身設計的非常巧妙,虽然命令多,但是底层传输协议非常简洁
- 所以,我只用 200 多行,就实现了:lua-resty-redis
后面两个模块都比较粗糙,仅仅封装了传输协议,所以,执行效率,高于它们官方c 实现的等价物 ;-)
lua-resty-upload 就是提及的大文件上传模块
- 不过,这模块写的比较粗糙
- api 暴露的不够 优美,,,,
QA:
- 将 Lua 当成什么来用? 直接业务嘛?
- 简单的可以直接来
- 也可以架构更高层的領域脚本,编译成 Lua 来执行
- 不过,最终,都是通过寄生在 nginx 平台上的 Lua 来实际跑
- 那 openresty 主要解决了nginx 的什么问题?是nginx 的缺陷嘛?
- 分两个方面来想:
- 1.作为 nginx 的补充,很多人也是这么用的,比如说负载的接入,简化 F5 的前端配置,访问的逻辑控制,,,
- 2. 直接作为 web 应用的机制,直接实现所有的应用,输出网页,发布 web service,等等
- 和 apache 什么的性能差别主要在哪里?
- 主要是 I/O 模型的本质差异
- nginx + Lua 可以完成数量级上的提升
- 而且,作为应用或是作为 httpd 可以同时胜任双重角色!
- t2t渲染:: 2013-12-13 02:41:34
- 动力源自::txt2tags
是也乎, Ubuntu 和 MBP 不是同种事物吼
- 不过 Ubuntu 作为操作系统,可以安装在几乎任何硬件中
- 但是, OS X 只有在 Apple 硬件上,才真心自在
所以,,,,
出于各种原因, 111216 在澳门专卖店,老婆赞助之下,入手俺第一台个人笔记本:
- MacBook Pro(15吋)
- 2.2 GHz 四核 Intel Core i7
- 8 GB 1333 MHz DDR3(自购4G)
- 500GB 5400-rpm
- Mac OS X Lion 10.7.3 Lion (自动从10.7.2升级的)
而之前使用的是公司配置的 联想 x200商用笔记本,安装的是 Ubunru 10.04.4 LTS(Gutsy Gibbon);
更早先,2006年之前,是Dell 的商务本,安装windows2003服务器版;
虽然作的事儿一直没有怎么变化,但是,日用环境的变迁,令俺对工具箱有着不同的选择.
因为,很早水决心迁移出 M$ 环境的,所以,软件的组合,一直偏向跨平台,FLOSS软件;
倒是入 MAC 完全有点意外,工具的迁移有点小波折,特此,以系列文章形式记要一下;
对比\内容 |
~2006 |
~2011 |
2012~ |
OS |
Windows |
Ubuntu |
MAC |
>>> abt.输入 <<< |
浏览器 |
SwiftFox |
SwiftFox |
FireFox |
资料收集 |
ScrapBook |
ScrapBook |
ScrapBook |
视频回放 |
MPlayer |
MPlayer |
MPlayer |
email |
Thunderbird+Gmail |
Thunderbird+Gmail |
Gmail |
pdf |
FoxitReader |
Document View |
Skim |
chm |
内置 |
CHM Reader(FF插件) |
Enolsoft CHM View| |
漫画阅读 |
ComicsViewer |
Comix |
Simple Comic |
文本阅读 |
ReadBook |
LiteBook2 |
EPUBReader |
音乐播放 |
foobar2000 |
Moc |
Cmus |
图片浏览 |
IrfanView |
Geeqie |
Xee |
笔记 |
Leo |
Zim+Leo |
Notational Velocity+Leo |
辞典 |
星际译王 |
星际译王 |
内置(外挂星际译王词库) |
>>> abt.思考 <<< |
思维导图 |
FreeMind |
XMind |
Xmind |
关系图谱 |
Graphviz |
Graphviz |
Graphviz |
UML |
JUDE |
JUDE |
websequencediagrams.com |
antiRSI |
Workrave |
Workrave |
focus booster |
>>> abt.系统管理 <<< |
虚拟机 |
NULL |
VirtualBox |
VirtualBox |
软件仓库 |
NULL(可悲!) |
apt |
brew |
版本管理 |
CVS+SVN |
SVN+Hg |
Hg+git |
输入法 |
BXM |
SCIM(外挂BXM) |
IMKQIM(外挂BXM) |
终端 |
Putty |
Gnome 终端 |
iTerm 2 |
文件管理 |
Total Commander |
gnome-commder |
muCommander |
CPU分享 |
BINC |
BINC |
BINC |
>>> abt.输出 <<< |
办公 |
OOo |
OOo |
OOo |
幻灯 |
OOo |
S5 |
rst2S5 |
文档 |
t2t/rst |
t2t/rst |
t2t/rst |
在线写作 |
It’s All Text! |
It’s All Text! |
It’s All Text! |
图片管理 |
Picasa |
Picasa |
Picasa |
图形设计 |
Inkscape |
Inkscape |
Inkscape |
图像处理 |
GIMP |
GIMP |
GIMP |
视频处理 |
ffmpeg |
ffmpeg |
ffmpeg |
音频编辑 |
Audacity |
Audacity |
Audacity |
视频编辑 |
- |
Avidemux2 |
Avidemux2 |
系统监察 |
内置(弱!) |
内置+htop |
内置+atMonitor |
中文字体 |
wqy |
wqy |
wqy |
编程字体 |
Courier |
Monaco |
Incosolata |
编程 |
UltraEdit+Leo |
GEdit+Leo |
Sublime Text2 / Emacs +Leo |
IM |
Pidgin+Skype |
Pidgin+Skype |
Aduim+QQ |
可以看到,近7成的软件,根本不用迁移,可以直接使用!-)
- 这就是开源的伟力之一!
- 当然,有几个核心常用软件是有一定挣扎才迁移过来的,,,
接下来,将对其中比较折腾的进行逐一回顾,,,
- 动力源自::txt2tags
- t2t渲染:: 2012-03-19 04:28:55
|