Scala在Databricks的大規模應用

banq發表於2022-01-20

Databricks 擁有數百名開發人員和數百萬行程式碼,是最大的 Scala 應用之一。這篇文章將在 Databricks 對 Scala 進行一次廣泛的介紹,從開始到使用、風格、工具和挑戰,從這篇文章中,您將瞭解在 Databricks 中使 Scala 工作的所有大大小小的資訊,對於支援在成長中的組織中使用 Scala 的任何人來說,這是一個有用的案例研究。
Databricks 由 Apache Spark 的原始建立者構建,最初是分散式 Scala 集合。選擇 Scala 是因為它是少數具有可序列化 lambda 函式的語言之一,而且它的 JVM 執行時允許與基於 Hadoop 的大資料生態系統輕鬆互操作。從那時起,Spark 和 Databricks 的發展都遠遠超出了任何人最初的想象。
Scala 今天是Databricks 中的一種通用語言。
檢視我們的程式碼庫,最流行的語言是 Scala,有數百萬行,其次是 Jsonnet(用於配置管理)、Python(指令碼、ML、PySpark)和 Typescript(Web)。
Databricks 並不反對編寫非 Scala 程式碼。我們還有高效能的 C++ 程式碼、一些 Jenkins Groovy、在 Nginx 中執行的 Lua、一些 Go 和其他東西。但大部分程式碼仍使用Scala。
Databricks 的幾乎每個人都編寫了一些 Scala,但很少有人是狂熱者。我們沒有進行正式的 Scala 培訓。人們帶著各種各樣的背景來到這裡,第一天就開始編寫 Scala,然後隨著時間的推移慢慢掌握更多的功能特性。由此產生的 Java-Python-ish 風格是自然的結果。
儘管幾乎每個人都編寫了一些 Scala,但 Databricks 的大多數人並沒有深入研究該語言。人們首先是基礎設施工程師、資料工程師、ML 工程師、產品工程師等等。有時,我們必須深入處理一些棘手的問題(例如,著色、反射、宏等),但這遠遠超出了大多數 Databricks 工程師需要處理的標準。
總的來說,大多數 Databricks 程式碼都存在於單一儲存庫中。Databricks 對 mono-repo 中的所有內容都使用 Bazel 構建工具:Scala、Python、C++、Groovy、Jsonnet 配置檔案、Docker 容器、Protobuf 程式碼生成器等。鑑於我們從 Scala 開始,這曾經都是 SBT,但是我們主要遷移到 Bazel 是為了更好地支援大型程式碼庫。我們仍然在 SBT 或 Mill 上維護一些較小的開源儲存庫,並且在我們嘗試完成遷移時,一些程式碼具有並行的 Bazel/SBT 構建,但我們的大部分程式碼和基礎設施都是圍繞 Bazel 構建的。
 
Scala 編譯速度是一個普遍關注的問題,我們付出了巨大的努力來緩解這個問題:
  • 設定 Bazel 以使用長期存在的後臺編譯工作者來編譯 Scala,以保持編譯器 JVM 的熱和快速。
  • 在選擇加入的基礎上為想要使用它的人設定增量編譯(透過 Zinc)和並行編譯(透過 Hydra)。
  • 升級到更新版本的 Scala 2.12,比以前的版本快得多。

 
Scala 在主要版本之間是二進位制不相容的,這意味著需要為兩個版本分別編譯旨在支援多個版本的程式碼。即使忽略 Scala,支援多個 Spark 版本也有類似的要求。Databricks 的 Bazel-Scala 整合內建了交叉構建,每個構建目標(相當於“模組”或“子專案”)都可以指定它支援的 Scala 版本列表:

cross_scala_lib ( 
    base_name = "my_lib" , 
    cross_scala_versions = [ "2.11" , "2.12" ], 
    cross_deps = [ "other_lib" ], 
    srcs = [ "Test.scala" ], )     

透過上述輸入,我們的cross_scala_lib函式生成構建目標的my_lib_2.11和my_lib_2.12版本,並依賴於相應的other_lib_2.11和other_lib_2.12目標。
。。。。。
  

Scala 非常適合做指令碼/膠水類應用!
人們通常認為 Scala 是一種用於編譯器或 Serious Business後端服務的語言。但是,我們發現 Scala 對於類似指令碼的膠水程式碼來說也是一種出色的語言!我的意思是程式碼雜耍子程式、與 HTTP API 通訊、處理 JSON 等。雖然 Scala 的 JVM 執行時的高效能對於指令碼編寫無關緊要,但許多其他平臺優勢仍然適用:

  • Scala是簡潔的。根據您使用的庫,它可以與 Python 或 Ruby 等“傳統”指令碼語言一樣簡潔,甚至更簡潔,並且具有同樣的可讀性。
  • 指令碼/粘合程式碼通常是最難進行單元測試的。整合測試雖然可能,但通常是緩慢而痛苦的;我們不止一次讓第三方服務因為執行過多的整合測試而限制我們!在這種環境中,具有基本的編譯時檢查水平是天賜之物。
  • 部署很好:程式集 jar 比 Python PEX 好得多,例如,因為它們更標準、更簡單、更封閉、更高效等。嘗試在不同環境中部署 Python 程式碼一直是一個令人頭疼的問題,總是有人brew install或apt-get install會導致我們部署和測試的 Python 可執行檔案崩潰。Scala 程式集 jar 不會發生這種情況。

Scala/JVM 並編寫指令碼並不完美:任何非平凡程式都有 0.5-1 秒的 JVM 啟動開銷,記憶體使用率很高,編輯/編譯/執行 Scala 程式的迭代迴圈相對較慢。儘管如此,我們發現使用 Scala 與 Python 等傳統指令碼語言相比有很多好處,並且我們已經在許多人們自然希望使用指令碼語言的場景中引入了 Scala。甚至 Scala 的 REPL 也被證明是一種有價值的工具,可以方便靈活地與內部和第三方服務進行互動。
點選標題

相關文章