微服務架構為軟件開發帶來了極大的靈活性,并加快了交付速度,但同時也帶來了依賴管理問題。傳統的解決方案雖然能夠解決依賴管理問題,但都太極端,顧此失彼。于是,Netflix嘗試著尋找自己的解決方案,期待著在整個組織層面做到真正的持續集成。本文內容來自Netflix技術博客,已獲得翻譯授權,查看英文原文 Towards true continuous integration:distributed repositories and dependencies。
在過去的8年間,Netflix基于AWS構建了一套健壯的微服務架構,我們因此學會了如何在AWS上構建可靠的高性能服務。我們的微服務架構解耦了工程團隊,讓他們可以自由地構建、測試和部署他們的服務。這種靈活性最大化了團隊的交付速度。在Netflix,交付速度和可靠性是設計解決方案時首要的考慮點。
基于我們的架構,微服務為它們的消費者提供了一個客戶端軟件包,用于處理所有的IPC(進程間通信)邏輯。這同時為服務的提供者和消費者帶來了很多好處。除了客戶端,微服務的很大部分是基于我們的運行時平臺而構建的,這個平臺由內部的軟件包和第三方開源的軟件包組成。
盡管服務開發團隊有很大的發布靈活性,但他們的交付速度卻受到了依賴軟件包的影響。一項新增的產品特性可能要求很多微服務都用上最新版本的共享軟件包或客戶端,而更新依賴版本可能會帶來風險。
簡而言之,依賴管理是一項艱巨的任務。
更新項目的依賴可能帶來潛在的問題。
具有阻斷性的API變更。這是最典型的場景,一個編譯錯誤導致整個構建失敗。由依賴鎖定(Dependency Locking)和動態版本選擇器組成的語義版本控制(Semantic Versioning)可以幫助大部分團隊避免發生這種錯誤。不過,鎖定在一個主版本上會讓整個公司的代碼升級變得很困難,導致配置漂移(Configuration Drift),并且需要長期地維護舊軟件包。 具有傳遞性的依賴更新。因為JVM的類路徑是扁平結構,所以在一個應用程序里,一個類只能存在一個版本。像Gradle和Maven這類工具可以處理版本沖突,避免同一個軟件包的多個版本被引入到項目當中。這也意味著,你的應用程序里有一些代碼依賴了具有傳遞性特征的軟件包,但你的代碼并沒有針對它們進行過測試。 具有阻斷性的功能變更。理想情況下,這個問題可以通過執行適當的測試來緩解。軟件包的所有者可以通過運行使用者的測試案例來了解他們對軟件包功能的預期。我們發現,為了解決大規模的依賴管理問題,很多公司使用了兩種方案:共享最小化(Share Little)和單體倉庫(MonoRepo)。
共享最小化(或者干脆不使用共享軟件包)最近在微服務領域很流行,它的核心論調是說,微服務之間不應該共享代碼,服務之間只能通過HTTP API進行耦合。更有甚者,有人說直接使用拷貝加黏貼的方式來代替共享軟件包。這是一種非常極端的解耦手段。 單體倉庫的核心論調是說,組織的所有代碼應該全部保存在一個單獨的倉庫里。任何一個代碼變更在提交到HEAD之前,都需要針對整個代碼倉庫進行編譯和測試。內部軟件包沒有所謂的版本,只有HEAD代碼。所有的提交在到達HEAD之前需要跨過一些門檻。第三方軟件包需要通過“審批”才能被使用,而且僅限于一兩個版本。這兩種方式都能解決大規模的依賴管理問題,不過它們也帶來了一些挑戰。共享最小化促進了解耦,也加快了工程速度,但犧牲了代碼的重用性和一致性。單體倉庫保證了代碼一致性,并降低了風險,但犧牲了靈活性。不管采用哪一種方式,我們都需要對Netflix的開發基礎設施和運行時架構做出重大的調整。況且,這兩種方案會破壞我們所推崇的自由和責任文化。
我們給自己提出了一個很大的挑戰目標:
我們能否為Netflix的工程師們提供一種解決方案,它不但具有單體倉庫的優勢,還能保持分布式倉庫的靈活性?
我們以單體倉庫為藍本,另辟蹊徑,希望找出能夠達到相同目的的可替代方案。單體倉庫所要解決的核心問題是什么?我們能否在傳統的二元集成世界里開發出一種新的方案?
我們的解決方案,雖然還在試驗階段,不過可以從中歸納出三個關鍵的特性。
向發布者反饋。直接或間接地向共享代碼所有者快速地反饋使用者所遇到的問題。同時,允許團隊因下游依賴的中斷而暫停發布。目前,我們不會把這類問題的責任歸咎到使用者身上。通過向軟件包所有者反饋他們的問題給Netflix帶來的影響,希望他們能夠負起應有的責任。 來源管理。當有新版本發布時,為使用者提供一種安全的方式,用于自動增加軟件包的版本。既然我們已經針對所有的下游依賴測試過每一個軟件包,那為什么不直接讓使用者知道新版本,從而加快新版本的采用速度呢! 分布式重構。為共享代碼的所有者提供一種方式,讓他們可以全局地對API的使用者進行快速的重構。我們已經開始向使用了某些特定Java API的Git代碼倉庫發起了全面的拉取請求。我們已經做了一些試驗,并希望在這方面有更多的投入。我們的旅程才剛剛開始。我們的發布者反饋服務目前正處于alpha測試階段,我們計劃后續會大規模采用這個服務,緊接著會進行來源管理。我們的分布式重構試驗讓我們了解到進行快速的全局重構是多么的重要。我們也看到了通過我們所構建的工具來降低依賴圖復雜度的可能性。我們相信,通過擴展和培養這種能力,我們的Netflix團隊將會在組織層面做到真正的持續集成,并減少(甚至免去)依賴管理的痛苦。
感謝郭蕾對本文的審校。