解決Jenkins性能緩慢的問題

2022年1月22日21:04:57 發表評論 3,304 ℃

沒有什么比緩慢的持續集成系統更令人沮喪的了。它減慢了反饋循環并阻止代碼快速投入生產。雖然像使用性能更好的服務器可以為您爭取時間,但您最終必須投資于維持持續集成工作流程的成本。

Jenkins 是目前最流行的 CI/CD 工具之一,但隨著時間的推移,用戶經常會遇到滯后和響應緩慢問題。在本指南中,我將分享一些 Jenkins 性能問題的概述,以及一些無需升級硬件即可顯著提高性能的技巧。

1. 為什么 Jenkins 如此受歡迎的 CI/CD 選擇?

Jenkins 是一種基于 Java 的開源工具,成千上萬的開發人員在數十萬次安裝中使用它,使其成為最受歡迎的自動化集成工具。這種廣泛使用意味著很容易找到對 Jenkins 的支持和提示,但這并不是它如此廣泛使用的唯一原因。

Jenkins 為 CI 工作流程帶來了許多有趣的范例,包括:

更快的部署。在所有開發人員提交他們的代碼之后,一次測試和部署構建的日子已經一去不復返了。使用 Jenkins 的自動化 CI/CD 管道,無論何時開發人員提交代碼,它都會在一天中跨多個周期進行構建和測試。

可擴展的主代理架構。在大規模管理分布式構建時,Jenkins 可能是一個不錯的選擇。Jenkins 的主服務器是調度構建作業并將它們分配給代理(以前是從屬)執行的主服務器。此模式允許您在一臺或數百臺服務器上運行 Jenkins 以加快構建速度。

數以千計的插件:作為一個開源平臺,Jenkins 為其他開發人員構建的持續集成提供了大量插件。這允許您擴展基本功能,而無需在內部編寫或維護大量額外代碼。

2. 克服常見的 Jenkins 性能問題

隨著時間的推移,構建頻率的增加、并行運行的多個作業以及構建復雜性的增加可能會導致 Jenkins 出現性能問題。您的體驗可能會因您的使用場景而異,但一些常見問題包括:

每次運行時構建似乎都“卡在”特定步驟的“中斷”。

達到單個機器或主節點的內存限制。

CPU 瓶頸會減慢構建的特定部分。

插件或腳本中的錯誤或低效代碼。

由于這些問題可能是由多種根本原因引起的,因此很難概括解決方案,但 Jenkins 用戶可能想要研究一些事情。以下是一些最通用的方法,您可以提高 Jenkins 構建性能并限制上述問題的頻率。

2.1 避免在管道中使用復雜的 Groovy 腳本

Jenkins Groovy腳本控制臺在主節點上執行并直接使用主資源,例如CPU和存儲器。因此,建議您減少管道中 Groovy 腳本的數量和復雜性,轉而可以直接使用在每個代理上運行的插件。

在 Jenkins 中要避免的最常見的 Groovy 方法是 JsonSlurper、Jenkins.getInstance 和 HttpRequest。Jenkins在其博客上有更多關于可擴展管道代碼和要避免的操作的建議。

2.2 在主節點上保持最少的構建

Jenkins 的主節點位于應用程序運行的整個 CI/CD 流程的中心。因此,主節點上的構建數量會顯著影響資源使用。在主節點上保持較少的構建將為代理節點留出足夠的 CPU 和內存來安排和觸發作業。

您可以在工作中使用“限制項目可以運行的位置”選項。雖然 Jenkins 仍將在主節點上運行輕量級執行器,但您的重量級執行器將在代理節點上運行。

將主節點視為 Jenkins 的大腦。與代理不同,主節點不能被清除或替換。因此,為確保最佳 CI/CD 功能,請考慮對 Jenkins 進行一些性能調整,并將主節點從不必要的任務中解放出來。這將為您提供足夠的內存和 CPU 來有效調度和構建代理上的觸發器。

2.3 不要過渡 Jenkins 主節點插件安裝

DevOps 專業人員經常跨多個團隊和項目工作,以完成與 CI/CD 相關的任務。如果這是您的情況,請注意不要給單個 Jenkins master 帶來負擔。相反,創建多個主控。多個 master 將確保為 master 分配項目特定的資源,并且您還將避免插件沖突。

此外,不要設置可能在周期中的任何地方失敗的長時間構建,記住將構建分解為多個較小的作業。

2.4 輕松管理代理

在設置 Jenkins 時,正確設置代理很重要。您希望確保在時機成熟時,您可以輕松添加新代理或替換現有代理。為此,請考慮為代理創建虛擬機鏡像。您也可以考慮在 Kubernetes 或Amazon EKS等可擴展集群中的Docker 容器內運行 Jenkins。

使用具有通用性的代理也是一個好主意;一個代理應該運行多個不同的作業并最大限度地利用資源。

2.5 刪除構建歷史

一段時間后,Jenkins 構建可能會堆積起來,磁盤消耗可能會失控。開發人員經常忽略 Jenkins 的Discard Old Builds選項。設置指標,例如構建數量和保留構建和工件的天數,位于 Jenkins Log Rotation 菜單下。

與其讓舊版本累積并消耗文件系統,開發人員可以啟用Discard Old Builds并在 Jenkins 作業完成后享受自動資源使用清理。您還可以使用 G1 垃圾收集器來代替 Java 8 的默認Parallel GC,因為前者是一種服務器風格的垃圾收集器,具有較低的 GC 暫停時間。

也可以通過 Jenkins 命令行手動刪除構建,或者使用定期清理舊構建的cron 作業。您可以在此參考文章中找到丟棄舊構建數據的其他選項https://support.cloudbees.com/hc/en-us/articles/215549798-Deleting-Old-Builds-Best-Strategy-for-Cleanup-and-disk-space-management。

2.6 防止并行作業中的資源沖突

并行運行的作業可能需要獨占訪問端口或資源。這可能會導致沖突、構建失敗并進一步減慢 Jenkins 流水線。例如,如果您并行運行多個構建,則它們在訪問資源時很有可能發生沖突,例如 Postgres 的數據庫端口 5432。

Jenkins 提供Throttle Concurrent Builds插件來幫助調節 Jenkins 節點上的并發構建數量:

// Throttle a single operation
throttle(['test_1']) {
    node() {
        sh "sleep 100"
        echo "Done"
    }
}

2.7 控制堆大小

您想創建以性能為導向且永不會因內存泄漏或內存不足錯誤而失敗的 CI/CD 管道嗎?注意堆大小。隨著 Jenkins 構建數量的增長,如果不注意默認堆大小可能會導致內存不足錯誤。

大多數現代 Java 應用程序在啟動期間都使用最大堆大小配置。為了讓 Jenkins 順利運行,請將最大堆大小屬性降低到最大4 GB。您可以隨時間增加堆大小,具體取決于 Jenkins 構建。

要將堆大小設置為 4 GB:

/etc/default/jenkins

JAVA_ARGS="-Xmx4096m"

2.8 避免插件過載

Jenkins 擁有超過一千個可用插件,為其用戶提供了許多功能來增強他們的 CI/CD 管道。但是,在向管道添加插件和外部服務時,請牢記性能。將 Jenkins 與外部服務集成通常會減慢 Jenkins UI 并導致不利影響,例如代理丟失或斷開連接。

為了確定插件是否導致您的構建速度變慢,您可以嘗試在禁用所有或部分插件的情況下運行構建。逐漸添加每個返回以確定導致瓶頸的原因。找到導致性能問題的插件(或插件組合)后,您有幾個選擇:

通過搜索Jenkins Plugin Index找到替換插件。

通過檢查changelog來查看Jenkins 是否添加了對這個特性的原生支持。您可能必須升級 Jenkins 才能獲得最新功能,但這通常是提高性能的好主意。

用自定義腳本替換插件,記住這可能會引入新的性能問題。不過,如果您安裝一個復雜的插件,但只使用一兩個小功能,腳本可能會更有效。

如果您可以沒有它,請刪除該插件。有時這是一個值得的權衡。

3. 跟蹤 Jenkins 性能

當您開始調整 Jenkins 性能時,您可能有興趣添加一個插件來幫助監控和提高性能。例如,您可以利用Jenkins Monitoring 插件深入了解您的 CI/CD 管道,包括:

錯誤日志

CPU、內存和平均系統負載圖表

關于 HTTP 會話和 HTTP 響應時間的報告

構建時間和構建步驟的詳細統計信息

所有節點的聚合堆直方圖

解決Jenkins性能緩慢的問題

Jenkins 性能監控工具

這可以幫助您評估性能調整的有效性,并在您繼續改進 Jenkins 安裝時為您提供指導。

4.總結

Jenkins 的響應能力問題很常見,尤其是在處理較重的構建時。損壞的 Jenkins CI/CD 管道可能會拖延您的開發團隊并創建不必要的依賴項。本文中討論的技巧應該可以幫助您顯著提高 Jenkins CI/CD 管道的性能。

【騰訊云】云服務器、云數據庫、COS、CDN、短信等云產品特惠熱賣中

發表評論

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: