« January 2011 | Main | March 2011 »

February 25, 2011

ZeroMQ 的模式

在需要并行化处理数据的时候,采用消息队列通讯的方式来协作,比采用共享状态的方式要好的多。Erlang ,Go 都使用这一手段来让并行任务之间协同工作。

最近读完了 ZeroMQGuide。写的很不错。前几年一直有做类似的工作,但是自己总结的不好。而 ZeroMQ 把消息通讯方面的模式总结的很不错。

ZeroMQ 并不是一个对 socket 的封装,不能用它去实现已有的网络协议。它有自己的模式,不同于更底层的点对点通讯模式。它有比 tcp 协议更高一级的协议。(当然 ZeroMQ 不一定基于 TCP 协议,它也可以用于进程间和进程内通讯。)它改变了通讯都基于一对一的连接这个假设。

ZeroMQ 把通讯的需求看成四类。其中一类是一对一结对通讯,用来支持传统的 TCP socket 模型,但并不推荐使用。常用的通讯模式只有三类。

  1. 请求回应模型。由请求端发起请求,并等待回应端回应请求。从请求端来看,一定是一对对收发配对的;反之,在回应端一定是发收对。请求端和回应端都可以是 1:N 的模型。通常把 1 认为是 server ,N 认为是 Client 。ZeroMQ 可以很好的支持路由功能(实现路由功能的组件叫作 Device),把 1:N 扩展为 N:M (只需要加入若干路由节点)。从这个模型看,更底层的端点地址是对上层隐藏的。每个请求都隐含有回应地址,而应用则不关心它。

  2. 发布订阅模型。这个模型里,发布端是单向只发送数据的,且不关心是否把全部的信息都发送给订阅端。如果发布端开始发布信息的时候,订阅端尚未连接上来,这些信息直接丢弃。不过一旦订阅端连接上来,中间会保证没有信息丢失。同样,订阅端则只负责接收,而不能反馈。如果发布端和订阅端需要交互(比如要确认订阅者是否已经连接上),则使用额外的 socket 采用请求回应模型满足这个需求。

  3. 管道模型。这个模型里,管道是单向的,从 PUSH 端单向的向 PULL 端单向的推送数据流。

任何分布式,并行的需求,都可以用这三种模型组合起来解决问题。ZeroMQ 只专注和解决了消息通讯这一基本问题,干的非常漂亮。

基于定义好的模型,我们可以看到,api 可以实现的非常简单易用。我们不再需要 bind/listen/accept 来架设服务器,因为这个模型天然是 1:N 而不是 1:1 的,不需要为每个通道保留一个句柄。我们也不必在意 server 是否先启动(bind),而后才能让 client 工作起来(connect)。

这以上模型中,关注的是通讯双方的职责,而不是实现的方式:监听端口还是连接对方端口。对于复杂的多进程协同工作的系统, 不必纠结于进程启动的次序(在我前几年设计的系统中,启动脚本写起来就非常麻烦)。

使用 ZeroMQ 不必在意底层实现是使用短连接还是长连接方式。ZeroMQ 中的 Transient (短暂) 和 Durable (持久) socket 也并非区别于实现层是否保持了 tcp 连接。而是概念上的不同。对于 Durable socket ,其生命期可以长于一个进程的生命期,即使进程退出,再次启动后依旧可以维持继续之前的 socket 。当然,这并不是帮助你挽救你的程序因出错而崩溃的。它只是提出这个模式,让你根据设计需要可以实现。对于 ZeroMQ ,如有需求(若内存有限),甚至把数据传输的 buffer 放到磁盘上。


对于网络游戏,我觉得基于 ZeroMQ 来架构服务器非常合适。对于玩家 Client - Server 部分倒不必使用 ZeroMQ ,而可以写一个前端程序,比如前些年写过的一篇 blog 中提到的连接服务器依然适用。这个连接服务器对内的服务集群则可以用 ZeroMQ 的协议通讯。

February 16, 2011

食堂排队系统

今天晚上 18:00 准点去一楼食堂吃饭,结果队伍排到了门口还打了个圈。花了 20 多分钟才领到口粮,回头一看,队伍并没有减短。看着前后都有同学抱着 PSP 狩猎 MHP3,我有点后悔没把 PSP 带下来了。

从这几天的经历来看,我们公司食堂的处理能力应该是够的。从 17:30 到 18:45 基本能处理完 600 号人的进食问题。也不能完全怪发放食物的带宽不够,经过一个月的观察,这部分可以优化的余地不大。而且我认为优化的意义也不大。

那么怎么才能减少这么多无谓的排队时间呢?粗看可能性不大,但仔细想想,如果把眼界放宽到整个系统办公楼运作系统,应该是有可能的。

在不提高食堂带宽的前提下,如果用户随机抵达,理论上队伍总会排到 200 开外。并不会在某个特定时间点减少(只有等到最后队伍才可能逐步缩短)。但我们其实可以把排队时间挪一部分到食堂外面的。行政部以前分发过通知,安排各个部门错开时间用餐也是这个想法。

今天一边排队,一边跟前后的同学讨论是否有可能利用软件来节约大家的时间。

既然排队无法避免,相同状态下,我们当然可以在办公桌前排,而不用站在食堂里。既然每个人从座位上走到食堂的时间几乎不变(取决于电梯的运转周期),每个人从打卡到拿到食物的时间也几乎是恒定的。那么不需要特别的监控系统,我们就可以直接估算出食堂处理的带宽,并不会有太大波动。

而且每个工作日,总的用餐需求也是稳定的。

只要用一个系统,每天随机给所有同事自动排队,并在时间点通知。当每个人都比较严格的遵守约定,在接到通知的一分钟内步行去食堂。那么当他们都赶上同一部电梯的话,这批人抵达食堂的时间都是已知的。那么,在食堂的队伍理论上可以减少到一部电梯可以承载的人数左右。

这样,每个人都可以在本来需要的排队时间内做一些别的事情了。

今天讨论的时候,有同学提出应该在食堂安装摄像头做一个自反馈,让系统可以更好的自我调节。我认为意义不大,这样加大了系统实现的难度。其实在我们的特定需求下,大部分数据都是可以较为精确的估算的。我们可以允许一定的队伍(实际上也一定有,因为公司的电梯很大,导致食堂瞬间的业务量很大,不可以立刻全部处理掉),这个系统只要能帮助大家把在食堂的排队时间减少到 5 分钟以下就非常完美了。

关于如何避免大家都不遵守系统通知时间的问题,或者是有人拖拖拉拉不在通知时间去吃饭。我们先设想了复杂的打卡机制。后来觉得都没有必要。毕竟才几百人,还是比较好协调的。而且现在的饭卡系统本来就有统计每个工号的实际进餐时间。只需要每个晚上做一个统计,把严重不按照系统通知时间去吃饭的同学名单排出来,估计大家都会很有兴趣的去网站上围观的。

至于通知的问题,用 popo 就好了。

btw. 有同学认为,每天花两次 20 分钟在食堂里排队,也是个聊天交流的好机会。嗯,也有一定道理。

February 15, 2011

新年杂记

这个月由于过年,休假时间比较长,所以没有正经的做一整块事情。由于 douban 啦 twitter 啦神马的用的比较多。有什么一两句话能说的,都感觉不值得写整篇 blog 了。

不过呢,隔一段时间有个小总结还是有用的。都说,学到和经历的东西,能写出来,记忆比较深刻。

  1. 过年在家十多天,一半时间都是在跟同学玩桌游。还是武汉的同学比较给力,可以玩许多长时间的游戏。终于又可以开 TTA 了,比较爽快。RFTG 也玩的很过瘾。还开了大国崛起,两河流域等等平常不太开的游戏。电网也开了好几盘,很是爽快。

  2. 发现 iPAD 几乎可以取代日常的电脑用途。我上几篇 blog 都是在 iPAD 上写的。还有处理 email ,google talk 聊天,上 twitter 等等,iPAD 都够了。只有订机票跑回家里的机器上打开 IE 支付了一下。不过 iPAD 上 ssh client 太贵没买。偶尔需要登陆别的服务器,就用手机勉强也够的。用触摸屏使 VI 好是折磨人,还好是 VI ,如果是 emacs 我估计更崩溃。

  3. 给我爷爷扫墓那天,借了表妹的车用。居然是手动档的,天呐。我快三年没开过手动挡的了。一路堵车,一路熄火。唉,所以说驾校里的东西都是白学的。还是老实开自动挡的好。

  4. 过完年,武汉的家里宽带续费。居然逼人换密码。我已经离开武汉了,只好远程登陆回家里的机器去改网关服务器上的 pppoe 设置。结果出了点问题,被踢了,再也登不上去。最后只好用 vnc 软件连回家里的 windows 机器,指挥老爸从家里内网登上去修改。各种纠结啊。话说,Windows 真是太难用了。

  5. 有同学要从美国回来。让帮忙带了台 DreamPlug 。神机啊。我就不做广告了,有兴趣的同学自己 google 。

  6. 去年买的 Suunto X10 手表居然被我玩死机了,这货居然不在上面做个 Reset 键。害我把东西全拆了再装起来才正常。发现手边的工具极度缺乏,应该常备一些。在网上跟 Sean 同学聊起来,他鼓捣我去买台机床玩,方显 Geek 本色。好吧,其实我也是机械科班毕业的 :D 等我在杭州买了房买了车库再装台机床在车库里做高达玩。

  7. 年前为梦幻做优化的事终于有了点阶段性的结果。在把服务器内存加到 8G 后,(上次搞错了,我们许多机器还是 4G 内存的)终于性能在新代码下有所改善了。关于 fork 的一系列问题,在上个帖子的回复里许多同学有各种质疑其必要性。实际上,那些不必要的 COW 操作,在内存有限的情况下果然极大的影响了最终的性能。主要是超过了物理内存临界值,让 OS 动用了交换区导致的。虽然现在内存卖的跟白菜价一样,但是几百M内存还是能省则省吧,只要方法简洁。经过细调,省出 200M 以上内存还是很容易的。即使内存够了,应该也会有别的正面效果。毕竟可以节约不少的总线带宽。具体测试结果,还需要等几天看数据。

  8. 周爱民同学年前邀请我年后去支付宝做一个 2 小时的教程,介绍一下 Go 语言,就是帮助那些使用单一语言的程序员同学们开拓一下眼界。我打了个草稿,打算这周先在公司内部讲一下,看看效果和时间长度。

  9. 争取在一个月内,把 RFTG 的比赛办起来。

  10. 不知道啥时候 MHP3 能到上位啊。必须找几个同学联机了,一个人死磕也不是个事啊。

February 04, 2011

写在 0x20 岁之前

还有一天,我的人生就进入第三个 0x10 年。

第一个 0x10 年里我无忧无虑。

当我路还走不稳时,我就喜欢拿着彩色笔涂鸦。我妈盼望着我长大能当一名画家。理论上我应该能遗传点我爸这方面的基因的。可惜我不努力,最终辜负了母亲的殷切期望。

在我还小的时候,我坐在老爸的自行车后座上,父亲问,你长大了想做什么?那是我第一次考虑这个问题。我说,做个数学家吧。那时我参加小学生的数学奥赛,成绩还不错。他不是很满意这个答案,说再想想吧,那或许不是你真正的兴趣。我沉默了,好象我不是真的很喜欢数学。或许是因为比其他人学的好一点造成的错觉。

不过我对用机器来解决数学问题很好奇。最初学 basic 时,我无法理解赋值的等号为什么不能用来自动解方程,那是我第一次萌生写程序的念头,却没有正确写出来。后来突然一天开窍了,我爱上计算机这个大玩具。那本是我爸的总多玩具之一的。

不过那也仅仅是我诸多玩具之一。它并不比其它玩具地位更高。小孩子是很难沉浸在同一事物里的。我格外好玩,一切新鲜之事。我更离不开朋友,离不开与人分享的快乐。至于学业,似乎我从未放在心上。不至于太差,也不会特别之好。初中之后,我知道我的朋友们学习比我好,我的成绩就是考不过他们。可我就是难舍玩儿的精力去把成绩提上去。玩,才是一等大事。

唉,到今天,小我 0x10 岁的小表妹都能一本正经的套我爸的话说,我哥他还没玩醒呢。

进入第二个 0x10 年,我开始思考。

我已经学了五六年编程了。除了写程序比朋友们强一些,别的似乎没什么长处。至于强的那么一点,也是花的比别人多这么多时间换来的。如果他们也肯花这么多时间,一定玩的比我好。我这么想。不过,人的生命有限的很,你花在这方面多一点,其他方面就少了。我也不是刻意去学编程,只是喜欢而已。不仅仅是编程,我发现我越来越喜欢搞明白计算机里的一切,那些是那么有条理,弄明白了就把握住了。

我还认识了生命中第一个让我动心的女孩。只是暗恋而已,但那感情很绵长。我不知道该如何表白,只是用各种方式接近她,直到要离开武汉去读大学。我告诉了她,她拒绝了。我想我的确也不优秀,我应该再做的优秀一些,或许她会喜欢我。那时我不懂爱情,或许现在也不懂。我说我可以等,她说不要,那是不可能的。

大学里,我只做了三件事。

一,读书。读了大量编程方面的书。

二,写信,每天给她写信,写我又在想些什么,做些什么,权当在记日记。也给我的各个老朋友写信,我的大学里没有太多人和我交流计算机方面的东西,我便大版的写学习心得给我中学时的玩伴,他们曾和我一起学编程,打游戏。

三,维护我的个人网站,写我学到的点点滴滴,写我明白了什么。通过 email irc icq 和我的网站的读者交流。到了假期,我就五湖四海的去拜会他们。那些网友多是中国早期的游戏行业先驱。我本没打算以游戏为业,可是接触的人都是这个圈子,反过来加强了我为游戏做点什么的信念。

其他,玩玩游戏,打打零工赚点钱什么的只是消遣,就不算正经事了。至于听课读那些专业课程。惭愧,丝毫没有兴趣,居然能让我毕业,真还是一奇迹啊。嗯,我的专业是机械。

把精力放在一处,比如专心于学习实践编程上,绝对是让自己忘记寂寞是何物的最佳方法。这个学习当是无功利心的,仅仅是因为我想知道为什么是这样。满足好奇心是唯一的目的。

从学校里出来,我感觉整个人都是自由的。这种自由感之前只在高考后体验过一次。我在高中里曾经想过不读大学,面对老泪纵横的父亲,我退缩了。读大学时,我想过退学。跟家人小心翼翼的提出,并没有想像中父母该有的怒火,但毕竟还是不被支持的,我自己也没有勇气真的去做。终于拿到学位证,才是最为解脱的一件事。

在这种心境下,我莫名其妙的开始喜欢读一些以前不读的书。如醍醐灌顶般,我发现历史是那么有趣。不仅仅是小时候理解的一系列的人物故事,或是上学时,为应付考试背的枯燥的大事年表。我为之前一直没好好读历史而惋惜那些逝去的时光。同时也读一些简单的哲学以及经济。我发现这个世界上其实任何一门学科都挺有趣的,去读读前人都是怎么一步步的做那些学问尤其有趣。我的书架上就不再只有编程书籍和科普读物了。

还有网友给我发一些邮件讨论美国的政治制度,推荐我读易中天关于美国宪政的文章。我渐渐发现许多政治课上没学明白的东西,有点明白了。独立思考这档子事,是小孩子成年的标志之一。我曾经认为长大遥遥无期,我妈有天突然对我说,你爸跟你谈了次话,发现你长大了。

我到广州生活的第二年,事业一帆风顺。追了多年的女孩从国外回来找到我,说,只要你说让我留下来,我就不再出国了。那晚我流了一晚上眼泪,她也是。因为我发现我的爱情离我远去。我不再想之前感情上受的伤害,我还是念着她的好,只是,有些东西没了就真的没了。然后她就又离开。

9 年之后,我在 google talk 上和她聊起往事。谈我后来的感情生活,讨论爱情和她已相处 9 年的男友。她说,恐怕我是除了她妈妈,每年都一定记得她生日的人。但是一切都是缘。突然间,她说她想明白了,明天就答应她的男友。她曾经是我的心结,而后我又成了她心中的一点无以形容的存在。她说她终于解脱了。我祝福他们。

我去参加了他们的婚礼。

人活着的意义是什么?我不知道下个 0x10 年我能否找到答案。

这个 0x10 年里,我只是放纵着自己,想到什么就做什么,依着自己的道德准则行事。我对世界充满好奇,就尽可能的去学习。我发现自己所学能帮到别人,就乐于去分享,去帮人解决问题。碰巧,爱做的事情还有人把它转换为不菲的收益。我也就心安理得的拿取自己那一份。我觉得我很幸运的逃离了所有经济上的制约,可以不去关心许多同学必须关心的房子,车子,工作等等问题。可以更纯粹的做喜欢做之事。

我不认为这全是因事在人为。所谓谋事在人,成事在天。多年的经历,我不会把自己看的太高,人生不如意十之八九,所以我格外感激珍惜获得的那些。

我很开心,当我回到广州公司大楼,即使已经离开五年,员工换了一茬茬,但无论是在楼道中,还是电梯里,都有熟悉的面孔亲切着打招呼。嘿,云风,好久不见。晚上一起吃饭吧。有如五年前,我拉着一大帮刚从校园里出来的同学们,呼啦啦的一大片,吃遍广州大大小小的馆子。在珠江边的露天酒吧里大口灌着啤酒,玩着天黑请闭眼。

这几年做的不够好。吾友 tdlife peng 同学曾说,做些啥,不在于取得多少成绩,在乎自己在不断积累。是啊,唯有自己学到的知识,明白的道理才真正属于自己。其它的,身外之物而已。

做了几年项目下来有点累。连社交都越来越少。总觉得有责任做好。而我偏偏又是个随心所欲的人。我曾碰上那个我确切感觉到真的爱我的好姑娘,性子也与我相似。吾友杨录同学说,第一眼见她,觉得跟我好相像。我无法确定是否爱她。但我知道辜负了她的感情是我这几年最大的遗憾。我隐隐知道,感情之外的,我在做的事情给了我不少压力。但我内心却并不承认那些会影响到情绪。直到她绝然的离开,甚至带着恨意。我明白我在感情上欠她太多,也没有机会偿还了。她教会了我,再独立坚强的女孩也是需要人哄的。而人之复杂,单靠逻辑和理性去表达只能是一厢情愿。

我希望新的 0x10 年是我人生新的篇章,就像上个 0x10 年,我突然就发现了喜欢的人。不知不觉就找到了适合自己做的事,一直做了下来。我希望接下来的日子能找到真爱,共渡一生。希望可以继续无拘束的以自己的方式理解世界。活的像个孩子,对一切保持好奇心,相信爱情。


写给本文的非程序员读者:程序员通常用 16 进制计数,只有 2 的整数幂的数字才觉得是整的。比如 1 2 4 8 16 32。

0x10 是 C 语言风格的 16 进制数字表示,相当于 16 。0x20 表示 32 。