在上周的nginx.conf 2015用户大会上,咱们发布了全新的JavaScript引擎nginscript的预览版。历史上,JavaScript语言已经应用在许多方面,首先是做为客户端脚本,而后又被用于服务器后台开发。至于nginscript,咱们要介绍的是第一种"代理端"的使用状况,用于知足咱们在会上提出的一系列独特的要求。消息公布后,许多人对咱们决定要实现一个新的JavaScript引擎,而不是使用V8,SpiderMonkey,或其余的已有引擎而感到好奇,因此这篇文章用于解释咱们为何这么作。 nginx
咱们正在作什么?
咱们正在编写本身的JavaScript引擎,称为nginscript。nginscript目前支持解析器ECMAScript 5的一个子集(咱们将在将来进行扩展),采用基于寄存器的虚拟机(VM),运行时将把代码编译成字节码,同时支持 nginx和nginx plus。在目前的预览阶段,nginx能够编译JavaScript代码并用在两个场景:产生nginx的配置,或者在nginx执行阶段生成内容。将来的版本将支持更多的使用场景。 编程
为何要建立本身的JavaScript运行时?
Nginx有一些特别的需求致使咱们要去创造属于咱们本身的引擎。为了扩展请求应的处理流程,咱们须要nginx在处理一个请求时能够运行nginscript片断。咱们不寻求创造一个后端JavaScript应用程序执行环境–由于Node.js已经作的很好。目前的JavaScript引擎被设计为运行在一个Web浏览器中,他们依靠垃圾收集器的管理内存。若是耗尽内存,JavaScript VM会异常退出;这种行为对于浏览器是能够容忍的。可是对于持有数千个链接的服务器却不行,总的来讲,专门为浏览器设计的引擎不适合服务器,包括v8,SpiderMonkey它们没有供简单的方法来控制执行(即预防奔溃和恢复虚拟机的机制),同时支持JIT的能力有限。咱们但愿能有一种引擎将nginscript的脚本简单并快速的执行。同时,由此产生的状态被保存在虚拟机外部。由于脚本简单,因此全面支持JavaScript语言没有必要。同时,nginx已经拥有很是精细的事件驱动架构,咱们不想nginx的性能受到垃圾收器的影响。
后端
相反,咱们正在建立一个很是简单的引擎以知足咱们的要求:
架构 – 使用单线程,字节码的执行部分将会很是快速。为每一个请求分配虚拟机。由于没有复杂的状态须要初始化,这种简单的虚拟机能够快速启动,同时使用简单的缓存池管理内存。这种内存管理方案,无需跟踪和释放单个对象或使用垃圾回收器,能够大大提升性能。
辅助功能 –Nginx实现了许多内置操做。例如,复杂的数学运算,哈希函数,当nginscript与nginx结合时,这些操做也会是本地的。你可使用nginscript以编程的方式来驱动nginx的本地方法。
和nginx配合 – nginx的事件驱动模型能够用于调度nginscript VMS的执行。当一个nginscript正在执行阻塞操做(如读取网络数据),nginx能够暂停该VM的执行,当该VM的事件完成后再恢复。这意味着你能够在编写一个简单的脚本, nginx会调度脚本不形成阻塞。最后,用咱们本身的引擎,咱们能够保证API统一,同时确保咱们的VM和nginx支持的平台范围一致。 浏览器
关于性能
如今谈论性能还过早,目前咱们正在专一于功能的实现。nginscript编译为内部的字节码而且运行在一个基于寄存器的虚拟机;这种机制使得它和其余解释性语言(PHP,Ruby,等等)性能至关。因此为了提升性能,咱们想在一些地方增长JIT编译,但这可能会限制支持的平台范围。nginscript只是被设计用来执行一些简单的内部脚本,咱们不想让它来执行计算密集型操做,由于nginx内部基于C语言的模块已经解决这个问题。
缓存
将来
nginscript目前处于其发展的早期阶段,咱们称当前版本是"预览"版。咱们将重点放在核心语言的实现(如增长闭包),并实施许多内置的JavaScript对象(日期,数学,等等)。
咱们还将重点放在如何整合资源,好比nginx的配置如何集成脚本,在哪些方面nginscript能够访问和控制nginx内部?如何在脚本之间共享数据,以及跨集群?用户如何调试nginscript脚本?
对于长时间运行的脚本(如WebSocket),咱们甚至能够添加一个垃圾收集器,但那是在将来好久之后。
对于nginscript将来如何发展目前尚未定论。咱们但愿获得您的反馈。请在咱们的邮件列表中分享您的想法和看法,咱们将共同开发这个功能。谢谢你。 服务器