探索 Blue 如何利用 Rust 和可擴展架構及戰略技術選擇,將 CSV 匯入和匯出擴展 10 倍。
在 Blue,我們不斷推動項目管理軟體的可能性邊界。多年來,我們已經發布了數百個功能。
我們最新的工程成就?
對我們的 CSV 匯入 和 匯出 系統進行了全面的改革,顯著提高了性能和可擴展性。
這篇文章將帶您深入了解我們如何應對這一挑戰、我們所採用的技術以及我們所取得的驚人結果。
最有趣的是,我們不得不走出我們典型的 技術堆疊 以實現我們想要的結果。這是一個必須深思熟慮的決定,因為長期的後果可能在技術負債和長期維護開銷方面是嚴重的。
為企業需求擴展
我們的旅程始於一位來自活動行業的企業客戶的請求。這位客戶將 Blue 作為管理大量活動、場地和講者的中央樞紐,並與他們的網站無縫整合。
對他們而言,Blue 不僅僅是一個工具——它是他們整個運營的唯一真相來源。
雖然我們總是驕傲地聽到客戶將我們用於如此關鍵的需求,但我們也承擔著巨大的責任,以確保系統的快速和可靠。
隨著這位客戶擴大其業務,他們面臨了一個重大障礙:匯入和匯出包含 100,000 到 200,000+ 筆記錄的大型 CSV 文件。
這超出了我們當時系統的能力。事實上,我們之前的匯入/匯出系統已經在處理超過 10,000 到 20,000 筆記錄的匯入和匯出時掙扎!所以 200,000+ 筆記錄根本不可能。
用戶經歷了令人沮喪的長等待時間,在某些情況下,匯入或匯出甚至會完全無法完成。這對他們的運營造成了重大影響,因為他們依賴每日的匯入和匯出來管理運營的某些方面。
多租戶是一種架構,其中單個軟體實例為多個客戶(租戶)提供服務。雖然高效,但需要仔細的資源管理,以確保一個租戶的行為不會對其他租戶產生負面影響。
而這一限制不僅僅影響這位特定客戶。
由於我們的多租戶架構——多個客戶共享相同的基礎設施——單個資源密集型的匯入或匯出可能會潛在地減慢其他用戶的操作,這在實踐中經常發生。
像往常一樣,我們進行了建設與購買的分析,以了解我們是否應該花時間升級自己的系統或從其他地方購買系統。我們考慮了各種可能性。
突出的供應商是一家名為 Flatfile 的 SaaS 提供商。他們的系統和能力看起來正是我們所需要的。
但是,在審查了他們的 定價 後,我們決定這將成為一個對於我們規模的應用來說極其昂貴的解決方案——每個文件 $2 的成本迅速累積!——因此更好的是擴展我們內建的 CSV 匯入/匯出引擎。
為了應對這一挑戰,我們做出了一個大膽的決定:將 Rust 引入我們的主要 Javascript 技術堆疊中。這種系統編程語言以其性能和安全性而聞名,是滿足我們性能關鍵的 CSV 解析和數據映射需求的完美工具。
以下是我們解決方案的具體方法。
引入背景服務
我們解決方案的基礎是引入背景服務來處理資源密集型任務。這種方法使我們能夠將重處理卸載到主伺服器之外,顯著提高了整體系統性能。
我們的背景服務架構是以可擴展性為考量設計的。像我們基礎設施的所有組件一樣,這些服務根據需求自動擴展。
這意味著在高峰時期,當多個大型匯入或匯出同時處理時,系統會自動分配更多資源來應對增加的負載。相反,在較安靜的時期,它會縮減以優化資源使用。
這種可擴展的背景服務架構不僅使 Blue 在 CSV 匯入和匯出中受益。隨著時間的推移,我們已經將大量功能移入背景服務,以減輕我們主伺服器的負擔:
- 公式計算:卸載複雜的數學運算,以確保衍生字段的快速更新,而不影響主伺服器性能。
- 儀表板/圖表:在背景中處理大型數據集,以生成最新的可視化,而不會減慢用戶界面。
- 搜索索引:在背景中持續更新搜索索引,確保快速和準確的搜索結果,而不影響系統性能。
- 複製項目:在背景中處理大型複雜項目的複製,使用戶在複製過程中能繼續工作。
- 項目管理自動化:在背景中執行用戶定義的自動化工作流程,確保及時行動而不阻塞其他操作。
- 重複記錄:在背景中生成定期任務或事件,保持時間表的準確性,而不給主應用帶來負擔。
- 時間持續自定義字段:持續計算和更新 Blue 中兩個事件之間的時間差,提供實時的持續時間數據,而不影響系統的響應能力。
新的 Rust 模組用於數據解析
我們的 CSV 處理解決方案的核心是一個自定義的 Rust 模組。雖然這標誌著我們首次走出核心技術堆疊的 Javascript,但使用 Rust 的決定是基於其在並發操作和文件處理任務中的卓越性能。
Rust 的優勢與 CSV 解析和數據映射的需求完美契合。它的零成本抽象允許高級編程而不犧牲性能,而其所有權模型確保了內存安全,無需垃圾回收。這些特性使 Rust 特別擅長高效、安全地處理大型數據集。
對於 CSV 解析,我們利用了 Rust 的 csv crate,它提供高性能的 CSV 數據讀取和寫入。我們將這一點與自定義數據映射邏輯相結合,以確保與 Blue 的數據結構的無縫整合。
學習 Rust 的曲線陡峭但可管理。我們的團隊花了大約兩週的時間進行了密集學習。
改進的效果令人印象深刻:
我們的新系統能在約 30 秒內處理與舊系統在 15 分鐘內能處理的相同數量的記錄。
網頁伺服器與數據庫互動
對於我們 Rust 實現的網頁伺服器組件,我們選擇了 Rocket 作為我們的框架。Rocket 以其性能和開發者友好的特性而脫穎而出。它的靜態類型和編譯時檢查與 Rust 的安全原則很好地對齊,幫助我們在開發過程中及早發現潛在問題。
在數據庫方面,我們選擇了 SQLx。這個 Rust 的異步 SQL 庫提供了幾個優勢,使其成為我們需求的理想選擇:
- 類型安全的 SQL:SQLx 允許我們編寫原始 SQL,並進行編譯時檢查查詢,確保類型安全而不犧牲性能。
- 異步支持:這與 Rocket 及我們對高效、非阻塞數據庫操作的需求相符。
- 數據庫無關性:雖然我們主要使用 AWS Aurora,其與 MySQL 兼容,但 SQLx 對多個數據庫的支持為我們未來提供了靈活性,以防我們決定更改。
批量優化
我們尋求最佳批量配置的旅程是一個嚴格測試和仔細分析的過程。我們進行了廣泛的基準測試,測試各種並發交易和塊大小的組合,不僅測量原始速度,還測量資源利用率和系統穩定性。
這一過程涉及創建不同大小和複雜性的測試數據集,模擬現實世界的使用模式。我們然後將這些數據集通過我們的系統,調整每次運行的並發交易數量和塊大小。
在分析結果後,我們發現處理 5 個並發交易和 500 筆記錄的塊大小提供了速度和資源利用率的最佳平衡。這一配置使我們能夠保持高吞吐量,而不會使數據庫過載或消耗過多內存。
有趣的是,我們發現將並發性增加到 5 個交易以上並未帶來顯著的性能提升,有時甚至導致數據庫競爭加劇。同樣,較大的塊大小提高了原始速度,但以更高的內存使用和對小到中型匯入/匯出的更長響應時間為代價。
通過電子郵件鏈接匯出 CSV
我們解決方案的最後一部分解決了將大型匯出文件交付給用戶的挑戰。我們沒有提供從我們的網頁應用程序直接下載,因為這可能導致超時問題和增加伺服器負載,而是實施了一個通過電子郵件發送下載鏈接的系統。
當用戶啟動大型匯出時,我們的系統在背景中處理請求。完成後,我們不會保持連接開放或將文件存儲在我們的網頁伺服器上,而是將文件上傳到安全的臨時存儲位置。然後,我們生成一個唯一的安全下載鏈接並通過電子郵件發送給用戶。
這些下載鏈接的有效期為 2 小時,這在用戶便利性和信息安全之間取得了平衡。這一時間框架為用戶提供了充足的機會來檢索他們的數據,同時確保敏感信息不會無限期地保持可訪問。
這些下載鏈接的安全性是我們設計中的首要任務。每個鏈接都是:
- 唯一且隨機生成的,幾乎不可能被猜測
- 只有 2 小時的有效期
- 在傳輸過程中加密,確保數據在下載時的安全性
這種方法提供了幾個好處:
- 它減少了我們的網頁伺服器的負擔,因為它們不需要直接處理大型文件下載
- 它改善了用戶體驗,特別是對於那些可能面臨瀏覽器超時問題的慢速互聯網連接用戶
- 它為非常大的匯出提供了更可靠的解決方案,這些匯出可能超過典型的網頁超時限制
用戶對此功能的反饋非常積極,許多人欣賞它在管理大型數據匯出方面提供的靈活性。
匯出過濾後的數據
另一個明顯的改進是允許用戶僅匯出在其項目視圖中已過濾的數據。這意味著如果有活動標籤“優先”,那麼只有具有此標籤的記錄才會出現在 CSV 匯出中。這意味著在 Excel 中操作數據以過濾不重要的內容所需的時間更少,並且還幫助我們減少需要處理的行數。
展望未來
雖然我們沒有立即擴大使用 Rust 的計劃,但這個項目向我們展示了這項技術在性能關鍵操作中的潛力。這是我們現在在未來優化需求中擁有的令人興奮的選擇。這次 CSV 匯入和匯出的改革與 Blue 對可擴展性的承諾完美契合。
我們致力於提供一個隨著客戶增長而增長的平台,處理他們不斷擴大的數據需求,而不妥協性能。
將 Rust 引入我們的技術堆疊的決定並不是輕率做出的。這提出了一個許多工程團隊面臨的重要問題:什麼時候適合走出核心技術堆疊,什麼時候應該堅持使用熟悉的工具?
沒有一個放之四海而皆準的答案,但在 Blue,我們已經制定了一個框架來做出這些關鍵決策:
- 以問題為先的方式: 我們總是從明確定義我們要解決的問題開始。在這種情況下,我們需要顯著提高大型數據集的 CSV 匯入和匯出的性能。
- 耗盡現有解決方案: 在尋找核心堆疊之外的解決方案之前,我們徹底探索現有技術能夠實現的內容。這通常涉及分析性能、優化和在熟悉的約束內重新思考我們的方法。
- 量化潛在收益: 如果我們考慮引入新技術,我們需要能夠清晰地表達,並且理想情況下量化其好處。對於我們的 CSV 項目,我們預測處理速度會有數量級的提升。
- 評估成本: 引入新技術不僅僅是關於當前項目。我們考慮長期成本:
- 團隊的學習曲線
- 持續的維護和支持
- 部署和運營中的潛在複雜性
- 對招聘和團隊組成的影響
- 控制和整合: 如果我們確實引入新技術,我們的目標是將其限制在系統的特定、明確定義的部分。我們還確保有清晰的計劃來整合它與我們現有的堆疊。
- 未來保障: 我們考慮這一技術選擇是否開啟了未來的機會,或者是否可能將我們困在某個角落。
頻繁採用新技術的主要風險之一是最終形成我們所稱的 “技術動物園”——一個碎片化的生態系統,其中應用的不同部分使用不同的語言或框架,維護需要廣泛的專業技能。
結論
這個項目體現了 Blue 的工程方法:我們不怕走出舒適區,採用新技術,只要這意味著為我們的用戶提供顯著更好的體驗。
通過重新構想我們的 CSV 匯入和匯出過程,我們不僅解決了對一位企業客戶的迫切需求,還改善了所有處理大型數據集的用戶的體驗。
隨著我們繼續推動項目管理軟體的可能性邊界,我們期待著迎接更多像這樣的挑戰。
請持續關注更多 深入探討驅動 Blue 的工程!