云端開發(fā)環(huán)境是軟件工程的未來嗎?
一些運行在 Kubernetes 中的復(fù)雜微服務(wù)架構(gòu)是 CPU 和內(nèi)存密集型的,在某些情況下編譯或測試可能非常耗時且占用大量資源。然而大多數(shù)工程師的標(biāo)準(zhǔn)設(shè)備是筆記本電腦,有 CPU 和內(nèi)存的限制,編譯一次的時間估計夠喝好幾杯咖啡。
建立在云端的遠(yuǎn)程實例通常可以根據(jù)需要進行擴展,以適應(yīng)對容量的額外需求,因此在容器化變革的基礎(chǔ)上,一些企業(yè)開始不再那么依賴于本地開發(fā)環(huán)境。雖然近一兩年有一些令人興奮的遠(yuǎn)程方案,比如 GitHub Codespaces、AWS Workspaces 或其它使用云的標(biāo)準(zhǔn)解決方案,但在它們足夠成熟和安全之前,很多企業(yè)早已選擇了自建云端開發(fā)環(huán)境,Lyft 就是其中之一。
云端開發(fā)逐漸成為了坑
早在 2018 年,Lyft 的工程師就將一個大單體拆分成了一系列微服務(wù)。基于 Docker 容器的模塊化開發(fā)環(huán)境最終轉(zhuǎn)移到了云端。然而隨著時間的推移,工程師、微服務(wù)和測試的數(shù)量的激增,他們的開發(fā)工具跟不上了。
實際上,Lyft 對綜合開發(fā)環(huán)境的第一次重大投資始于 2015 年,當(dāng)時的工程師人數(shù)為 100 名,大部分開發(fā)還是在一個單體架構(gòu)上,只有少數(shù)用例是微服務(wù),但預(yù)計到工程師和服務(wù)的數(shù)量會增長,所以他們認(rèn)為遷移到容器是很有意義的。最初的計劃是構(gòu)建一個基于 Docker 的容器編配環(huán)境,工程師可以用它們做測試。它將在生產(chǎn)環(huán)境中使用多租戶環(huán)境,相比以前的解決方案,可以更便宜、更快地進行伸縮。
2016 年初,Lyft 發(fā)布了一個本地開發(fā)環(huán)境,叫作 Devbox,是“盒子里的開發(fā)環(huán)境”的縮寫,由一些管理本地虛擬機及其配置的工具組成,包括數(shù)據(jù)生成、包和鏡像的下載和安裝。開發(fā)人員只需要發(fā)出一個命令就可以構(gòu)建一個可以處理請求的環(huán)境。
這些體驗很棒,讓工程師們第一次擁有了一種一致的、可重復(fù)的、簡單跨多個服務(wù)開發(fā)方法,于是很快出現(xiàn)了共享這些環(huán)境的需求。Devbox 轉(zhuǎn)向了云端,變成了 Onebox。Onebox 本質(zhì)上是一個運行在 EC2 實例上的 Devbox 環(huán)境。由于它的容量更大,下載鏡像的速度更快,工程師們自然更喜歡它而不是 Devbox。
兩種不同風(fēng)格的開發(fā)環(huán)境
在將 Devbox 和 Onebox 作為容器化開發(fā)環(huán)境引入四年后,使用這些環(huán)境的工程師增加了十倍,微服務(wù)數(shù)量也一直在激增,配置和啟動 Onebox 實例變得越來越困難和耗時。
由于每個服務(wù)都有很深的交互樹結(jié)構(gòu),實例可能需要很多的資源。可觀察性工具不能跟上所有正在運行的環(huán)境,導(dǎo)致調(diào)試工作變得很困難。打比方說,不可能在數(shù)百個環(huán)境中運行相同的可觀察性工具,當(dāng)出現(xiàn)問題時,就很難查明確切原因。此外,工程師的認(rèn)知負(fù)擔(dān)顯著增加,因為他們需要牢記整個系統(tǒng),而不是專注于特定的組件。
根據(jù) Lyft 的工程設(shè)計,工程師的代碼變更過程可以分為“內(nèi)部開發(fā)循環(huán)”和“外部開發(fā)循環(huán)”。前者應(yīng)該只需要幾秒鐘就能給出反饋,因為它只涉及修改代碼和運行一些測試。后者可能需要更長的時間(至少 10 分鐘),因為它涉及持續(xù)集成和代碼評審。集成測試臃腫笨拙,花費一個小時是司空見慣的事情。并且 80% 以上的測試要么是不必要的,要么可以在短時間內(nèi)重寫并在沒有外部依賴的情況下運行。測試失敗還要花費數(shù)小時的調(diào)試時間,大多數(shù)還都是誤報。
另一方面,執(zhí)行內(nèi)部開發(fā)循環(huán)通常需要將代碼更改同步到開發(fā)人員自己在 Onebox 的遠(yuǎn)程 VM 環(huán)境。考慮到 Onebox 環(huán)境的設(shè)置和啟動速度很慢,再加上明顯的不穩(wěn)定性,工程師通常會依賴外部開發(fā)循環(huán)的 CI 測試來驗證每個代碼變更迭代。
一年前,將開發(fā)環(huán)境遷移到 Kubernetes 之后,工程資源的變化讓大家不得不重新審視開發(fā)環(huán)境:維護基礎(chǔ)設(shè)施以支持這些按需環(huán)境變得過于昂貴,而且只會隨著時間的推移而惡化,所以需要對開發(fā)和測試微服務(wù)的方式進行更根本性的改變。
開發(fā)環(huán)境必須回到工程師的機器上
為了擺脫不斷增長的煩惱和挫折,Lyft 將開發(fā)環(huán)境帶回到工程師的筆記本電腦上,同時重新構(gòu)建內(nèi)部開發(fā)循環(huán)。
在容器中運行代碼并不是一種免費的抽象,因此他們決定在 macOS 的隔離環(huán)境中運行服務(wù)代碼,不使用容器或虛擬機。
在 Lyft,大多數(shù)后端服務(wù)是用 Python 或 Go 語言開發(fā)的,而前端服務(wù)是用 Node 開發(fā)的:
- 對于 Python 服務(wù),通過使用不可變的虛擬環(huán)境進行隔離。每次 requirements.txt 文件發(fā)生變化,都會構(gòu)建一個新的虛擬環(huán)境。
- Go 服務(wù)利用 Go 模塊工具鏈在 go run 或 go test 命令執(zhí)行時自動下載和鏈接所有依賴項。
- 他們基于 nodeenv 構(gòu)建了一個包裝器,用于根據(jù)每個 Node 服務(wù)的元數(shù)據(jù)為其創(chuàng)建合適的環(huán)境。
一些專門的服務(wù),如數(shù)據(jù)存儲,也在本地運行,通常會使用容器。數(shù)據(jù)存儲在啟動時使用由服務(wù)所屬團隊維護的腳本來加載新數(shù)據(jù)。
因此,在本地啟動服務(wù)需要多個步驟。通過手動來執(zhí)行它們既乏味又容易出錯。Lyft 使用 Tilt 來協(xié)調(diào)服務(wù)的生命周期及其環(huán)境,避免通過手動執(zhí)行所有的步驟。每個服務(wù)都有一個 Tiltfile,用于描述在本地運行服務(wù)所需的步驟。當(dāng)工程師在 IDE 中修改了代碼時,運行中的服務(wù)也會重新加載自己,從而進一步縮短內(nèi)部開發(fā)循環(huán)。
除了運行服務(wù)之外,還需要與服務(wù)發(fā)生交互。由于 Lyft 使用了不同的傳輸格式,比如 gRPC、JSON/HTTP 和 protobuf/HTTP,因此向服務(wù)發(fā)出請求并不是那么簡單。工程師們使用 Lyft 開發(fā)的一個工具向本地服務(wù)發(fā)送請求。這個工具可以與服務(wù)的 IDL 集成,因此可以利用工具的自動補全功能。
最終結(jié)果
自從將這個工具推廣到整個公司以來,Lyft 工程師反饋非常積極。
開發(fā)人員喜歡無需任何遠(yuǎn)程環(huán)境即可在筆記本電腦和 IDE 中運行測試的能力。創(chuàng)建一個新的 Onebox 環(huán)境通常需要大約一個小時,但現(xiàn)在筆記本電腦環(huán)境始終可以運行測試,使用 Tilt 在本地啟動服務(wù)只需幾分鐘。
負(fù)責(zé)基礎(chǔ)架構(gòu)的高級軟件工程師 Scott Wilson 說:“我們還觀察到開發(fā)人員的行為轉(zhuǎn)變,因為他們花費更多時間專注于測試他們的服務(wù)。在測試本地服務(wù)時,用戶可以直接向服務(wù) API 發(fā)送請求,而不是通過移動應(yīng)用程序與公共 API 對話。這增加了開發(fā)人員對服務(wù) API 的熟悉程度,并縮小了在出現(xiàn)錯誤時的調(diào)試范圍。”
而且讓用戶在他們的筆記本電腦上單獨運行服務(wù)意味著真正減少所需的總計算資源。“雖然成本不是這個項目的主要驅(qū)動因素,但不再為每個開發(fā)人員支付 Onebox 的 AWS 實例,我們最終節(jié)省了大量資金。”
總的來說,對于開發(fā)者來說,因開發(fā)環(huán)境而導(dǎo)致正常工作停滯不前是特別讓人不可忍受的。不好的開發(fā)環(huán)境會嚴(yán)重影響大家的生產(chǎn)力,而一個好的本地開發(fā)環(huán)境,允許開發(fā)人員在沒有破壞共享環(huán)境或干擾面向客戶的環(huán)境的風(fēng)險的情況下運行和測試代碼。而且,它通常是低成本的,依賴于已經(jīng)支付的資產(chǎn),比基于云的環(huán)境更高效、更便宜。
另外,Scott Wilson 表示他們也正在密切觀望完全遠(yuǎn)程的開發(fā)環(huán)境,例如 Github Codespaces,以了解它們成熟后是否適合自己。
參考鏈接:
https://eng.lyft.com/scaling-productivity-on-microservices-at-lyft-part-1-a2f5d9a77813
https://eng.lyft.com/scaling-productivity-on-microservices-at-lyft-part-2-optimizing-for-fast-local-development-9f27a98b47ee
https://eng.lyft.com/scaling-productivity-on-microservices-at-lyft-part-3-extending-our-envoy-mesh-with-staging-fdaafafca82f
https://eng.lyft.com/scaling-productivity-on-microservices-at-lyft-part-4-gating-deploys-with-automated-acceptance-4417e0ebc274
https://github.com/readme/guides/developer-onboarding
了解更多軟件開發(fā)與相關(guān)領(lǐng)域知識,點擊訪問 InfoQ 官網(wǎng):https://www.infoq.cn/,獲取更多精彩內(nèi)容!






