債務(wù)治理實(shí)戰(zhàn):存量修復(fù)加增量攔截的雙軌治理體系)
本文整理自QCon北京《何之真 - B站的存量修復(fù)和增量攔截》通過(guò)AI音視頻總結(jié)工具Ai好記視頻轉(zhuǎn)文字轉(zhuǎn)錄整理以下為精煉整理后的會(huì)議筆記內(nèi)容。講到技術(shù)債務(wù)治理很多團(tuán)隊(duì)的第一反應(yīng)是搞專(zhuān)項(xiàng)治理短期把告警曲線(xiàn)降下來(lái)過(guò)一陣子又反彈回去然后再來(lái)一次專(zhuān)項(xiàng)。B站工程技術(shù)團(tuán)隊(duì)的這篇分享提出了一個(gè)不同的思路存量修復(fù)和增量攔截雙軌并進(jìn)加上AI深度參與構(gòu)建一套可持續(xù)、自動(dòng)化的技術(shù)債務(wù)治理體系。整場(chǎng)內(nèi)容對(duì)在中大型互聯(lián)網(wǎng)公司做工程效能、開(kāi)發(fā)者工具、代碼治理的人都很有參考價(jià)值。痛點(diǎn)為什么技術(shù)債務(wù)治理這么難B站除了視頻業(yè)務(wù)還包括直播、社區(qū)、生態(tài)、游戲、漫畫(huà)、大會(huì)員、商業(yè)等語(yǔ)言也很豐富主力是 Java、Go、C移動(dòng)端還有 Kotlin、Swift、鴻蒙等代碼倉(cāng)庫(kù)量級(jí)大且持續(xù)增長(zhǎng)。單以用戶(hù)技助中心為例整體代碼量六七千萬(wàn)行平均每人十幾萬(wàn)行每季度新增數(shù)百萬(wàn)行而主站研發(fā)只有五六百人的規(guī)模。傳統(tǒng)治理有幾個(gè)繞不開(kāi)的問(wèn)題專(zhuān)項(xiàng)治理不治本是臨時(shí)性、階段性的動(dòng)作無(wú)法常態(tài)化還會(huì)打斷正常開(kāi)發(fā)節(jié)奏人必須做優(yōu)先級(jí)取舍。問(wèn)題引入是持續(xù)過(guò)程正常迭代、重構(gòu)、bugfix 都會(huì)引入新問(wèn)題引入速度往往超過(guò)修復(fù)速度債務(wù)越來(lái)越多。人工修復(fù)周期長(zhǎng)從定位、復(fù)現(xiàn)、理解、嘗試修復(fù)、驗(yàn)證編譯、單測(cè)、lint甚至部署測(cè)試環(huán)境到 app owner review 和合入每一步都靠人每步都可能因優(yōu)先級(jí)卡住。核心矛盾在于修復(fù)是單點(diǎn)、離散的行為而問(wèn)題引入是持續(xù)不斷的。所以作者認(rèn)為要做好治理需要四個(gè)能力穩(wěn)定的修復(fù)產(chǎn)能不依賴(lài)人工排期可信的驗(yàn)證鏈路風(fēng)險(xiǎn)分層機(jī)制有人負(fù)責(zé)兜底確認(rèn)問(wèn)題并處理AI 在治理中的價(jià)值極大提高修復(fù)產(chǎn)能人工一個(gè)一個(gè)修AI 可以批量自動(dòng)化還包含驗(yàn)證步驟。拓展增量攔截在 MR 階段的增量攔截里發(fā)現(xiàn)更多問(wèn)題避免它們變成歷史債務(wù)。知識(shí)沉淀修復(fù)獲得的經(jīng)驗(yàn)轉(zhuǎn)成 prompt 或 skill 及對(duì)應(yīng)評(píng)測(cè)級(jí)用于持續(xù)優(yōu)化。降低修復(fù)門(mén)檻原來(lái)人要理解規(guī)則再改代碼現(xiàn)在 AI 能根據(jù)自然語(yǔ)言描述直接修人只需看修復(fù)對(duì)不對(duì)。雙軌治理總體架構(gòu)與核心原則存量修復(fù)解決如何清空歷史債務(wù)增量攔截解決如何避免新問(wèn)題合入主干成為新債務(wù)。兩條軌道互相依賴(lài)存量修復(fù)的產(chǎn)出也是一個(gè) MR必須通過(guò)增量攔截再驗(yàn)證增量攔截發(fā)現(xiàn)的新問(wèn)題又能作為存量修復(fù)的輸入擴(kuò)大范圍存量端 AI 負(fù)責(zé)執(zhí)行修復(fù)驗(yàn)證交其他工具和角色增量端 AI 擴(kuò)展發(fā)現(xiàn)問(wèn)題的范圍并持續(xù)提高準(zhǔn)確率四條核心原則雙軌并進(jìn)存量修復(fù)和增量攔截必須同時(shí)進(jìn)行風(fēng)險(xiǎn)分層減少人工介入但保持可控職責(zé)明確規(guī)則負(fù)責(zé)發(fā)現(xiàn)和驗(yàn)證AI 負(fù)責(zé)修復(fù)owner 兜底決策回流優(yōu)化成功失敗結(jié)果都回流優(yōu)化規(guī)則、prompt 和策略存量修復(fù)約束下的批量自動(dòng)化修復(fù)背景團(tuán)隊(duì) 2024 年做了全公司工程能力建設(shè)為幾乎所有應(yīng)用都增加了增量攔截環(huán)節(jié)配置了包含編譯、單測(cè)、lint靜態(tài)代碼掃描的流水線(xiàn)要求不能有新增 bug有的團(tuán)隊(duì)還要求不能新增異位或漏洞甚至配置接口測(cè)試流水線(xiàn)發(fā)現(xiàn)接口不兼容影響。流程存量修復(fù)流程從 sonar 掃描開(kāi)始每個(gè) MR 合并后流水線(xiàn)自動(dòng)掃描相關(guān)應(yīng)用拿到最新問(wèn)題數(shù)。達(dá)到修復(fù)閾值后觸發(fā)自動(dòng)修復(fù)流水線(xiàn)AI 在約束下工作只在自定義 linter 工具和 prompt 指定的問(wèn)題類(lèi)型內(nèi)修復(fù)不在全量問(wèn)題上自由發(fā)揮只在指定文件范圍內(nèi)修改修復(fù)結(jié)果必須通過(guò)同一 linter 工具驗(yàn)證生成的 MR 必須通過(guò)增量攔截流水線(xiàn)再次檢驗(yàn)最后由 app owner review 決策合入為什么是半自動(dòng)化早期試點(diǎn)時(shí)對(duì)所有有問(wèn)題的應(yīng)用每天全量跑修復(fù)但研發(fā)正處于緊急新功能迭代沒(méi)時(shí)間 review加上主干頻繁合入導(dǎo)致 MR 一直沖突、最后不得不用 MR。后來(lái)改成先收集掃描得到的問(wèn)題數(shù)據(jù)做報(bào)表按應(yīng)用等級(jí)、部門(mén)、問(wèn)題嚴(yán)重程度同步給應(yīng)用負(fù)責(zé)人再根據(jù)應(yīng)用重要程度和問(wèn)題嚴(yán)重程度商定修復(fù)閾值達(dá)到閾值才批量觸發(fā)修復(fù)流水線(xiàn)owner 也更有動(dòng)力去 review 合入。效果數(shù)據(jù)用戶(hù)技助中心代碼異位從第一季度最高 1 萬(wàn) 4 千多降到接近平緩的 1 千 1 百多疊加上其他業(yè)務(wù)整體一個(gè)季度下降約 90%bug 數(shù)因?yàn)楣こ棠芰ㄔO(shè)加增量攔截長(zhǎng)期維持在個(gè)位數(shù)增量攔截在主干之外攔下新問(wèn)題AI 是對(duì)原有 CI 流程的補(bǔ)充增強(qiáng)。MR 的增量攔截流水線(xiàn)必跑編譯、單測(cè)、lint部分開(kāi)啟 AI 能力的倉(cāng)庫(kù)還會(huì)跑 AI 相關(guān)的流水線(xiàn)比如 AI CodeReview、單元測(cè)試補(bǔ)充、接口測(cè)試補(bǔ)充。所有流水線(xiàn)跑完后匯總結(jié)果參考配置判斷哪些弱軟性失敗不阻塞合入綜合得到 MR 是否 ready 合入的狀態(tài)。研發(fā)能看到問(wèn)題描述和修復(fù)建議對(duì) AI 部分的問(wèn)題可據(jù)建議修復(fù)其他常規(guī)編譯問(wèn)題自行處理或暫緩。最終 owner 再做一次 review 決定合入。AI CodeReview對(duì)傳統(tǒng) lint 的補(bǔ)充而非替代傳統(tǒng) lint 的局限要把經(jīng)驗(yàn)固化成規(guī)則由工具執(zhí)行確定性極強(qiáng)只能發(fā)現(xiàn)能形式化表達(dá)的問(wèn)題基于單行或局部模式匹配AI CodeReview 的優(yōu)勢(shì)可以用自然語(yǔ)言描述審查意圖能理解代碼上下文、函數(shù)模塊調(diào)用鏈甚至變更意圖從而發(fā)現(xiàn)難以規(guī)則化的邏輯和規(guī)范問(wèn)題具備需求視角能對(duì)照需求、接口約束、預(yù)期行為判斷實(shí)現(xiàn)有沒(méi)有偏差可構(gòu)建數(shù)據(jù)閉環(huán)審查結(jié)果人工反饋、誤報(bào)分析、問(wèn)題歸因回流去迭代提示詞、更新規(guī)則提升識(shí)別能力和準(zhǔn)確度分層處理很關(guān)鍵對(duì)代碼本身的審查是高置信度結(jié)論作為阻塞合入的門(mén)檻有問(wèn)題必須修復(fù)對(duì)需求實(shí)現(xiàn)的理解和評(píng)估是低置信度結(jié)論只作為提示不阻塞供研發(fā)參考目前 AI CodeReview 只對(duì)一部分倉(cāng)庫(kù)開(kāi)啟開(kāi)啟范圍內(nèi)準(zhǔn)確率在 85% 以上。AI 補(bǔ)充單元測(cè)試圍繞 MR 變更函數(shù)流程從 MR diff 獲取變更函數(shù)用代碼圖譜加靜態(tài)分析梳理這些函數(shù)的下游依賴(lài)先去遠(yuǎn)端存儲(chǔ)找現(xiàn)成單測(cè)執(zhí)行并看覆蓋率超過(guò)閾值就結(jié)束否則生成新測(cè)試生成時(shí)在 prompt 里提供整條函數(shù)鏈路信息AI 生成的測(cè)試文件可能編譯不過(guò)會(huì)有修復(fù)編譯循環(huán)把編譯報(bào)錯(cuò)、堆棧喂給 AI 修之后做兩輪分析第一輪用變更函數(shù)及下游依賴(lài)信息對(duì)失敗 case 歸因把非代碼問(wèn)題環(huán)境、框架的失敗去掉但不簡(jiǎn)單丟棄而是人工收集處理第二輪給 AI 完整代碼庫(kù)梳理上下游依賴(lài)去除無(wú)效 case比如針對(duì)防御性編程的失敗用例最終保留 AI 認(rèn)為有效并經(jīng)部分人工確認(rèn)的用例保存云端復(fù)用當(dāng)前狀態(tài)上線(xiàn)不到一個(gè)月增量覆蓋率約 85%正確率還沒(méi)到門(mén)檻AI 標(biāo)注有效 28 條、人工標(biāo)注完成 22 條里 12 條有效、準(zhǔn)確率 54.5%暫時(shí)不把它作為合入門(mén)檻等正確率提到 80% 到 90% 再考慮AI 補(bǔ)充接口測(cè)試覆蓋率驅(qū)動(dòng)的迭代閉環(huán)整體設(shè)計(jì)整體是兩層循環(huán)。外層循環(huán)生成測(cè)試用例內(nèi)層循環(huán)修復(fù)測(cè)試用例執(zhí)行中的問(wèn)題。設(shè)計(jì)原則盡可能覆蓋未覆蓋的鏈路一輪只生成一個(gè)測(cè)試用例避免批量生成互相干擾內(nèi)層也一次只修一條問(wèn)題批量修容易出現(xiàn)級(jí)聯(lián)問(wèn)題、排查困難執(zhí)行過(guò)程基于 mock 回放工具發(fā)現(xiàn)下依賴(lài)缺失或 mock 內(nèi)容不對(duì)就修對(duì)時(shí)間戳、隨機(jī)值這類(lèi)高波動(dòng)內(nèi)容通過(guò)策略忽略最后一輪數(shù)據(jù)鏈路復(fù)盤(pán)比較接口實(shí)際響應(yīng)和預(yù)期是否一致不一致時(shí)讓 AI 根據(jù)應(yīng)用日志做完整歸因復(fù)盤(pán)輸出交人工確認(rèn)當(dāng)前狀態(tài)目前是內(nèi)部試點(diǎn)效果波動(dòng)較大好的應(yīng)用兩三輪就能到 60% 覆蓋率??偨Y(jié)與展望核心觀(guān)點(diǎn)技術(shù)債務(wù)治理本質(zhì)是持續(xù)運(yùn)行的系統(tǒng)不能靠一兩次專(zhuān)項(xiàng)完成存量修復(fù)和增量攔截必須同時(shí)做驗(yàn)證要優(yōu)先AI 或人工修復(fù)都先通過(guò)驗(yàn)證再人工 review 合入當(dāng)前局限存量修復(fù)主要覆蓋少部分低風(fēng)險(xiǎn)類(lèi)型的規(guī)則補(bǔ)充單測(cè)和接口測(cè)試都還處于小規(guī)模試點(diǎn)未來(lái)方向MR 合入最終還是由 owner 決定后續(xù)可以嘗試更精細(xì)的分層機(jī)制讓某類(lèi)問(wèn)題自動(dòng)修復(fù)持續(xù)優(yōu)化成本總體落地思路是先證明局部成立再平臺(tái)化擴(kuò)張以上內(nèi)容由 Ai好記 轉(zhuǎn)錄整理。Ai好記是一款支持音視頻轉(zhuǎn)圖文筆記的AI知識(shí)庫(kù)工具支持B站、小紅書(shū)、抖音、小宇宙等平臺(tái)鏈接及本地音視頻文件視頻轉(zhuǎn)文字后自動(dòng)生成精華速覽、思維導(dǎo)圖和結(jié)構(gòu)化圖文筆記幫助你把幾小時(shí)的視頻內(nèi)容變成可搜索、可復(fù)習(xí)的圖文筆記。