Aembit為什麼選擇 Rust?

banq發表於2022-09-17

Aembit 是一個平臺,可將身份分配給工作負載並控制對其互動的服務的訪問。Aembit 平臺由兩個元件組成:
  • 基於雲的管理平面,包括管理控制檯和系統後端
  • 與客戶流量保持一致並按照管理平面的指示執行操作的代理

本文重點介紹我們對代理元件的語言選擇。

C++
我們團隊的明顯選擇是C++。這是團隊中的工程師們在構建以前的產品時使用的語言,而且大多數現代代理的開發者也使用它。然而,C++的記憶體管理和併發的危險在過去曾咬過這些人,要對程式碼的安全性有信心並不容易,特別是當新成員加入團隊時,他們的編碼能力和成熟度各不相同。

Golang
下一個競爭者是Go,我們的團隊在這方面有一些經驗。由於Go的高效能、併發支援和安全性,它是網路程式設計的一個常見選擇。由於Go是一種垃圾收集的語言,它可以防止許多可能困擾C++程式碼的記憶體問題。然而,垃圾收集器為高效能應用程式帶來了另一種挑戰。雖然Go的垃圾收集器總體上具有良好的聲譽,但高效能應用程式可能會表現出垃圾收集暫停阻礙效能的問題。儘管Go提供了一些調整垃圾收集器的方法,但並沒有辦法規避所有潛在的挑戰。雖然我們通常對在充分了解效能瓶頸之前對效能進行過度最佳化持謹慎態度,但對於我們這個剛剛起步的產品來說,以後需要用更高效能的語言重寫代理的可能性太大。

Rust
我們的第三個選擇,也是我們的最終選擇,是Rust。Rust結合了C++的效能和Go的記憶體安全保證。然而,有一個小小的挑戰,那就是我們團隊中沒有人有Rust的經驗。我們的第一位工程師從閱讀《Rust程式設計》開始,經過一個半月的經驗積累,足以建立起代理的初始原型。請注意,這位工程師有很多過去的開發經驗,這不是一個經驗不足的人可能會做的事情。

進展順利
1、支援性社群

如果沒有遍佈網際網路的Rust社群的幫助,我們不可能取得如此大的進展,尤其是考慮到我們團隊的Rust經驗很少。Stack Overflow、Rust程式語言論壇以及Discord、Slack和Gitter上的特定專案社群對我們在原型設計階段和之後的工作都起到了重要作用。

2、工具化
Rust的工具生態系統發展良好。Rust的包管理器、通用的瑞士軍刀,稱為Cargo,使得構建、測試、執行和依賴性管理變得非常簡單。它還透過GitHub Actions輕鬆實現了我們的CI流程。我們成功利用的其他工具包括。

  • 格式化(透過Rustfmt)
  • 提示(透過Clippy)
  • 語言伺服器(透過Rust-analyzer)和相關的VS Code外掛
  • 除錯(透過LLDB)
  • 本地單元和整合測試
  • 程式碼覆蓋率(透過LLVM)


3、信心
到目前為止,用Rust開發已經給我們帶來了輕微的信心優勢,否則我們可能不會有這樣的信心。Rust的Result和Option型別使錯誤處理變得明確和詳盡,而且Rust由於沒有null的概念,所以減少了執行時錯誤。我們可以透過搜尋程式碼庫中的 "unwrap "和 "expect "方法找到幾乎所有可能發生執行時錯誤的地方。

Rust的效能與C和C++處於同一數量級。由於它缺乏垃圾收集,所以我們並不擔心我們是否有能力調整我們的應用程式,以滿足我們的客戶在未來可能需要的任何資源和效能要求。我們有信心將我們的程式碼最佳化到需要的程度。

最後,Rust的記憶體安全保證消除了我們在使用C++時可能會出現的一類錯誤。這讓我們感到非常安心,並釋放了精神頻寬,使我們能夠專注於其他優先事項,而不是捕捉記憶體漏洞。

挑戰

1、學習曲線
Rust是一種大語言,有一些具有挑戰性的概念,如所有權和壽命。正如我們的一位工程師所指出的,由於Rust的分層複雜性,學習Rust的概念往往具有挑戰性。在沒有深入瞭解記憶體模型、壽命和其他主題的情況下,人們不可能只是潛心研究非同步程式碼這樣的主題。這使得開始學習Rust的人在沒有徹底理解發生了什麼的情況下就跳入深淵是很棘手的。同一位工程師指出,C++的初學者可以比Rust的初學者更快產生程式碼。不過,他們在剛開始時寫的C++程式碼還是很危險的,而Rust的編譯器會首先阻止不安全程式碼的編譯。

2、僱用情況
僱用Rust程式設計師是很棘手的。由於它仍然是一種相對較新的語言,所以很難找到精通該語言細節的人。我們花了四個月的時間才找到一個有Rust經驗的高階開發人員,他是適合我們這個團隊的。

3、原型到生產
根據我們的經驗,在Rust程式碼庫中對設計進行大量的重新架構是很痛苦的。Rust有嚴格的規則來支援沒有垃圾收集的安全,這迫使你堅持使用Rust友好的架構。作為一個團隊,我們還沒有形成對Rust的經驗,無法預見到什麼是可以在Rust中乾淨地實現的,什麼是不可以。因此,當我們試圖從最初的原型遷移到第二稿時,我們遇到了多個路障。人們常說,Rust迫使你提前考慮你的設計。這對快速迭代是一個挑戰。

總結
如果我們重新開始,我們會再次使用Rust嗎?我們仍然不確定。雖然我們很高興我們選擇了Rust而不是C++來保證我們的記憶體安全,但我們仍然懷疑Go是否足以滿足我們的目的。Go似乎可以解決所有列出的挑戰。

  • 它的學習曲線要簡單得多。
  • 它更容易找到對它有深刻經驗的程式設計師。
  • 它的垃圾收集意味著更容易重新架構。

然而,有了Rust,我們不會為最佳化效能的能力而失眠,並對我們的執行時穩定性感到比以往更有信心。如果你處於類似的情況,正在評估Rust和Go,我們建議仔細考慮我們上面強調的挑戰。仔細考慮Rust所提供的速度和執行時的穩定性是否能證明這些實際的障礙。

相關文章