NodeParty杭州站会议纪实:Jscex,SeaJS与MyFOX

​CNodeJS.ORG是由淘宝工程师志愿发起的关注Node.js技术的原创社区,致力于Node.js技术的研究和推广。5月14日CNodeJS.ORG在浙江大学玉泉校区开展了第二次NodeParty技术交流活动,来自盛大和淘宝的工程师分享了他们在Node.js使用中的经验,思考及体会。主要话题涉及异步编程方式,模块管理与分布式的数据统计中间件等等。

第一场演讲是由盛大创新院的老赵带来的Jscex项目介绍。Node.js的一大特点便是“无阻塞”编程,正是这种纯异步的的特质让它可以应对互联网服务对性能和伸缩性的要求。但老赵认为,程序员早已习惯于使用线性的方式表达一段算法,但异步编程却迫使我们使用大量回调函数,最终代码逻辑会被拆分地支离破碎。这样我们无法使用while/for/do来执行循环,使用if…else进行逻辑判断,或是使用try…catch…finally来处理异常,甚至简单的异步操作顺序执行也要用回调函数串联起来。因此,与传统编程相比,异步编程无疑会显著提高代码编写的复杂度。老赵在演讲里演示了一段冒泡排序的简单算法,在将其异步化(编写为动画)之后代码长度增加了不少,他同时表示,这里的问题并不仅仅是代码长度增加了,更关键的是代码的语义丢失严重。例如,在异步化之后几乎没有人能够轻易看出这是一段冒泡排序算法。

Jscex便是为了解决这个问题而诞生的。从某种程度上说,Jscex是F#中“计算表达式”特性的JavaScript移植,不过严格说来是受到该特性的启发,而针对JavaScript设计而实现。老赵表示,由于JavaScript中存在break、continue或是return这类中断执行流的语言特性,因此在JavaScript中实现“计算表达式”相对来说可能更复杂一些。Jscex的核心是一个使用JavaScript编写的JavaScript编译器,它将一段普通的,线性的JavaScript函数编译为monadic形式,继而可以异步地执行。老赵提到,Jscex的首要原则便是为JavaScript程序员保留一切习惯。Jscex不是一门新语言,它支持几乎完整的JavaScript语法特性及语义,包括编程体验等方面可谓没有丝毫改变。Jscex的JIT编译器会在运行时获取一段函数的源代码(通过其toString方法),解析成抽象语法树,再生成新的代码,因此它可以直接运行在所有支持ECMAScript 3的引擎上,包括Web页面,浏览器插件以及Node.js等等。使用Jscex后,程序员完全是以同步的方式编写异步代码。此外,Jscex也提供了AOT编译器,可以在运行时之前编译代码。AOT编译后后的代码可以独立于编译器脚本,十分适合生产环境上发布使用。

在会上老赵还演示了Jscex的一些使用方式,高级模式,还有它是如何解决基于事件的异步模型中的一些限制,性能分析,调试支持等等。Jscex基于BSD开源协议发布,在它的Github页面上有更为详细的说明。此外,Jscex在SNDACode站点上也有与英文内容保持同步的中文说明。

第二场演讲由来自淘宝的前端工程师玉伯介绍他创建的SeaJS项目。在项目开始,他展示了苹果主页上的HTML代码,其中引入了9个零碎的JavaScript脚本文件,导致在YSlow里的评分很低。玉伯表示这种做法是十分不可取的,严重违反前端开发的优秀实践。接着他又展示了Yahoo在这方面的处理方式。Yahoo页面上使用了大量的JavaScript模块,在服务器端合并输出,方式不那么优雅,复杂度也比较高。玉伯认为,Node.js中的模块管理方式及require引入机制让他觉得十分惊艳。Node.js使用CommonJS Module 1.0规范,每个JavaScript文件便是一个模块,每个模块中可以引入其他模块,并通过exports来输出需要对外暴露的成员。

不过玉伯同时提到,V8引擎直接提供了相关接口,因此Node.js可以轻易让一个JavaScript文件在某个特定的上下文里执行,从而不会污染到全局,但是在浏览器环境中几乎做不到这一点。对于在浏览器中使用的模块加载器等方面,社区中也有过一些努力(例如RequireJS),但实际使用中还是过于复杂。假如再同时考虑到脚本下载的阻塞,跨域问题,浏览器兼容性,与CSS结合等方面,这方面的问题几乎找不到完美的解决方案。因此业界也出现了一些思考,例如“是否一定要遵循CommonJS规范”等等。

玉伯的SeaJS也是一个模块加载器,它要求每个模块在编写时遵循一个简单的规范,这样便可以在页面中使用require引入该模块。绝大部分常用的类库/框架(例如jQuery,MooTools,YUI,Backbone.js等等)都可以通过简单的修改成为支持SeaJS加载的模块。SeaJS中也提供了一些Ant脚本来辅助这方面工作。在演示中,玉伯将之前老赵的Jscex项目进行了模块化,还“尝试”着优化了苹果的主页。他表示,SeaJS模块同样可以在Node.js里运行,做到“编写一次、到处执行”的效果。在演讲的问答环节中,听众提出了有关脚本依赖,重复加载、重复执行方面的问题,玉伯针对这些问题一一作了解答。

第三场演讲则是淘宝的朋春讲解的一个Node.js在淘宝中的使用案例:MyFOX。MyFOX是一个数据处理中间件,负责从一个MySQL集群中提取数据,计算,并输出统计结果。用户提交一段SQL语句,MyFOX根据该SQL命令的语义,生成各个数据库分片所需要执行的查询语句,并发送至各个分片,再将结果进行汇总和计算。MyFOX的特点是CPU密集,无文件IO,并只处理只读数据。起初MyFOX使用PHP编写,但遇到许多问题。例如PHP是单线程的,MySQL又需要阻塞查询,因此很难并发请求数据,后来的解决方案是使用nginx和dirzzle,并基于HTTP协议实现接口,并通过curl_multi_get命令进行请求。不过MyFOX项目组最终还是决定使用Node.js来实现MyFOX。

朋春表示,选择Node.js有许多方面的原因,比如考虑了兴趣及社区发展,同时也希望可以提高并发能力,榨干CPU。例如,频繁地打开和关闭连接会让大量端口处于等待状态,当并发数量上去之后,时常会因为端口不够用(处于TIME_WAIT状态)而导致连接失败。之前往往是通过修改系统设置来减少等待时间以绕开这个错误,然而使用连接池便可以很好地解决这个问题。此外,以前MyFOX会在某些缓存失效的情况下出现十分密集的访问压力,使用Node.js便可以共享查询状态,让某些请求“等待片刻”,以便系统重新填充缓存内容。

朋春在演讲中还阐述了MyFOX的结构设计,例如分层的引入,master、worker及router组件的职责等等,对于服务的出错处理及监控重启等方面也提出了一些建议供大家参考。此外,在监控Node.js服务中彭春也观察到一些可能造成的问题,例如内存使用及GC对响应时间的影响,并提出了一些优化的设想。

目前,NodeParty活动已经公开了三场演讲的幻灯片,在老赵博客上也提供了第一场演讲的中英文幻灯片。

你可能感兴趣的:(NodeParty杭州站会议纪实:Jscex,SeaJS与MyFOX)