成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從 Kubernetes 學習大規模 Go 項目架構

開發 后端 云原生
如何在演進過程中持續優化模塊設計和代碼結構、提升迭代速度,是我們需要深入思考和探索的問題。

在嘗試使用 Go 構建一個具有高可擴展性、高可靠性和高可維護性的大型項目之前,先來看一下 Kubernetes 的項目結構,了解它是如何組織一系列用于容器編排的功能模塊的。

1. Kubernetes 代碼布局

下面是 Kubernetes 主目錄下的各個頂層目錄及其主要功能,隨后我們會逐一說明它們的用途。

  • api:存放接口協議;
  • build:與構建相關的腳本和代碼;
  • cmd:各個可執行程序的入口;
  • pkg:各組件的核心實現和導出包;
  • staging:臨時存放組件間相互依賴的代碼。

(1) api

該目錄存放 OpenAPI 和 Swagger 文件,包括 JSON 與 Protocol Buffer 的定義。

(2) build

該目錄包含構建 Kubernetes 項目所需的腳本,包括各組件的編譯和鏡像(例如 pause 鏡像)的構建。

(3) cmd

cmd 目錄存放用于生成可執行文件的 main 包源代碼。若需構建多個可執行程序,可將它們分別放在各自的子目錄下。以 Kubernetes 為例,cmd 目錄下有:

  • kube-proxy:負責網絡相關規則的實現 ;
  • kube-apiserver:暴露 Kubernetes API 并處理請求,為 Pod、ReplicaSet、Service 等資源提供增刪改查(CRUD)操作;
  • kube-controller-manager:kubernetes 資源控制器;
  • kube-scheduler:監控新建的 Pod,并為其選擇運行節點;
  • kubectl:訪問集群的命令行工具;

由此可見,像 kube-proxy、kube-apiserver 這樣的核心組件,都在這里有對應的可執行入口。

(4) pkg

pkg 目錄既包含項目自身的依賴,也包含對外導出的包。主要實現了各個核心組件的業務邏輯。

(5) staging

staging 目錄下的包通過符號鏈接映射到 k8s.io 下。首先,由于 Kubernetes 項目體量龐大,這樣做可以避免因倉庫分散帶來的開發障礙,使所有代碼能夠在一次 PR 中提交和審查。通過這種方式,既保證了模塊化,又保持了主倉庫的完整性。

同時,借助 go mod 中的replace指令,無需為每個依賴單獨打 tag,簡化了版本管理和發布流程。

如果不這么做,而是采用將 staging 目錄下的所有代碼拆分到獨立倉庫的方式,那么每次子倉庫代碼變化時,都需要先在子倉庫提交 PR、發布新 tag,然后在主倉庫中更新 go mod 依賴,才能繼續開發。這無疑會大幅增加整體開發成本。

因此,通過符號鏈接將 staging 目錄下的包關聯到主倉庫,能夠有效簡化版本管理和發布流程。

2. 與標準 Go 項目結構的對比

在 Go 中,internal目錄用于存放不對外導出的包。它的原則是在項目內部可以正常使用,但外部項目無法訪問。

然而,Kubernetes 并沒有internal 目錄。這是因為 Kubernetes 項目最早啟動于 2014 年左右,而 Go 1.4(于 2014 年底發布)才引入了 internal 目錄的概念。在 Kubernetes 早期開發階段,使用 internal 目錄的慣例尚未普及,且后來也未進行大規模重構來添加它。

此同時,Kubernetes 的設計目標之一就是模塊化與解耦。它通過明確的包組織和代碼結構來實現封裝,而無需依賴internal=目錄來限制包的訪問權限。

至此,我們已經了解了構建項目的標準頂層目錄結構。

Go 并不像 Java 那樣有一套統一的目錄框架。因此,不同項目往往各自為政。即使在同一個團隊中,也可能存在多種結構,這對新人理解項目是一大障礙。

正因為如此,協作往往會變得困難。統一的頂層目錄結構能讓我們快速定位代碼,并在接手項目時擁有標準的切入點,從而提高開發效率,減少協作中的定位混亂。

但僅僅有統一的目錄結構,就能構建完美的大型項目嗎?答案顯然是否定的。

單靠統一目錄結構,無法從根本上解決代碼隨著項目規模擴大而逐漸“衰變”“混亂”的問題。唯有遵循良好的設計原則,才能在項目不斷擴張時始終保持清晰的設計脈絡。

3. 聲明式設計理念

聲明式 API 貫穿 Kubernetes 的整個代碼設計,防止系統陷入過程式編程。

例如,當需要改變某個資源的狀態時,我們應告訴 K8s “期望的狀態”,而不是告訴它 “要執行哪些步驟”。這也是為何 kubelet 的滾動更新最終被廢棄:它的設計對更新 Pod 的整個過程進行了過度微觀管理。

通過告知 Kubernetes 目標狀態,kubelet 可以根據該狀態自主采取相應措施,而無需外部過度干預。

此時你可能會疑問:聲明式 API 在項目擴展時如何有助于保持模塊清晰?這不正是用戶在使用Kubernetes 時的感受嗎?它與內部設計有什么關系?

如果我們在設計接口時,將整個操作流程完全暴露給用戶,讓他們逐步干預 Pod 更新的每個步驟,那么我們設計的模塊就不可避免地演變為過程式。這會導致代碼模塊與大量用戶操作高度耦合,難以保持清晰。

而采用聲明式 API 后,我們僅向 K8s 傳達期望狀態,集群內部的多個組件便能協同工作,最終實現該狀態。用戶無需關心內部的更新細節。更重要的是,當需要增加新的協作插件時,只需新增相應模塊,無需再對外暴露更多用戶操作的 API。

以 cAdvisor 為例,它獨立監控 Kubernetes 部署的資源并收集容器指標,不依賴外部組件。控制器再將這些指標與用戶聲明的目標進行對比,以判斷是否滿足擴容或縮容條件。

由于各模塊相互獨立,cAdvisor 只需專注于采集并返回監控數據,而無需關心這些數據是用于觀測還是自動伸縮。

這也是設計不同任務組件時的關鍵原則:

  • 明確要達成的需求;
  • 傳遞信息時只關注輸入與輸出;
  • 內部實現則封裝起來,不向外暴露,讓外部業務調用保持盡可能簡單。

4. 避免過度設計

過度的工程設計往往比設計不足更糟糕。

Kubernetes 的最早版本是 0.4。在網絡方面,官方的實現方案是讓 GCE 運行 Salt 腳本來創建網橋,而在其他環境下推薦使用 Flannel 和 OVS。

隨著 Kubernetes 的發展,Flannel 在某些場景下已不足以滿足需求。大約在 2015 年,社區中出現了 Calico 和 Weave,基本解決了網絡問題。于是 Kubernetes 就不用再花力氣自己去做網絡實現,而是引入了 CNI 以標準化網絡插件。

很顯然,Kubernetes 并不是一開始就設計得十分完美,而是在新問題出現時,才逐步引入新的設計來適應不同環境的變化。

在項目啟動初期,依賴關系相對清晰,所以工程設計階段一般不會出現循環依賴。但隨著項目規模增長,這些問題會逐漸顯現。產品功能的不斷演進,會導致代碼設計中出現互相引用。

即便我們在項目啟動前盡力去了解所有業務背景和待解問題,隨著產品功能的變化和程序的迭代,總會出現新的問題。我們能做的,是關注模塊設計和依賴管理,盡可能保持功能內聚,并在后續添加抽象時,避免對已有代碼進行大規模“重構”式的改動。

為“可擴展性”過度設計系統、只為設計而設計,反而會成為未來變更的絆腳石。

下面用一個電商業務場景來說明設計演進。

初始階段,系統包含兩個模塊:

  • 訂單模塊: 負責創建訂單、支付、狀態更新等,依賴用戶模塊獲取用戶信息(如收貨地址、聯系方式等)。
  • 用戶模塊: 負責管理用戶信息、注冊、登錄,存儲用戶數據,不依賴訂單模塊。

在這個階段,依賴關系是單向的:訂單模塊 → 用戶模塊。此時無需過度抽象,過早的設計投入并不劃算;許多項目并不知道是否能夠成功,從產品發布角度看,投入過多設計成本并不可行,而且若產品定位發生劇烈變化,過度設計會成為后續修改的障礙。

隨著需求演變,出現了個性化推薦的需求:平臺需要根據用戶的購買歷史(訂單記錄)向用戶推薦商品。

為實現個性化推薦,用戶模塊需要調用訂單模塊的 API 來獲取用戶的歷史訂單。此時依賴關系變為:

訂單模塊 依賴 用戶模塊(獲取用戶信息)

用戶模塊 依賴 訂單模塊(獲取訂單歷史)

這就形成了循環依賴。為了解決它,可以考慮責任拆分:引入一個新的“推薦模塊”,專門處理個性化推薦邏輯。推薦模塊分別從用戶模塊和訂單模塊獲取數據,避免它們之間直接依賴。通過提取模塊,我們解決了用戶與訂單模塊之間的耦合。

然而,新需求又來了:在促銷活動期間,用戶購買特定活動商品時,產品經理希望推薦模塊能實時感知此類訂單,并推薦相關的促銷商品(例如用戶買了打折運動手表,就推薦打折藍牙運動耳機,以提高復購率)。

在這個場景中,讓訂單模塊直接調用推薦模塊來傳遞數據顯然不合適:推薦模塊已經依賴訂單模塊獲取用戶購買數據,如果再讓訂單模塊調用推薦模塊,就又會產生循環依賴。

那么,推薦模塊該如何快速感知訂單變化?這就需要事件驅動架構。

  • 當用戶下單時,訂單模塊觸發一個事件;
  • 推薦模塊訂閱與用戶訂單相關的事件;
  • 通過事件傳遞數據后,推薦模塊立即觸發模型重訓練,并向用戶推薦相關商品。

從上述例子可見,企業級應用的一大挑戰是:業務域建模。在建模過程中,需要隨著需求的持續演進,不斷優化設計。

上面提到的用戶、訂單與推薦模塊,也是大多數 To-C(面向消費者)產品演進中的常見場景。如何在演進過程中持續優化模塊設計和代碼結構、提升迭代速度,是我們需要深入思考和探索的問題。

5. 總結

讓我們回顧下本文內容:

  • 在構建大型項目時,統一的目錄結構可以提高協作效率,但良好的設計原則才是在項目不斷增長時保持清晰性和可擴展性的關鍵;
  • Kubernetes 的聲明式 API 能讓模塊保持獨立,避免過程式編程的陷阱;
  • 項目設計應根據實際需求逐步演進,避免過度設計;
  • 著重模塊職責和依賴的合理拆分,并使用事件驅動的方法解決模塊間的耦合。
責任編輯:趙寧寧 來源: 令飛編程
相關推薦

2020-10-15 19:22:09

Menger機器學習強化學習

2023-03-19 23:31:32

OpenKruise項目自動化

2019-04-02 08:00:39

閃存架構共享

2009-03-20 09:49:00

負載均衡CDN網站架構

2021-03-26 09:49:22

架構并行處理

2017-06-03 16:34:22

云服務數據中心公有云

2022-06-09 13:45:18

vivoK8S集群Kubernetes

2023-11-24 13:24:14

CIOOptus

2017-10-09 16:51:34

機器學習No Free Lun

2015-06-12 09:58:51

2022-07-07 11:00:09

美團模型實踐

2016-01-29 20:23:23

華為

2017-04-26 13:30:24

爬蟲數據采集數據存儲

2009-04-09 09:32:00

VoWLANWLAN

2010-09-01 15:16:49

WLAN交換機結構

2020-02-17 08:00:02

云計算云開發Kubernetes

2024-04-30 07:00:00

公共云云策略云計算

2015-09-22 09:43:31

2017-11-06 10:15:36

機器學習框架Tensorflow

2023-05-26 08:39:44

深度學習Alluxio
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 人人人人人爽 | 高清av一区 | 欧美aaa级 | 一区二区三区视频在线观看 | 一区二区中文字幕 | 国产精品毛片一区二区三区 | 中文字幕综合 | 在线观看中文字幕 | 亚洲天堂中文字幕 | 一区二区三区视频 | 成人午夜视频在线观看 | 久久精品亚洲精品国产欧美 | 欧美亚洲国产一区二区三区 | 午夜精品一区二区三区在线 | 成人欧美一区二区三区在线播放 | 久色一区 | 亚洲国产精品人人爽夜夜爽 | 亚洲国产成人精品女人 | 天天爽天天干 | 蜜臀网 | 成人中文字幕av | 免费精品一区 | 日韩国产黄色片 | 国产成人一区二区三区久久久 | 成人精品鲁一区一区二区 | 日韩中文字幕在线视频观看 | 999视频 | 中文字幕在线观看 | a视频在线播放 | 成人影院一区二区三区 | 久久综合伊人一区二区三 | h片在线观看网站 | 久久精品av麻豆的观看方式 | 成人免费视频观看视频 | 欧美理伦片在线播放 | 欧美日高清| 日韩国产免费观看 | 国产成人精品一区二三区在线观看 | 日韩毛片在线免费观看 | 日韩毛片网 | 99免费在线视频 |