Nginx為什么要造重復的輪子nginScript

jopen 9年前發布 | 10K 次閱讀 nginScript

 

前不久,Nginx發布了一種“代理端”的JavaScript實現 nginScript 。該實現可以提高Nginx的腳本能力,使Nginx配置更簡單、操作更高效,使用戶無需編寫C模塊就可以在Nginx中做更多的事情。目前, nginScript 解析器僅支持 ECMAScript 5 的一個子集,不過后續還會擴展。在對JavaScript求值時,nginScript會使用一個基于寄存器的虛擬機將JavaScript編譯成字節碼然后在Nginx(或Nginx Plus)中運行。

許多人對此都非常好奇,既然已經有了 V8SpiderMonkey 或其它實現,為什么還要實現一個新的JavaScript運行時。 Hacker News 上也出現了大量不同的聲音。比如,網友stanleydrew就認為這個做法很糟糕,因為它可能讓Nginx這個原本很棒的工具走上膨脹之路。對此,網友n42表示:

任何你不想用的特性都是膨脹,但用到的時候就必要了。

而網友eknkc則認為:

它是一個很好的補充。我在高業務量的服務器使用了Varnish,一個原因就是它有“可視化組件庫”,這是一種類JavaScript的語言,可以用它來定義請求處理邏輯。nginx將為熟悉它的人提供許多配置選項。

針對這些疑惑和爭論,Nginx近日專門 撰文 解釋了他們為什么要創建自己的JavaScript實現。

Nginx有一些獨特的需求,他們希望nginScript代碼片段可以在Nginx處理請求時運行,以此擴展Nginx處理請求和響應的能力。但是,他們無意創建一個像Node.js那樣的持久化的JavaScript應用程序運行時環境。

然而,現有的JavaScript運行時都是針對Web瀏覽器而設計的,依賴于垃圾收集,很難控制JavaScript VM的資源使用。如果內存溢出,它們就會異常退出。這在瀏覽器端尚可接受,但在服務器端是不可容忍的。他們希望nginScript能夠提供簡潔且可以快速執行的規則,而不是對JavaScript的完整支持。而且,Nginx已經有一個經過充分優化的、事件驅動的架構,所以他們不希望受垃圾收集所帶來的性能不可預見性所影響。

出于上述種種考慮,他們實現了一種非常簡單但與其需求相匹配的JavaScript運行時:

  • 架構 ——單線程、字節碼執行是為了實現快速初始化和處理。由于每個請求會分配一個單獨的虛擬機,所以不需要垃圾收集。虛擬機沒有復雜的狀態或輔助程序初始化,啟動速度非常快。
  • 輔助函數 ——內置操作在Nginx本地實現,用戶可以將nginScript視為一種通過編程驅動Nginx本地操作的方式。
  • 預占 ——Nginx事件驅動模型負責調度單個nginScript VM的執行。當nginScript規則執行阻塞操作時,Nginx會暫停那個虛擬機的執行,待事件完成后再重新調度。這意味著,用戶可以采用一種簡單線性的方式編寫規則,Nginx會調度它們,而且不會有內部阻塞。

截止目前,nginScript尚處于早期開發階段,當前版本為預覽版,其團隊一直致力于功能的構建,開發主要是圍繞完成核心的語言實現以及實現許多內置的JavaScript對象(如Date、Math等)進行。因此,談論nginScript的性能還為時過早。但測試表明,nginScript VM的性能同其它解釋型語言(PHP、Ruby等)類似,但不如JIT實現快。同時,nginScript團隊還專注于nginScript VM與Nginx的整合,比如,如何在Nginx配置中引用nginScript規則,nginScript如何訪問和控制Nginx內部構件。對于長時間運行的腳本,他們可能還會引入垃圾收集。nginScript的完整路線圖尚未形成,讀者可以通過 郵件列表 分享自己的想法。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!