使用 Rust 來解決 CPU 性能產生的 npm 軟件包註冊瓶頸前端
事實與數據:android
共有超過 836,000 個 JavaScript 包可用
每月使用 npm 下載的軟件包超過三百億
下載來自於超過一千萬個用戶
複製代碼
npm 公司(npm, Inc.)是 npmjs.com 網站和 npm 註冊服務背後的公司。它是全世界最大的軟件註冊中心,天天有高達 13 億的包下載量。除了維護開源軟件包註冊,npm 公司也提供企業級的軟件包註冊產品,並維護着一個用於與註冊信息交互的命令行工具。ios
npm 所面臨的挑戰是對效率和擴展性的要求。若是服務部署後能夠被遺忘(譯註:指服務不須要花精力維護),咱們就節約了寶貴的時間,能夠處理別的問題。npm 員工們也很但願,他們所使用的技術有一個有幫助的社區。Rust 符合這些要求,並且在 npm 目前的技術棧中也有部分使用。git
npm 工程團隊時刻關注着隨着 npm 包指數增加可能致使的性能問題。大多數狀況下 npm 的操做性能受限於網絡,JavaScript 足以支撐實現性能目標。然而,決定用戶是否被容許發佈軟件包的認證服務,是一個受限於 CPU 性能的任務,預計會成爲性能瓶頸。github
Node.js 中使用傳統 JavaScript 實現的這個服務不管如何都須要重寫,因此 npm 團隊藉此契機,考慮在服務降級前從新實現,既使得代碼更現代化,又能提升服務性能。npm
當考慮替代技術時,npm 團隊很快否決了 C,C++和 Java 實現,而密切關注 Go 語言和 Rust 語言。編程
在 npm 工程團隊的考慮中,C 或 C++ 解決方案再也不是一個合理的選擇。「我不相信本身能寫一個 C++ HTTP 應用程序,而後把它發佈到網絡上,」npm 的工程師 Chris Dickinson 解釋說。這些語言須要內存管理方面的專業知識,以免可能致使災難性問題的錯誤。即便是爲了提升性能,npm 公司也沒法容忍安全問題、系統崩潰和內存泄漏的發生。後端
Java 也未被考慮,由於要部署任何程序到生產服務器上,都得帶上 JVM(Java 虛擬機)和相關類庫。這是一系列複雜操做,會產生資源消耗,與 C 或 C++的不安全性同樣難以接受。安全
考慮到這些要求,所選的編程語言應該:bash
所以最後考慮使用的是 Go 語言和 Rust 語言。
爲了評估候選方案,npm 團隊分別使用 Node.js、Go 語言和 Rust 語言重寫了受權服務。
使用 Node.js 重寫的服務被當作基準線,以評估使用 Go 語言和 Rust 語言帶來的變化。如你所料,npm 有不少 JavaScript 專家。使用 Node.js 重寫受權服務大約用了一個小時,性能表現與過去實現的差很少。
使用 Go 語言重寫受權服務用了 2 天。在這個過程當中,npm 團隊對於缺乏依賴管理的解決方案感到失望。npm 公司致力於讓 JavaScript 依賴管理可預測,而且用起來絕不費力,他們期待其餘語言生態也有一樣的世界級依賴管理工具。Go 語言的依賴安裝全球化進程、跨項目版本共享的前景(在他們進行評估時 Go 語言的標準)都不具備吸引力。
當開始用 Rust 語言實現時,他們在依賴管理方面發現了鮮明的對比。「Rust 語言有着絕對使人驚歎的依賴管理,」一位工程師熱情地說,他指出 Rust 的依賴管理策略從 npm 得到了靈感。Rust 語言安裝時附帶的 Cargo 命令行工具與 npm 命令行工具相似:Cargo 分開協調每個項目中的各依賴版本,從而讓搭建每一個項目時所在環境不會影響最終的執行結果。Rust 語言的開發體驗很友好,符合 npm 團隊受到 JavaScript 影響的預期。
Rust 語言有着絕對使人驚歎的依賴管理。
使用 Rust 語言重寫受權服務的時間其實比 JavaScript 版本和 Go 語言版本的都長:大約用了一週來熟悉語言並進行實現。Rust 感受像是一種更難以搞定的編程語言。語言的設計預先加載了不一樣於其餘常見編程語言的內存使用決策,以確保內存安全性。「你能夠寫出一個正確的程序,可是你必須考慮到這個程序的方方面面,」Dickinson 說。然而,當工程師們遇到問題時,Rust 社區友善地回答了問題,頗有幫助。這一點讓 npm 團隊可以用 Rust 語言重寫服務並將其部署到生成環境。
我對 Rust 最大的恭維就是它很「無聊」。
npm 的第一個 Rust 程序在一年半的生產使用中沒有引發任何警報。「我對 Rust 最大的恭維就是它很‘無聊’,」Dickinson 說,「而這是一個很棒的恭維。」部署新的 Rust 服務的過程很簡單,很快他們就忘記了這個 Rust 服務,由於它極少引發運行問題。在 npm 公司,將 JavaScript 服務部署到生產環境的通常經驗是,要對服務的錯誤和過多的資源佔用進行大量監控,從而須要調試和重啓。
npm 稱 Rust 社區是決策過程當中的一個積極因素。他們認爲 Rust 社區頗有價值的一些方面是他們的包容、友好以及作出困難的技術決策的可靠流程。這些方面使 Rust 語言的學習和解決方案的開發更容易,並保證了語言將以健康、可持續的方式繼續提升。
每一個技術決策都須要權衡利弊,將 Rust 語言加入 npm 的生產服務也不例外。將 Rust 引入 npm 的最大缺點是,現有的 JavaScript 技術棧和新的 Rust 技術棧都有本身的解決方案,用來進行狀態監視、日誌記錄與發出警報;而維護這些解決方案有必定的負擔。做爲一門年輕的語言,Rust 尚未用以完成工業級產品標準的庫和最佳實踐,可是但願在不久的未來能實現。
Rust 語言是一種可擴展且易於部署的解決方案。它能夠佔用較少的資源而不影響內存安全性。經過 Cargo 的依賴管理爲系統編程領域帶來了現代化工具。雖然仍有最佳實踐和工具備待提升,但社區的創建保證了長期成功。出於這些緣由,npm 選擇了 Rust 來處理 CPU 限制的性能瓶頸。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。