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

系統(tǒng)成功率99.99%+,美團CI/CD流水線引擎演進實踐

原創(chuàng) 精選
開發(fā) 新聞
本文主要介紹美團在自研引擎建設層面遇到的挑戰(zhàn)以及解決方案,希望對大家能夠有所幫助或啟發(fā)。

作者:耿杰 春暉 志遠

經(jīng)過近3年的建設打磨,美團流水線引擎完成了服務端的基建統(tǒng)一,每日支撐近十萬次的流水線執(zhí)行量,系統(tǒng)成功率保持在99.99%以上。

一、背景

持續(xù)交付這個概念最早在2006年敏捷大會上被提出,經(jīng)過多年的發(fā)展,目前已成為很多技術團隊提升研發(fā)效能的必經(jīng)之路。通過建設部署流水線,打通從代碼開發(fā)到功能交付的整個環(huán)節(jié),以自動化的方式完成構建、測試、集成、發(fā)布等一系列行為,最終實現(xiàn)向用戶持續(xù)高效地交付價值。

流水線引擎作為支撐部署流水線的底座,它的好壞直接影響著部署流水線建設的水平。業(yè)界通常的做法是通過Jenkins、GitlabCI等開源工具(或公有云產品)進行搭建,這是一條能幫助業(yè)務快速落地持續(xù)交付的道路,美團早期也是采用搭建Jenkins的方式來快速支撐業(yè)務。

但隨著越來越多業(yè)務開始做持續(xù)交付的建設,這種“短平快”方式的弊端逐漸顯現(xiàn)。比如,工具建設沒有統(tǒng)一的標準,各業(yè)務都需要去了解整個工具鏈的細節(jié),建設成本高、水平參差不齊,很少有業(yè)務能搭建完整的部署流水線。同時,業(yè)務每天的構建量都在快速增長,逐漸超過Jenkins等開源工具所能承受的極限,在交付高峰期任務嚴重排隊、服務不可用現(xiàn)象頻出,嚴重影響著業(yè)務交付的順暢度。

美團在流水線引擎的建設層面大概經(jīng)歷了幾個階段。在2019年以前,主要圍繞Jenkins進行優(yōu)化,2019年開始正式立項打造自研的流水線引擎,大致的歷程如下:

第一階段(2014-2015):搭建Jenkins統(tǒng)一集群,解決業(yè)務接入的通用問題(如單點登錄、代碼倉庫集成、消息通知、執(zhí)行機的動態(tài)擴縮等),降低業(yè)務的建設成本。

  • 第二階段(2016-2018):拆分多個Jenkins集群,解決業(yè)務增長導致單集群性能瓶頸。最多時有十幾個集群,這些集群通常是按業(yè)務線維度劃分,并由業(yè)務自行建設。但隨著時間的推移,集群的拆分管理難度越來越大,Jenkins安全隱患頻出,對平臺方造成了很大的運維負擔。
  • 第三階段(2019-至今):為了徹底解決引擎單機瓶頸和工具重復建設問題,我們開始自研分布式流水線引擎(美團內部項目名稱為Pipeline),并逐步收斂各業(yè)務依賴的底層基建。

經(jīng)過3年左右的建設打磨,流水線引擎完成了服務端的基建統(tǒng)一,涵蓋到店、到家、大眾點評、美團優(yōu)選、美團平臺、自動配送車、基礎研發(fā)平臺等幾乎所有的業(yè)務,支持Java、C++、NodeJS、Golang等多種語言。在性能和穩(wěn)定性方面,引擎每日支撐近十萬次的流水線執(zhí)行量(作業(yè)調度峰值每小時達上萬次),系統(tǒng)成功率保持在99.99%以上(排除業(yè)務代碼自身原因和第三方工具的問題)。

下面我們主要介紹下我們在自研引擎建設上遇到的挑戰(zhàn)以及對應的解決方案。

二、問題及思路

1、業(yè)務介紹

1)什么是流水線

我們可以把流水線的執(zhí)行看作是對代碼一步步加工,最終交付到線上的過程。根據(jù)業(yè)務定義的順序關系,依次執(zhí)行相應的加工或質量校驗行為(如構建、代碼掃描、接口測試、部署工具等),整個執(zhí)行過程類似一個有向無環(huán)圖。

圖1 流水線概念

2)基本概念

  • 組件:出于代碼復用和業(yè)務共享的考慮,我們將某一工具的操作行為封裝成一個組件,表示對于一項具體的加工或校驗行為。通過組件方式,業(yè)務可以便捷地使用已集成的質量工具(如靜態(tài)代碼掃描、安全漏洞分析等),減少在同一工具上的重復開發(fā)成本;對于不滿足需求的場景,業(yè)務可以自定義一個新的組件。
  • 組件作業(yè):表示組件的一次運行實例。
  • 資源:為組件作業(yè)分配的一個可執(zhí)行環(huán)境。
  • 流水線編排:表示流水線中不同組件執(zhí)行的先后順序。
  • 引擎:負責調度所有的組件作業(yè),為其分配相應的執(zhí)行資源,保證流水線執(zhí)行按預期完成。

2、主要挑戰(zhàn)

1)調度效率瓶頸

對調度時間相對敏感,流水線大部分是短時作業(yè)(作業(yè)持續(xù)數(shù)十秒到分鐘不等),如果調度時間過長,業(yè)務能明顯感知到流水線執(zhí)行變慢了。我們需要保證作業(yè)調度時間在一個可控的范圍內,避免出現(xiàn)調度瓶頸。

  • 從業(yè)務場景考慮,調度邏輯存在一定的業(yè)務復雜性(如組件串并行判斷、優(yōu)先級搶占、降級跳過、復用上一次結果等),不僅僅是作業(yè)與資源的匹配計算,作業(yè)調度耗時存在一定的業(yè)務開銷。
  • 引擎支撐公司每天近十萬次的執(zhí)行量,峰值量情況下,并發(fā)調度的作業(yè)量大,常見的開源工具(Jenkins/GitLab CI/Tekton等)都是采用單體調度模式,作業(yè)是串行調度的,容易出現(xiàn)調度瓶頸。

2)資源分配問題

對于作業(yè)系統(tǒng)來說,作業(yè)數(shù)通常都是大于資源數(shù)的(真實部署情況,資源不是無限的),作業(yè)積壓是系統(tǒng)設計時必須考慮的問題。如何在有限的資源下,盡可能提高作業(yè)的吞吐能力,同時降低在資源不足情況時造成對核心業(yè)務場景的影響。

  • 如果只依靠動態(tài)擴容,容易出現(xiàn)資源不足時無法擴容、作業(yè)排隊等待的情況。特別是對于依賴流水線做研發(fā)卡控的業(yè)務,這會直接阻塞業(yè)務的上線流程。
  • 出于執(zhí)行耗時的考慮,大部分資源采用預部署的方式,縮短資源申請和應用啟動的準備時間。而對于預部署的資源,如何進行有效劃分,既保證每類資源都有一定配額,同時也避免出現(xiàn)部分資源利用率過低,影響作業(yè)整體的吞吐能力。
  • 不是所有工具的執(zhí)行資源都由引擎管理(如發(fā)布系統(tǒng),部署任務的資源管理是單獨的),在作業(yè)的資源分配上,還需要考慮不同的資源管理方式。

3)工具差異化問題

公司內不同業(yè)務的差異化大,涉及的質效類工具眾多,如何設計一個合適的插件化架構,滿足不同工具的接入需求。

  • 不同工具實現(xiàn)形式差異化大,有些工具有獨立的平臺,可以通過接口方式進行集成,有些僅僅是一段代碼片段,還需要提供相應的運行環(huán)境。面對不同的接入形態(tài),引擎如何屏蔽不同工具帶來的差異,使業(yè)務在編排流水線時不用關注到工具的實現(xiàn)細節(jié)。
  • 隨著業(yè)務場景的不斷豐富,組件執(zhí)行還會涉及人工交互(審批場景)、支持重試、異步處理、故障恢復等能力,這些能力的擴展如何盡可能減少對系統(tǒng)的沖擊,降低實現(xiàn)的復雜度。

3、解決思路

1)拆分調度決策與資源分配,解決調度效率瓶頸

從上述分析,一個作業(yè)的實際調度耗時 = 單個作業(yè)的調度耗時 * 待調度的作業(yè)數(shù)。因為單個作業(yè)的調度耗時會受具體的業(yè)務邏輯影響,不確定性大,優(yōu)化空間有限。而串行調度問題相對明確,在作業(yè)調度時間和數(shù)量不可控的情況下,是一個合適的優(yōu)化方向。

關于串行調度,業(yè)界常見的做法是按照業(yè)務線維度拆分多個集群,分攤總的調度壓力。但這種方式存在的問題是資源分配不具備靈活性,很容易出現(xiàn)資源的分配不均,在整體資源不足時,無法從全局上考慮高優(yōu)作業(yè)的資源分配。并且,多集群管理(新增集群/拆分現(xiàn)有集群)也是不小的運維負擔。

進一步分析,串行調度主要是為了避免資源競爭問題,獲得相對最優(yōu)的資源。這對于流水線場景(作業(yè)量大于資源量且都是短時作業(yè)),資源最優(yōu)解不是強訴求。并且,資源量的并發(fā)度相對作業(yè)量更可控,根據(jù)作業(yè)執(zhí)行快慢不同,我們通過主動拉取作業(yè)的方式,控制拉取的數(shù)量和頻率,從而有效降低了資源競爭的情況。

最終,我們在設計上采取了調度決策與資源分配分離的模式:

  • 調度決策:負責計算出可以調度的作業(yè),提交決策,等待合適的資源來執(zhí)行。該模塊具體水平擴展,分擔調度決策的壓力。
  • 資源分配:負責維護作業(yè)與資源的關系,通過主動拉取作業(yè)的方式,資源可以向任意的實例拉取作業(yè),取消了原先串行分配資源的單點限制。

在這種模式下,作業(yè)調度、資源分配都具備水平擴展能力,擁有更高的性能和系統(tǒng)可用性。也利于作業(yè)調度的邏輯能夠獨立演進,便于開發(fā)、測試以及灰度上線。

2)引入資源池管理模式,實現(xiàn)資源的靈活分配

考慮到不是所有資源都由引擎管理,我們引入資源池的概念來屏蔽不同資源方式的差異,每個資源池代表一類資源的集合,不同資源池的資源管理方式可以是多樣化的。通過該方式,我們將資源分配的問題簡化為作業(yè)與資源池的匹配問題,根據(jù)作業(yè)的實際情況,合理設置不同的資源池大小,并配合監(jiān)控手段對資源池進行動態(tài)調整。

在具體措施上,我們選擇“標簽”的方式建立作業(yè)與資源池的匹配關系,通過從作業(yè)與資源兩個維度來滿足上述條件。

  • 在作業(yè)端,作業(yè)基于標簽屬性拆分到不同的作業(yè)隊列,并引入優(yōu)先級概念,保證每個隊列中作業(yè)按優(yōu)先級高低被拉取到,避免在積壓時,高優(yōu)作業(yè)排在后面無法被及時處理,阻塞業(yè)務研發(fā)流程。
  • 在資源端,結合資源的實際場景,提供三種不同的資源池管理方式,以解決不同資源類型的配額和利用率問題。

a. 預置的公共資源,這部分資源會提前在資源池上擴容出來,主要應對業(yè)務高頻使用的且對時間敏感的組件作業(yè)。在資源配額和利用率上,根據(jù)資源池的歷史情況和實時監(jiān)控,動態(tài)調整不同資源池的大小。

b. 按需使用的資源,主要針對公共資源環(huán)境不滿足的情況,業(yè)務需要自定義資源環(huán)境,考慮到這部分作業(yè)的體量不大,直接采用實時擴容的方式,相比預置資源的方式,可以獲得更好的資源利用率。

c. 外部平臺的資源,這些資源的管理平臺方比我們更有經(jīng)驗,平臺方通過控制向引擎拉取作業(yè)的頻率和數(shù)量,自行管理作業(yè)的吞吐情況。

3)引入組件的分層設計,滿足工具差異化需求

為了保持工具接入的自由度,引擎提供了作業(yè)維度最基本的操作接口(拉取作業(yè)、查詢作業(yè)狀態(tài)、上報作業(yè)結果),不同工具可以根據(jù)作業(yè)接口形式實現(xiàn)定制化的組件開發(fā)。

組件開發(fā)主要涉及①實現(xiàn)業(yè)務邏輯和②確定交付方式兩部分工作,而與引擎的系統(tǒng)交互相對是標準的。我們根據(jù)組件執(zhí)行過程進行分層設計,拆分出業(yè)務邏輯、系統(tǒng)交互與執(zhí)行資源三層。在向引擎屏蔽工具實現(xiàn)細節(jié)的同時,可以更好地滿足多樣化的接入場景。

  • 系統(tǒng)交互層,該層相對組件開發(fā)者是透明的,根據(jù)引擎提供的接口制定統(tǒng)一的流程交互標準,以向引擎屏蔽不同組件的實現(xiàn)差異。
  • 執(zhí)行資源層,主要解決工具運行方式的差異化,通過支持多種組件交付形式(如鏡像、插件安裝、獨立服務)滿足工具與引擎的不同集成方式。
  • 業(yè)務邏輯層,針對業(yè)務不同的開發(fā)場景,采用多種適配器的選擇,來滿足業(yè)務不同的開發(fā)訴求。

三、整體架構

圖片

圖2 流水線架構

  • 觸發(fā)器:作為流水線的觸發(fā)入口,管理多種觸發(fā)源及觸發(fā)規(guī)則(Pull Request、Git Push、API 觸發(fā)、定時觸發(fā)等)。
  • 任務中心:管理流水線構建過程中的運行實例,提供流水線運行、中止、重試、組件作業(yè)結果上報等操作。
  • 決策者:對所有等待調度的作業(yè)進行決策,并將決策結果同步給任務中心,由任務中心進行作業(yè)狀態(tài)的變更。
  • Worker:負責向任務中心拉取可執(zhí)行的作業(yè),并為作業(yè)分配具體的執(zhí)行資源。
  • 組件SDK:作為執(zhí)行組件業(yè)務邏輯的殼,負責真正調起組件,完成組件初始化與狀態(tài)同步的系統(tǒng)交互。

四、核心設計點

1、作業(yè)調度設計

1)調度過程

下面,我們以一個簡單的流水線調度示例(源碼檢出 - [并行:代碼掃描,構建] - 部署),來介紹調度設計中各模塊的協(xié)作過程。

圖片

圖3 調度過程

大致邏輯如下:

①當觸發(fā)流水線構建后,系統(tǒng)會在任務中心創(chuàng)建該編排所要執(zhí)行的所有組件作業(yè)。并且將作業(yè)狀態(tài)的變化以事件方式通知決策者進行決策。

②決策者接收決策事件,根據(jù)決策算法計算出可被調度的作業(yè),向任務中心提交作業(yè)的狀態(tài)變更請求。

③任務中心接收決策請求,完成作業(yè)狀態(tài)變更(作業(yè)狀態(tài)變更為已決策),同時加入相應的等待隊列。

④Worker 通過長輪詢方式拉取到和自己匹配的等待隊列的作業(yè),開始執(zhí)行作業(yè),執(zhí)行完成后將結果上報給任務中心。

⑤任務中心根據(jù)Worker上報的作業(yè)執(zhí)行結果變更作業(yè)狀態(tài),同時向決策者發(fā)起下一輪決策。

⑥以此反復,直至流水線下所有作業(yè)都已執(zhí)行完成或出現(xiàn)作業(yè)失敗的情況,對流水線進行最終決策,結束本次執(zhí)行。

整個過程中,任務中心作為一個分布式存儲服務,統(tǒng)一維護流水線和作業(yè)的狀態(tài)信息,以API方式與其他模塊進行交互。而決策者和Worker通過監(jiān)聽作業(yè)狀態(tài)的變化執(zhí)行相應的邏輯。

2)作業(yè)狀態(tài)流轉

下面是一個作業(yè)完整的狀態(tài)機,我們通過作業(yè)決策、拉取、ACK以及結果上報一系列事件,最終完成作業(yè)從初始狀態(tài)向完結狀態(tài)的流轉過程。

狀態(tài)機在接收某種狀態(tài)轉移的事件(Event)后,將當前狀態(tài)轉移至下一個狀態(tài)(Transition),并執(zhí)行相應的轉移動作(Action)。

圖片

圖4 狀態(tài)機

在實際場景中,由于調度過程涉及鏈路長、各環(huán)節(jié)穩(wěn)定性無法完全保證,容易產生因異常情況導致狀態(tài)不流轉的情況。為此,在設計上利用數(shù)據(jù)庫保證狀態(tài)變更的正確性,同時為非完結狀態(tài)作業(yè)設立相應的補償機制,確保任一環(huán)節(jié)異常后作業(yè)可以恢復正確流轉。

我們重點從作業(yè)決策和作業(yè)拉取這兩個關鍵過程來看狀態(tài)流轉過程可能出現(xiàn)的問題,以及在設計上是如何解決的。

①作業(yè)決策過程:任務中心接收調度作業(yè)的決策,將可調度的作業(yè)從unstart變?yōu)閜ending狀態(tài),同時將作業(yè)加入等待隊列,等待被拉取。

圖片

圖5 狀態(tài)機-決策

  • 未收到?jīng)Q策事件:由于決策者服務自身的問題或網(wǎng)絡原因,導致決策事件的請求失敗,作業(yè)長時間處于未調度狀態(tài)。

解決方案:引入定時監(jiān)測的機制,對于無過程狀態(tài)作業(yè)且處于未完結狀態(tài)的流水線進行重新決策,避免決策服務短時間異常導致決策失敗。

  • 重復決策:由于網(wǎng)絡延遲、消息重試現(xiàn)象可能出現(xiàn)多個決策者同時決策同一個作業(yè),產生作業(yè)轉移的并發(fā)問題。

解決方案:增加pending的狀態(tài)表示作業(yè)已被決策到,并通過數(shù)據(jù)庫樂觀鎖機制進行狀態(tài)變更,保證僅有一個決策會真正生效。

  • 狀態(tài)變更過程異常:由于存在異構數(shù)據(jù)庫,狀態(tài)變更和加入隊列可能存在數(shù)據(jù)不一致,導致作業(yè)無法被正常調度。

解決方案:采用最終一致性的方案,允許調度的短暫延遲。采用先變更數(shù)據(jù)庫,再加入隊列的操作順序。利用補償機制,定時監(jiān)測隊列隊首的作業(yè)信息,若pending狀態(tài)下的作業(yè)有早于隊首作業(yè)的,進行重新入隊操作。

②作業(yè)拉取過程:任務中心根據(jù)Worker拉取作業(yè)的事件請求,從等待隊列中獲取待調度作業(yè),將作業(yè)的狀態(tài)從pending變更為scheduled,并返回給Worker。

圖片

圖6 狀態(tài)機-ACK

  • 作業(yè)丟失問題:這里存在兩種情況,①作業(yè)從隊列中移除,但在狀態(tài)將要變更時異常了;②作業(yè)從隊列中移除,也正確變更了狀態(tài)。但由于poll請求連接超時,未正常返回給Worker。

解決方案:前者通過作業(yè)決策環(huán)節(jié)中對pending狀態(tài)的作業(yè)補償機制,重新加入隊列;后者對于狀態(tài)已變更的情況,已調度的作業(yè)增加ACK機制,若超時未確認,狀態(tài)會流轉回pending狀態(tài),等待被重新拉取。

  • 作業(yè)被多個Worker拉取:Worker在接收到作業(yè)后,遇到長時間的GC,導致狀態(tài)流轉回pending狀態(tài),在Worker恢復后,可能出現(xiàn)作業(yè)已分配到另一個Worker上。

解決方案:通過數(shù)據(jù)庫樂觀鎖機制保證僅有一個Worker更新成功,并記錄作業(yè)與Worker的關系,便于對作業(yè)進行中止以及Worker故障后的恢復操作。

3)決策過程

決策過程是從所有未啟動的作業(yè)中篩選出可以被調度的作業(yè),通過一定的順序將其提交給任務中心,等待被資源拉取的過程。整個篩選過程可以分為串并行順序、條件過濾、優(yōu)先級設置三部分。

圖片

圖7 決策過程

  • 串并行順序:相對于DAG中復雜的尋路場景,流水線場景比較明確,是將代碼逐步加工驗證,通過開發(fā)、測試、集成、上線等一系列階段的過程。階段間是嚴格串行的,階段內出于執(zhí)行效率的考慮,會存在串并行執(zhí)行的情況。這里通過模型設計,將DAG的調度問題轉變成作業(yè)的先后次序問題,引入run order概念,為每個組件作業(yè)設置具體的執(zhí)行次序,根據(jù)當前已執(zhí)行作業(yè)的次序,快速篩選出下一批次序僅大于當前的作業(yè),若并行執(zhí)行,僅需將作業(yè)的次序設置成相同即可。

圖片

圖8 串并行決策

  • 條件過濾:隨著業(yè)務場景擴展,不是所有的作業(yè)都需要調度資源,進行真正的執(zhí)行。如某類耗時的組件,在代碼和組件參數(shù)都不變的情況下,可以直接復用上一次的執(zhí)行結果,或者在系統(tǒng)層面針對某類工具異常時進行組件跳過的降級操作。針對這類情況,在作業(yè)真正提交給任務中心之前,會增加一層條件判斷(條件分為全局設置的系統(tǒng)條件以及用戶條件),這些條件以責任鏈形式進行依次匹配過濾,根據(jù)匹配到的條件單獨向任務中心提交決策。
  • 優(yōu)先級設置:從系統(tǒng)全局考慮,在作業(yè)出現(xiàn)積壓時,業(yè)務更關心核心場景下整條流水線是否能盡早執(zhí)行完成,而不是單個作業(yè)的排隊情況。所以,在優(yōu)先級設置上除了基于時間戳的相對公平策略外,引入流水線類型的權重值(如發(fā)布流水線>自測流水線;人工觸發(fā)>定時執(zhí)行),保證核心場景流水線相關作業(yè)能夠盡早被調度到。

2、資源池劃分設計

1)整體方案

我們采用多隊列的設計,結合標簽建立作業(yè)隊列與資源池的匹配關系,以保障不同隊列資源的有效劃分,在出現(xiàn)隊列積壓、資源池故障、無可擴資源等情況時,最大限度地降低影響范圍,避免所有作業(yè)全局排隊等待的現(xiàn)象。

圖片

圖9 資源池架構

2)模型關系

圖片

圖10 資源池模型對象

①作業(yè)隊列與標簽的關系:隊列與標簽采用1對1的關系,降低業(yè)務理解和運維成本。

  • 當隊列積壓時,能快速定位到某個標簽沒資源了。
  • 標簽資源不足時,也能快速判斷影響的具體隊列情況。

②標簽與資源池的關系:標簽和資源池采用多對多的關系,主要從資源整體利用率和對核心隊列的資源可用性保障考慮。

  • 對于一些作業(yè)量較少的隊列,單獨分配一個資源池會造成大部分時間資源是空閑狀態(tài),資源利用率低。我們通過給資源池打多標簽的方式,既保證了隊列有一定的資源配額,同時也能處理其他標簽的作業(yè),提高資源的利用率。
  • 對于核心場景的隊列,通常標簽資源會分配到多個資源池上,保證資源的一定冗余,同時也降低單個資源池整體故障帶來的影響。

3)標簽設計

標簽的目的是建立資源(池)與作業(yè)(隊列)的匹配關系。在設計上,為便于標簽管理和后期維護,我們采用二維標簽的形式,通過組件和流水線兩個維度,共同決定一個作業(yè)所屬標簽及對應的資源。

  • 第一維度:組件維度,對資源做通用劃分。結合組件的業(yè)務覆蓋情況、作業(yè)執(zhí)行量、對機器和環(huán)境的特殊要求(如SSD、Dev環(huán)境等),對需要獨立資源的組件進行打標,劃分出不同的公共資源池(每個公共資源池執(zhí)行一類或多類組件作業(yè)),在引擎層面統(tǒng)一分配,保證所有作業(yè)都有可正常運行。
  • 第二維度:流水線維度,根據(jù)業(yè)務場景進行劃分。結合業(yè)務對資源隔離/作業(yè)積壓敏感度的訴求,按需進行劃分。有些希望資源完全獨立的業(yè)務,會從所有的公共資源池進行切分;有些僅對部分核心場景下的資源需要保障,根據(jù)鏈路上涉及的組件,選擇性地從部分公共資源池進行劃分,實現(xiàn)業(yè)務隔離和資源利用率的平衡。

注:每個維度都會設一個other的默認值用來兜底,用于處理無資源劃分需求的場景。

圖片

圖11 標簽設計

4)隊列拆分設計

根據(jù)作業(yè)所屬標簽不同拆分出多個隊列,保證每個隊列的獨立性,降低作業(yè)積壓的影響范圍。整個拆分過程可以分為入隊和出隊兩部分:

  • 入隊過程:通過計算作業(yè)在組件和流水線兩個維度的屬性值,來確定作業(yè)對應的標簽。結合模型關系中標簽與隊列(1對1)的關系,為每個標簽按需創(chuàng)建一個隊列,存儲該標簽作業(yè),不同隊列間作業(yè)做排他處理,簡化出隊的實現(xiàn)復雜度。
  • 出隊過程:隊列拆分后,因為標簽和資源池(多對多)的關系,資源池的一次作業(yè)拉取請求往往會涉及多個隊列。出于拉取效率的考慮,采用輪詢的方式依次對單隊列進行出隊操作,直到達到該次請求的作業(yè)數(shù)上限或所有可選隊列為空時返回結果。該方式可以避免同時對多個隊列加鎖,并且在前置環(huán)節(jié)會對多標簽進行隨機排序,降低多個請求同時操作一個隊列的競爭概率。

圖片

圖12 隊列拉取設計

3、組件分層設計

1)分層架構

圖片

圖13 組件架構設計

  • 業(yè)務層:引入適配層,滿足組件開發(fā)中多樣化的需求場景,同時避免上層差異污染到下層。
  • 系統(tǒng)交互層:設立統(tǒng)一的流程標準,保證引擎和組件交互過程的一致性,便于統(tǒng)一處理非功能性的系統(tǒng)優(yōu)化。
  • 執(zhí)行資源層:提供多種資源策略,向上層屏蔽不同資源類型的差異。

2)標準的交互流程設計

在系統(tǒng)交互層,組件與引擎交互的過程中,有兩個環(huán)節(jié)是確定的,①組件作業(yè)的狀態(tài)機流轉,這涉及到組件執(zhí)行的整個生命周期管理,若允許存在不同的狀態(tài)流轉關系,整個管理過程會十分混亂;②引擎對外提供的接口范圍,從服務間解耦的角度,對外提供的接口主要是組件作業(yè)維度的接口操作,不應該耦合任何組件內部的實現(xiàn)細節(jié)。

結合作業(yè)狀態(tài)機 + 引擎提供的接口,確定了組件執(zhí)行基本的系統(tǒng)交互流程。利用模版模式,抽象出init()、run()、queryResult()、uploadArtifacts() 等必要方法供業(yè)務實現(xiàn),整個交互流程則由系統(tǒng)統(tǒng)一處理,業(yè)務無需關心。

圖片

圖14 組件標準流程設計

3)擴展基礎能力

組件執(zhí)行除了正常的執(zhí)行流程外,隨著業(yè)務場景的豐富,還會涉及組件中止、回調(人工審批場景)等操作,這些操作的引入勢必會改變原先的交互流程。為了不增加額外的交互復雜度,在拉取作業(yè)環(huán)節(jié),增加作業(yè)的事件類型(運行、中止、回調等事件),Worker根據(jù)拉取到的不同事件,執(zhí)行相應的擴展邏輯。同時,引入新的擴展也不會影響到已有的交互流程。

圖片

圖15 組件擴展能力設計

基于上述擴展,我們可能更好地將一些通用能力下沉到Daemon Thread層。如結果查詢流程,通過守護線程的方式,取消了原先同步等待的查詢限制,這對于需要異步化處理的場景(如組件作業(yè)邏輯已執(zhí)行完,僅在等待外部平臺接口返回結果)可以提前釋放資源,提高資源執(zhí)行的利用率。并且,當執(zhí)行資源故障重啟后,結果查詢線程會自動恢復待處理異步作業(yè)。這部分能力的支持在業(yè)務層是透明的,不改變整個交互流程。

4)引入適配器

業(yè)務雖可以通過必要方法完成自定義組件,但這些方法過于基礎,業(yè)務在一些特定場景下實現(xiàn)成本較高。如對于組件支持Shell的腳本化調用,業(yè)務其實僅需提供可執(zhí)行的Shell即可,通用約定的方式,其他必要方法的實現(xiàn)都可以交由系統(tǒng)完成。

針對業(yè)務個性化的處理,采用適配器模式,通用引入不同Command(ShellCommand、xxCommand)來默認實現(xiàn)特定場景下的必要方法,降低業(yè)務的開發(fā)成本。同時,保持系統(tǒng)側流程的一致性,通過動態(tài)注入Command的方式,防止對業(yè)務個性化處理的耦合。

圖片

圖16 組件適配器設計

5)效果

目前已支持Shell組件、服務組件、容器組件等多種接入方式,平臺上已提供數(shù)百個組件,組件開發(fā)方涉及數(shù)十個業(yè)務線。組件庫覆蓋源碼域、構建域、測試域、部署域、人工審批域等多個環(huán)節(jié),打通了研發(fā)過程所涉及的各個基礎工具。

圖片

圖17 組件庫

五、后續(xù)規(guī)劃

  • 借助Serverless等云原生技術,探索更輕量、高效的資源管理方案,提供更精細化的資源策略,從資源的彈性、啟動加速、環(huán)境隔離三個方面為業(yè)務提供更優(yōu)的資源托管能力。
  • 面向組件開發(fā)者,提供從開發(fā)、上線到運營的一站式開發(fā)管理平臺,降低組件開發(fā)、運營成本,使更多工具方、個人開發(fā)者能參與其中,共同打造豐富多樣的業(yè)務場景,形成良性的組件運營生態(tài)。?
責任編輯:張燕妮 來源: 美團技術團隊
相關推薦

2019-11-07 09:00:39

Jenkins流水線開源

2023-08-18 10:24:52

GitLabCI 流水線

2022-07-18 06:05:28

Gitlab流水線

2024-01-07 12:47:35

Golang流水線設計模式

2023-09-27 08:24:49

2025-05-08 07:36:57

DevOpsSpringCI/CD

2017-03-02 14:12:13

流水線代碼Clojure

2023-11-08 00:25:14

CI云原生DevOps

2021-12-24 08:02:48

GitLabCI模板庫流水線優(yōu)化

2023-04-02 21:49:10

開源Tekton

2018-03-28 09:53:50

Android架構演進

2021-04-29 08:55:54

GitLabDevOps項目

2023-12-11 18:35:37

測試流水線自動化

2017-02-28 16:00:45

DevOpsMarkdownreST

2023-05-10 15:08:00

Pipeline設計模式

2017-02-28 15:40:30

Docker流水線Azure

2013-06-06 09:31:52

2021-11-08 07:41:16

Go流水線編程

2020-10-25 11:28:12

開源端到端流水線

2012-10-23 14:27:55

無奈大裁員濾鏡拍照
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本精品一区二区三区在线观看视频 | 日韩色图视频 | 国产欧美日韩精品在线观看 | www久久99| 伊人欧美视频 | 国产一区二区观看 | 在线观看中文字幕 | 91麻豆精品一区二区三区 | 日本aaa视频| 波多野结衣亚洲 | 国产精品久久久久久婷婷天堂 | 日本一区二区不卡 | 成人深夜福利网站 | 91精品国产综合久久婷婷香蕉 | 在线观看国产www | 国产东北一级毛片 | 国产视频不卡一区 | 欧美一区二区三区久久精品视 | 国产98色在线 | 日韩 | 国产高清一区二区三区 | 在线观看h视频 | 成人欧美一区二区三区黑人孕妇 | 99久久久久久久 | 国产欧美精品区一区二区三区 | www.日韩高清 | 成人h视频在线 | 久久久精 | 久久久久久国产 | 国产区视频在线观看 | 久久国产欧美一区二区三区精品 | 色综合一区二区 | 涩涩操 | 91天堂 | 久久久久99 | 毛片一区二区三区 | 99精品视频在线观看 | 久久国产精品亚洲 | 亚洲网址| 精国产品一区二区三区四季综 | 国产一区欧美一区 | 精品欧美色视频网站在线观看 |