<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何打造支撐百萬(wàn)級(jí)構(gòu)建量的服務(wù)系統(tǒng)

          共 4527字,需瀏覽 10分鐘

           ·

          2020-10-14 18:45



          正文如下

          本文是第十三屆 - 前端早早聊構(gòu)建專場(chǎng),也是早早聊第 89 場(chǎng),來(lái)自 淘系前端團(tuán)隊(duì) - 冬鶇 的分享

          引言 & 背景

          大家好,歡迎大家今天來(lái)參與本次“前端搞構(gòu)建”專場(chǎng),我是來(lái)自淘系前端的冬鶇,我所屬的團(tuán)隊(duì)負(fù)責(zé)淘系及集團(tuán)前端工程研發(fā)鏈路的建設(shè)。

          今天給大家分享的內(nèi)容是我們?cè)谠贫藰?gòu)建服務(wù)這個(gè)主題上的一些經(jīng)驗(yàn)和探索,也就是我們內(nèi)部所稱的“云構(gòu)建系統(tǒng)”。

          構(gòu)建,是前端同學(xué)日常開(kāi)發(fā)中的老朋友了,我敢打賭今天的聽(tīng)眾朋友中一定有不少是 Webpack 高級(jí)配置專家的,當(dāng)我們提到 “構(gòu)建” 這個(gè)詞時(shí),他可以代表多重意義:

          • 構(gòu)建過(guò)程:輸入源碼,輸入產(chǎn)物的過(guò)程
          • 構(gòu)建工具和生態(tài):webpack,rollup,以及 babel, ts 等
          • 構(gòu)建工具的“集成”:create-react-app,vue-cli,團(tuán)隊(duì)共用配置等
          • 構(gòu)建服務(wù)環(huán)境:jenkins,travis ci,gitlab ci 等

          構(gòu)建概念的變化,基本上是隨著項(xiàng)目和公司的規(guī)模擴(kuò)大而變化的,當(dāng)項(xiàng)目很小,一個(gè)人,本地構(gòu)建就能完成目標(biāo),使用的也是社區(qū)現(xiàn)成產(chǎn)物,隨著項(xiàng)目變多,構(gòu)建會(huì)很快成為一個(gè)團(tuán)隊(duì)做前端工程化的切入點(diǎn),隨著團(tuán)隊(duì)規(guī)范和統(tǒng)一構(gòu)建配置的產(chǎn)出,構(gòu)建工程化也算完成了它的歷史使命。

          然后有一周末,后端突然打來(lái)電話,線上出問(wèn)題了!說(shuō)要一個(gè)兩周前的版本回滾,你得回公司,開(kāi)電腦, git checkout, npm run build,構(gòu)建完成估計(jì)還有幾分鐘,趕緊內(nèi)網(wǎng)沖浪朋友圈分享,好不容易敬業(yè)一回。發(fā)完回來(lái)一看,構(gòu)建失敗,node 版本不匹配,一拍腦門,上周升了個(gè) node 版本,趕緊降回去,再 npm run build,泡杯茶壓壓驚,回來(lái)一看,less loader not found,node_modules/a/node_modules/b/node_modules/c minify error 全出來(lái)了。

          我們會(huì)進(jìn)一步思考,有沒(méi)有一個(gè)平臺(tái)能解決這一類的問(wèn)題?云構(gòu)建來(lái)了。

          系統(tǒng)設(shè)計(jì)

          這時(shí)候,構(gòu)建的概念終于變成了“前端構(gòu)建的服務(wù)化系統(tǒng)”,也就是我們今天的主角,前端云構(gòu)建系統(tǒng)。那么云構(gòu)建到底是什么?

          本質(zhì)上非常簡(jiǎn)單,就是把本地的構(gòu)建過(guò)程搬到云上,這樣做有什么好處呢?

          • 環(huán)境純凈,不會(huì)有 node 版本的問(wèn)題
          • 構(gòu)建邏輯標(biāo)準(zhǔn)化、中心化,構(gòu)建的邏輯與代碼邏輯是拆分的,整體構(gòu)建流程更可控
          • 回滾產(chǎn)物溯源,以前所有的版本都能快速獲取
          • 立足前端生態(tài),構(gòu)建是前端的構(gòu)建,專注于前端才能伺候的更好。
          • 滿足不同團(tuán)隊(duì)的需求,無(wú)論是 webpack ts js 還是 c++ 自己擼了一個(gè)構(gòu)建器,都能兼容
          • 支撐本地&云研發(fā),線上線下用同一套系統(tǒng)

          我們已經(jīng)累計(jì)運(yùn)行了上百萬(wàn)次構(gòu)建,活躍的構(gòu)建器有上百個(gè),除了傳統(tǒng)的前端倉(cāng)庫(kù)構(gòu)建外,還服務(wù)了搭建、低代碼鏈路的構(gòu)建需求,工作日的日構(gòu)建量在一萬(wàn)五左右。

          回到標(biāo)題,那我們是如何支撐這么大量的構(gòu)建任務(wù),并同時(shí)滿足不同團(tuán)隊(duì)間的需求呢?

          先來(lái)看一下整體的系統(tǒng)設(shè)計(jì):

          • 左側(cè)是接口,SDK,負(fù)責(zé)將系統(tǒng)能能力開(kāi)放給三方平臺(tái)
          • 上層部分,一部分是平臺(tái)的基礎(chǔ)能力,主要服務(wù)于構(gòu)建的發(fā)起用戶,同時(shí)承接構(gòu)建服務(wù)能力的相關(guān)工作,如產(chǎn)物下載,日志分析等,另一部份則是服務(wù)構(gòu)建器的開(kāi)發(fā)者,為其提供開(kāi)發(fā)、測(cè)試、上線、灰度等服務(wù),我們后面會(huì)詳細(xì)解釋構(gòu)建器的整體設(shè)計(jì)。
          • 系統(tǒng)底層是基于容器調(diào)度的任務(wù)運(yùn)行系統(tǒng),負(fù)責(zé)構(gòu)建任務(wù)的調(diào)度與資源分配,可以看到我們還有一個(gè)構(gòu)建運(yùn)行器,它運(yùn)行在底層的 docker 容器中,是運(yùn)行構(gòu)建過(guò)程的核心,運(yùn)行器在執(zhí)行構(gòu)建邏輯的同時(shí)也負(fù)責(zé)構(gòu)建相關(guān)數(shù)據(jù)的記錄與上報(bào),比如結(jié)果上傳,依賴數(shù)據(jù)掃描,階段計(jì)時(shí)等等。

          一個(gè)構(gòu)建任務(wù)的運(yùn)行邏輯非常清晰,從三方調(diào)用至構(gòu)建服務(wù),構(gòu)建服務(wù)進(jìn)行一些準(zhǔn)備邏輯,比如構(gòu)建器版本的確認(rèn),配置讀取等,再調(diào)用任務(wù)調(diào)度平臺(tái)進(jìn)行運(yùn)行,他們之間通過(guò)實(shí)時(shí)的 Websocket 或 HTTP 請(qǐng)求、回調(diào)進(jìn)行溝通。

          構(gòu)建系統(tǒng)支持的兩種方式的構(gòu)建,一個(gè)是命令構(gòu)建,感覺(jué)就和運(yùn)行一段 Shell 命令一樣,自定義程度高,接入成本極低,比如可以在倉(cāng)庫(kù)中配置中寫一個(gè) tnpm run build,接入就基本完成了。這方便一些小項(xiàng)目,小團(tuán)隊(duì)快速?gòu)谋镜貥?gòu)建轉(zhuǎn)移到云端構(gòu)建上去,直接享受平臺(tái)提供的一些內(nèi)能。除此之外就是通過(guò)構(gòu)建器進(jìn)行構(gòu)建。

          接下來(lái)先給大家講講構(gòu)建器的設(shè)計(jì)。

          構(gòu)建器

          構(gòu)建器邏輯

          構(gòu)建器干了什么事呢?本質(zhì)上就是完成了構(gòu)建邏輯與代碼邏輯的解耦,也就是把項(xiàng)目間構(gòu)建的依賴、配置和自定義構(gòu)建邏輯從項(xiàng)目中抽離出來(lái)。

          我們基于構(gòu)建的場(chǎng)景,定義了構(gòu)建器的接口,一個(gè)是本地的開(kāi)發(fā)態(tài)下的構(gòu)建,別一個(gè)是生產(chǎn)態(tài)下的構(gòu)建邏輯。

          開(kāi)發(fā)態(tài)邏輯在本地調(diào)試時(shí)執(zhí)行,生產(chǎn)態(tài)邏輯主要在云端執(zhí)行,通過(guò)這樣的設(shè)計(jì),我們完成了構(gòu)建器的標(biāo)準(zhǔn)化。繼而可以進(jìn)一步基于構(gòu)建器這個(gè)概念來(lái)提供更多能力。

          有一些同學(xué)會(huì)覺(jué)得,我直接把構(gòu)建邏輯抽出來(lái)發(fā)個(gè) npm 包,項(xiàng)目中依賴一下不就可以了么?

          但如果今天你是 rax 的構(gòu)建器負(fù)責(zé)人,你肯定不敢隨便發(fā)布,發(fā)個(gè) minor 吧還怕出 bug 影響項(xiàng)目的構(gòu)建,發(fā)個(gè) breaking change 也免不了那些把版本標(biāo)記成星號(hào)的狂野用戶,更可怕的是,你沒(méi)有他們代碼的 git 權(quán)限,想拿幾個(gè)實(shí)際項(xiàng)目測(cè)都測(cè)不了。為了讓你發(fā) npm 包沒(méi)有顧慮,我們?yōu)闃?gòu)建器提供了兩個(gè)不同的更新通道:正式通道和灰度通道。

          構(gòu)建器版本控制與灰度

          構(gòu)建器開(kāi)發(fā)者可以在平臺(tái)上更新不同的通道,同時(shí)可以指定用戶或者指定用戶比例來(lái)進(jìn)行灰度,系統(tǒng)會(huì)通知到用戶他被開(kāi)啟了構(gòu)建灰度,用戶也可以主動(dòng)體驗(yàn)新版本的構(gòu)建器。

          構(gòu)建平臺(tái)對(duì)版本的指定將成為唯一的版本確定來(lái)源,無(wú)論是本地的調(diào)試構(gòu)建還是線上的云構(gòu)建,都會(huì)受到平臺(tái)的控制,出了問(wèn)題一鍵回滾即時(shí)生效,這回 rax 開(kāi)發(fā)者終于能安心喝茶了。

          構(gòu)建器持久化

          有一個(gè)調(diào)侃前端工程師的圖大家都見(jiàn)過(guò),其實(shí)這里最重的真不是 antd,人家頂頭了也就幾十兆,最重的明明是 ts babel,還有一安裝就要編譯的 Sass。

          但是有了構(gòu)建器就不一樣了,當(dāng)構(gòu)建邏輯本身被抽離之后,構(gòu)建器的依賴也同時(shí)自然的從項(xiàng)目中剝離(估計(jì)一大部分的 devDependence 都被從項(xiàng)目中拿走了),所以我們將構(gòu)建器及其依賴在構(gòu)建機(jī)上做了持久化,更新的時(shí)機(jī)與開(kāi)發(fā)者更新的時(shí)機(jī)保持一致,這樣做還可以保證構(gòu)建器的依賴不會(huì)頻繁變動(dòng),社區(qū)包更新也不怕出問(wèn)題了。

          跟據(jù)我們的觀察,這樣做能平均減少 10% - 50% 的構(gòu)建總時(shí)長(zhǎng)。

          構(gòu)建通用服務(wù)

          我們說(shuō)云構(gòu)建是為前端開(kāi)發(fā)者服務(wù)的,光有一個(gè)構(gòu)建器是可不夠,我們?cè)谄脚_(tái)上可以為構(gòu)建器以及構(gòu)建命令的使用用戶提供一些通用能力,來(lái)輔助他們進(jìn)行問(wèn)題的定位以及構(gòu)建效率的提升,這里給大家介紹兩個(gè)用戶不用配置就直接可用的平臺(tái)功能。

          Sourcemap 提取

          先來(lái)看 Sourcemap,這是一個(gè)讓人又愛(ài)又恨的功能,開(kāi)了之后線上調(diào)試那叫一個(gè)爽,但是就怕哪天有人在 Sourcemap 解析代碼中發(fā)現(xiàn)我罵老板,這是很大的安全隱患對(duì)不對(duì)。

          Sourcemap 要想正確生效,構(gòu)建的時(shí)候就需要一并產(chǎn)出,差一個(gè)字母都不行,因?yàn)榘踩珕?wèn)題又不能發(fā)上線,這個(gè)時(shí)候云構(gòu)建就可以幫項(xiàng)目做這個(gè)事了。

          構(gòu)建后,我們會(huì)在產(chǎn)物中搜索 map 文件,并記錄到系統(tǒng)中,用戶或平臺(tái)可以選擇在最終產(chǎn)物中刪除這些 map,來(lái)保證在發(fā)布的時(shí)候這些 map 不會(huì)泄露到外部造成一些安全問(wèn)題。被刪除的那些 sourcemap 文件會(huì)在內(nèi)網(wǎng)中提供入口,給三方平臺(tái)和用戶使用。淘系內(nèi)部的一些面向前端的混沌攻擊系統(tǒng)就使用了這個(gè)能力來(lái)進(jìn)行模擬攻擊。

          node_modules 掃描記錄

          大家都知道 npm 的 semver 原則,同樣的代碼今天構(gòu)建和明天構(gòu)建,他實(shí)際的依賴可能發(fā)生變化,這個(gè)變化有可能會(huì)帶來(lái)一些問(wèn)題,比如我們剛才講過(guò)的構(gòu)建失敗,甚至產(chǎn)物受到影響,或者出現(xiàn)一些邏輯問(wèn)題和安全問(wèn)題,類似前一段時(shí)間 is-promise 更新事件,所以產(chǎn)出構(gòu)建產(chǎn)物的這次構(gòu)建的實(shí)際依賴是有必要記錄下來(lái)的,其一可以幫助定位問(wèn)題,其二可以在發(fā)生一些安全風(fēng)險(xiǎn)時(shí)快速提醒相關(guān)的項(xiàng)目。

          大體邏輯是在構(gòu)建后進(jìn)行掃描,記錄,再通過(guò)數(shù)據(jù)清洗的方式得出相關(guān)的依賴關(guān)系,掃描邏輯可以看一下業(yè)界的一些實(shí)現(xiàn),比如 npm 7 使用的 arborist。之后用戶就可以查看每次構(gòu)建的依賴情況,出現(xiàn)了不知道原因的邏輯問(wèn)題時(shí),也可以通過(guò)比較依賴樹(shù)來(lái)定位問(wèn)題。同時(shí)當(dāng)一些包出現(xiàn)安全隱患或暴露已知問(wèn)題時(shí),我們也可以快速得到相應(yīng)的構(gòu)建記錄,來(lái)提醒同學(xué)注意修復(fù)問(wèn)題。

          數(shù)據(jù)相關(guān)的邏輯我們是和螞蟻合作產(chǎn)出的,有興趣大家可以關(guān)注下 陸沉 老師帶來(lái)的關(guān)于構(gòu)建數(shù)據(jù)相關(guān)的分享,一定非常精彩。

          任務(wù)系統(tǒng)

          任務(wù)系統(tǒng)是我們支撐 2000 每小時(shí)的構(gòu)建任務(wù)并發(fā)的核心,它負(fù)責(zé)容器的調(diào)度、基礎(chǔ)鏡像的管理以及管理日志、結(jié)果。這套系統(tǒng)現(xiàn)在已經(jīng)云構(gòu)建中剝離出來(lái)了,除了負(fù)責(zé)構(gòu)建相關(guān)的任務(wù)外,還同時(shí)會(huì)承載一些其他工程相關(guān)系統(tǒng)任務(wù)的運(yùn)行,比如代碼質(zhì)量的檢查,倉(cāng)庫(kù)分支的合并等等。在物理機(jī)或 ECS 上會(huì)有負(fù)責(zé)控制、發(fā)現(xiàn)機(jī)器的 Client,他同時(shí)也管理了我們上文提到的構(gòu)建器的緩存邏輯

          架構(gòu)上,我們主要使用 docker 及其提供的相關(guān) API,在之上標(biāo)準(zhǔn)化了一些日志、結(jié)果獲取的能力,通過(guò)與 docker server 直接進(jìn)行加密鏈接,就可以拿到實(shí)時(shí)的日志和容器中產(chǎn)出的文件了。

          團(tuán)隊(duì)介紹

          1. 歸屬的團(tuán)隊(duì)是淘系工程團(tuán)隊(duì),實(shí)際上不止服務(wù)著淘系近 300 左右的前端同學(xué),也服務(wù)著集團(tuán)每周近 3000 位的前端及非前端研發(fā)的同學(xué)
          2. 整體的平臺(tái)體系,底層依賴了非常多的底層服務(wù),有內(nèi)部體系的,云上資源的
          3. 團(tuán)隊(duì)小伙伴每天支撐的應(yīng)用體系內(nèi)容大致分為 基礎(chǔ)服務(wù)能力工程應(yīng)用產(chǎn)品
            1. 基礎(chǔ)服務(wù),依托于前面提到的底層任務(wù)調(diào)度系統(tǒng),以及上層的云構(gòu)建,依然存在著非常多的產(chǎn)品體系,以資源檢測(cè)為代表的門神系統(tǒng)、以腳手架倉(cāng)庫(kù)初始配置為代表的云腳手架系統(tǒng),以及面向工程研發(fā)流程定制能力的流程引擎系統(tǒng);
            2. 除此之外,我們也維護(hù)著整個(gè)阿里經(jīng)濟(jì)體體系內(nèi),最大的源站回源體系,作為經(jīng)濟(jì)體內(nèi)主要業(yè)務(wù)及雙促業(yè)務(wù)的資源、頁(yè)面基礎(chǔ)服務(wù)重要一環(huán)
            3. 在基礎(chǔ)服務(wù)能力之上,從用戶產(chǎn)品的維度提供了支撐前端研發(fā)應(yīng)用持續(xù)部署的工程研發(fā)平臺(tái),本地 CLI 研發(fā)工具解決方案工程套件,以及給予以及支撐面向上層體系內(nèi)平臺(tái)定制、自建場(chǎng)景的開(kāi)放平臺(tái)
            4. 以及去年在阿里舉辦的 D2 前端分享會(huì)中提到的 IDE 體系也正在緊鑼密鼓的建設(shè)推進(jìn)中
          4. 作為集團(tuán)前端研發(fā)的基礎(chǔ)設(shè)施,在整個(gè)體系內(nèi)也參與、主導(dǎo)了非常多的橫向體系,例如面向前端研發(fā)的安全生產(chǎn)治理、IDE 底層體系等等
          5. 平臺(tái)在幾年的建設(shè)下來(lái),以及支撐起集團(tuán)體系內(nèi)的絕大多數(shù) BU 的核心業(yè)務(wù)體系
          6. 歡迎敢想敢做的同學(xué)聯(lián)系我們交流

          書(shū):人類起源的故事

          加微信 codingdreamer ,備注進(jìn)群,加入大會(huì)專屬內(nèi)推群,及講師團(tuán)隊(duì)釘釘群

          掃碼關(guān)注公眾號(hào),訂閱更多精彩內(nèi)容。



          你點(diǎn)的每個(gè)贊,我都認(rèn)真當(dāng)成了喜歡
          ?


          瀏覽 67
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  美女扒开尿口让 | 亚洲免费黄色网址 | 日韩三级电影在线播放 | 国产精品成人无码a无码 | 美女无码电影 |