點(diǎn)擊上方“服務(wù)端思維”,選擇“設(shè)為星標(biāo)”
回復(fù)”669“獲取獨(dú)家整理的精選資料集
回復(fù)”加群“加入全國(guó)服務(wù)端高端社群「后端圈」
作者 | 網(wǎng)約車技術(shù)團(tuán)隊(duì)桔妹導(dǎo)讀:持續(xù)穩(wěn)定并體驗(yàn)良好的測(cè)試環(huán)境,一直是影響產(chǎn)品迭代效率和穩(wěn)定性的關(guān)鍵環(huán)節(jié),也是DevOps自動(dòng)化測(cè)試環(huán)節(jié)中最具挑戰(zhàn)的一環(huán),滴滴在測(cè)試環(huán)境上的探索從公司成立之初就從未停止,在這過(guò)程中沉淀了很多寶貴的經(jīng)驗(yàn)和教訓(xùn)。本文細(xì)數(shù)滴滴在測(cè)試環(huán)境的發(fā)展歷程,希望能給大家?guī)?lái)一些啟發(fā)。
伴隨著滴滴的不斷成長(zhǎng),業(yè)務(wù)復(fù)雜度與日俱增,團(tuán)隊(duì)在協(xié)作和迭代效率問(wèn)題上日益嚴(yán)重,"微服務(wù)"成了很多公司解決上述問(wèn)題的必經(jīng)之路,滴滴也不例外。隨著微服務(wù)在滴滴的落地,我們確實(shí)成功緩解了協(xié)作和迭代效率上的問(wèn)題,但同時(shí)也引出了很多新的問(wèn)題,比如構(gòu)建測(cè)試環(huán)境的復(fù)雜度,這也是我們今天要聊的主題——滴滴在測(cè)試環(huán)境上的探索與實(shí)踐。
在滴滴微服務(wù)落地初期,一個(gè)業(yè)務(wù)涉及服務(wù)數(shù)并不會(huì)太多,最多也就十幾個(gè),在這種場(chǎng)景下,不管怎么搭建測(cè)試環(huán)境都是相對(duì)容易的,哪怕是手動(dòng)維護(hù)也耗費(fèi)不了多少成本,所以在這個(gè)時(shí)期我們通過(guò)工具自動(dòng)構(gòu)建所有服務(wù),把所有服務(wù)都打包在一起基本就夠用了,我們管它叫"All in one"環(huán)境。這種方式持續(xù)了很長(zhǎng)時(shí)間,直到現(xiàn)在依然支持著部分測(cè)試工作,但隨著微服務(wù)數(shù)的增多這種方式越來(lái)越難以維護(hù)。當(dāng)我們的微服務(wù)數(shù)已經(jīng)達(dá)到了四位數(shù)的時(shí)候,All in one模式早已不能支撐測(cè)試需求,所以我們開(kāi)始探索其他解決方案。我們把目光轉(zhuǎn)移到了UT上,它最大的優(yōu)勢(shì)就是下游依賴全部通過(guò)mock的方式替換掉,只需部署被測(cè)服務(wù)即可。常見(jiàn)的類似方案還有契約測(cè)試,常用工具是Pact。契約測(cè)試認(rèn)為在微服務(wù)架構(gòu)下E2E測(cè)試其實(shí)是一個(gè)偽需求,應(yīng)該按照契約分別測(cè)試Consumer和Provider。我們也一度認(rèn)為微服務(wù)下的測(cè)試可能真的不適合做E2E測(cè)試,但當(dāng)真正應(yīng)用的時(shí)候,我們發(fā)現(xiàn)Pact測(cè)試太理想化了,如果針對(duì)下游依賴很少的服務(wù)來(lái)說(shuō)還行(但我們覺(jué)得All in one模式可能比Pact還好用),但對(duì)于最上游依賴成百上千個(gè)服務(wù),場(chǎng)景復(fù)雜多變的服務(wù)來(lái)說(shuō),Pact維護(hù)成本可能比環(huán)境維護(hù)成本還大(這里我們不討論架構(gòu)設(shè)計(jì)的合理性,只討論現(xiàn)狀)。但Pact測(cè)試還是給了我們一些啟發(fā),如果我們能解決自動(dòng)生成契約的方式,似乎問(wèn)題就解決了。所以從17年開(kāi)始我們嘗試通過(guò)線上錄制流量,線下回放流量的方式驗(yàn)證了可行性,隨后在滴滴內(nèi)部逐漸推廣開(kāi)來(lái),我們內(nèi)部管它叫Fastdev,同時(shí)對(duì)外分別開(kāi)源了針對(duì)PHP的https://github.com/didi/rdebug和針對(duì)Go的https://github.com/didi/sharingan,設(shè)計(jì)思路如下
隨著Fastdev的成功,似乎我們找到了銀彈,它可以完全模擬線上環(huán)境,測(cè)試場(chǎng)景也最真實(shí),就算流量變了,我們只需要手動(dòng)編輯一下個(gè)別流量也能實(shí)現(xiàn)mock能力,成本可比Pact編輯成本低多了。但通過(guò)實(shí)際應(yīng)用下來(lái),我們還是低估了業(yè)務(wù)的復(fù)雜度和用戶的接受度,雖然Fastdev能夠模擬線上真實(shí)場(chǎng)景,對(duì)重構(gòu)類變更(流量不變的情況)確實(shí)效果顯著,但一旦這次變更涉及到流量變化,就有可能導(dǎo)致所有流量都跟著變,比如在原來(lái)快車的基礎(chǔ)上增加了拼車邏輯,所有調(diào)用參數(shù)里都需要添加拼車相關(guān)數(shù)據(jù),那流量編輯的成本可能比Pact還高,因?yàn)槌艘斫鈽I(yè)務(wù)之外,還要熟悉每個(gè)通信協(xié)議設(shè)計(jì),比如Redis,mysql,http,thrift等等,就算我們針對(duì)所有協(xié)議設(shè)計(jì)了統(tǒng)一的DSL,也依然解決不了用戶的使用成本。針對(duì)流量變化的測(cè)試,我們的關(guān)注點(diǎn)又回到了環(huán)境搭建上,All in one的模式肯定是不可持續(xù)了,那如何才能以低成本方式保證每人都有一套穩(wěn)定的、高仿真度的測(cè)試環(huán)境呢?我們發(fā)現(xiàn)預(yù)發(fā)環(huán)境(類線上環(huán)境,除了沒(méi)有真實(shí)流量之外,其他跟線上環(huán)境無(wú)異)承擔(dān)了很多自動(dòng)化測(cè)試工作,并且足夠穩(wěn)定和仿真,所以我們又開(kāi)始了通過(guò)預(yù)發(fā)環(huán)境做測(cè)試的環(huán)境的探索,也就是業(yè)界常說(shuō)的TiP(Test in Production),先別著急噴TiP的各種問(wèn)題,后面會(huì)說(shuō)。其實(shí)從整個(gè)環(huán)境問(wèn)題來(lái)說(shuō),最難的其實(shí)就是下游依賴,如果我們把下游的預(yù)發(fā)環(huán)境做為測(cè)試環(huán)境的依賴,上游只需要部署被測(cè)服務(wù)即可,然后通過(guò)邏輯隔離的方式(測(cè)試賬號(hào))實(shí)現(xiàn)人手一套環(huán)境,成本也足夠低。按照這個(gè)思路,我們?cè)?8年開(kāi)始了TiP-Sim環(huán)境(線上仿真環(huán)境)的建設(shè),設(shè)計(jì)方案如下。
在實(shí)踐線上仿真環(huán)境的過(guò)程中遇到過(guò)很多問(wèn)題,其中一個(gè)就是流量閉環(huán)問(wèn)題,對(duì)于A調(diào)B,B調(diào)C的串行鏈路比較好支持,但涉及到A->B->C->A這種回調(diào)鏈路或者A->B->C,A只需要跟C單獨(dú)聯(lián)調(diào),跳過(guò)B的鏈路就不行了,無(wú)法實(shí)現(xiàn)流量的閉環(huán)。如果每人部署一套全量環(huán)境肯定不現(xiàn)實(shí),所以我們借鑒了一些業(yè)界常用的染色和分流方案,以很小的成本就實(shí)現(xiàn)了流量閉環(huán)。我們沒(méi)有采用在接入層或者路由層去做流量染色和分流,原因有兩方面,一是改動(dòng)成本較大,二是直連沒(méi)有經(jīng)過(guò)接入層。最終我們選擇了類似Service Mesh中Sidecar方案,在每個(gè)業(yè)務(wù)模塊上部署一個(gè)代理(只部署在基準(zhǔn)環(huán)境),所有的染色和流量都在代理上做,通過(guò)篡改Traceid實(shí)現(xiàn)流量標(biāo)識(shí)和分流(sim001xxxxxxxxxxxxxxx),最終實(shí)現(xiàn)了流量閉環(huán)。目前成了滴滴主要的聯(lián)調(diào)測(cè)試環(huán)境,設(shè)計(jì)如下。

但現(xiàn)實(shí)總是殘酷的,這就說(shuō)到了上面提到的TiP問(wèn)題,其中最大的問(wèn)題就是RD不敢在上面隨意調(diào)試,因?yàn)椴捎玫氖沁壿嫺綦x,網(wǎng)絡(luò)和數(shù)據(jù)都跟線上共用,稍有不慎就有可能導(dǎo)致線上事故,類似事故已經(jīng)出現(xiàn)多起。所以線上仿真環(huán)境并不敢大面積應(yīng)用到RD開(kāi)發(fā)測(cè)試中,只在開(kāi)發(fā)的差不多情況下才敢部署到TiP測(cè)試,當(dāng)然我們也嘗試在這個(gè)環(huán)境的基礎(chǔ)上做了數(shù)據(jù)層面的物理隔離,但依然解決不了影響線上的風(fēng)險(xiǎn),最終我們還得是回到起點(diǎn) —— 創(chuàng)建一套穩(wěn)定的線下測(cè)試環(huán)境,從根本上杜絕環(huán)境污染,這就是接下來(lái)要說(shuō)的線下仿真環(huán)境——OSim(Offline-Simulation)。
得益于滴滴服務(wù)全面上云,很多基礎(chǔ)能力的建設(shè)都可以以IaC的方式進(jìn)行簡(jiǎn)單配置實(shí)現(xiàn),比如同一個(gè)服務(wù)不同集群之間在不同的網(wǎng)段,不同集群之間的不同標(biāo)識(shí)等等,都讓我們復(fù)用線上能力的同時(shí)區(qū)分線上線下容易了很多。OSim環(huán)境類似上面提到的線上仿真環(huán)境,最大的區(qū)別就是網(wǎng)絡(luò)變成了線下,實(shí)現(xiàn)了與生產(chǎn)環(huán)境的物理隔離,根本上解決了線上環(huán)境污染的問(wèn)題,但這也意味著我們要把所有服務(wù)都要在線下搭建一遍,除了業(yè)務(wù)服務(wù)之外,所有的基礎(chǔ)服務(wù)也需要適配線下環(huán)境,比如存儲(chǔ)服務(wù),代理服務(wù),配置推送服務(wù),日志采集,APP、小程序等等,這相當(dāng)于再造一個(gè)線下滴滴,挑戰(zhàn)可想而知。但剛才說(shuō)了得益于上云和前人經(jīng)驗(yàn),很多東西已經(jīng)準(zhǔn)備好了,比如云上的存儲(chǔ),網(wǎng)絡(luò)的隔離,app debug包等等,同時(shí)根據(jù)經(jīng)驗(yàn),我們?cè)陧?xiàng)目創(chuàng)立之初就確定了三大原則:所有線下服務(wù)必須跟線上服務(wù)同時(shí)部署——保證高仿真度;
誰(shuí)的服務(wù)誰(shuí)負(fù)責(zé)——把整個(gè)項(xiàng)目拆解到最適合的人手里;
接入公司統(tǒng)一技術(shù)方案,比如RPC、服務(wù)發(fā)現(xiàn)、鏈路追蹤等等——減少維護(hù)成本;
基于以上原則,我們把所有涉及的服務(wù)都做了線上線下自適配,根據(jù)容器提供的標(biāo)識(shí)可以自動(dòng)區(qū)分線下和線上環(huán)境。但總有一些例外,針對(duì)一些特殊場(chǎng)景,我們也會(huì)選擇直接調(diào)用線上,比如跟地圖服務(wù)無(wú)業(yè)務(wù)無(wú)關(guān)的調(diào)用,又或者一些不怎么變動(dòng)的服務(wù)以mock方式提供等等,我們并沒(méi)有過(guò)度追求完美,夠用就好。環(huán)境搭建好以后,如何持續(xù)保障環(huán)境的穩(wěn)定性又是一個(gè)巨大的挑戰(zhàn)。由于滴滴很早之前就實(shí)現(xiàn)了異地雙活,所以對(duì)新增一個(gè)機(jī)房(線下環(huán)境就相當(dāng)于模擬創(chuàng)建了一個(gè)新的機(jī)房)的邊際維護(hù)成本幾乎為零,這樣我們沿用線上的標(biāo)準(zhǔn)來(lái)維護(hù)線下環(huán)境,比如報(bào)警監(jiān)控,oncall機(jī)制,甚至可用性指標(biāo)和事故復(fù)盤(pán)機(jī)制(目前還是輕運(yùn)營(yíng)的方式)等等,無(wú)需單獨(dú)為線下環(huán)境單獨(dú)搞一套穩(wěn)定性方案,同時(shí)也可以驗(yàn)證我們穩(wěn)定性技術(shù)方案的擴(kuò)展性。到此滴滴在整個(gè)測(cè)試環(huán)境上探索和實(shí)踐就講完了,大體分為All in one、流量錄制回放、線上仿真和線下仿真四種模式,在整個(gè)演進(jìn)歷程中,我們發(fā)現(xiàn)每一種測(cè)試環(huán)境特定場(chǎng)景下都有存在的必要性,誰(shuí)都代替不了誰(shuí),所以每個(gè)環(huán)境都值得團(tuán)隊(duì)投入更大的精力去建設(shè),畢竟測(cè)試環(huán)境是所有測(cè)試能力的基礎(chǔ)。最后想跟大家探討一個(gè)話題:"到底該由誰(shuí)來(lái)進(jìn)行測(cè)試"?在說(shuō)觀點(diǎn)之前,我想拿OP到SRE角色的轉(zhuǎn)變來(lái)舉例。記得幾年前,我還在某大廠工作,每次上線都要坐到OP旁邊,小心翼翼的求著OP給我上線,人多了還得人肉排隊(duì),好不容易輪到我,還得陪著OP慢慢灰度驗(yàn)證,一旦發(fā)現(xiàn)問(wèn)題,就得讓OP操作回滾,然后被OP一臉嫌棄,甭提多痛苦了?,F(xiàn)在看來(lái),應(yīng)該很少有這種上線方式了吧,由SRE提供部署平臺(tái),RD負(fù)責(zé)所有的部署流程似乎成了最常規(guī)的操作,也消除了RD和SRE協(xié)作成本,SRE也能專注在工具優(yōu)化上。其實(shí)測(cè)試也是類似道理,RD同樣應(yīng)該負(fù)責(zé)測(cè)試工作,由QA(或者叫SET)提供穩(wěn)定的高效的測(cè)試平臺(tái)協(xié)助RD測(cè)試。但有人可能會(huì)質(zhì)疑,RD這樣豈不是啥都做了,需求更迭代不過(guò)來(lái)了,其實(shí)根本原因還是在測(cè)試成本,如果測(cè)試能變成跟部署一樣簡(jiǎn)單,那RD來(lái)測(cè)試也就沒(méi)那么多問(wèn)題了。同時(shí)RD開(kāi)發(fā)本身也離不開(kāi)測(cè)試,每一次小的變更可能都需要跑一下測(cè)試來(lái)驗(yàn)證,更別提復(fù)雜變更了。但如果RD只是把簡(jiǎn)單測(cè)試過(guò)的代碼交給QA測(cè)試,后面就等著QA報(bào)bug,這種狀況會(huì)讓QA壓力越來(lái)越大,RD對(duì)變更越來(lái)越?jīng)]自信,測(cè)試工具的建設(shè)也越來(lái)越跟不上業(yè)務(wù)迭代,陷入惡性循環(huán)。但如果RD肩負(fù)起測(cè)試的責(zé)任,不管是在需求評(píng)審階段,代碼設(shè)計(jì)階段,還是在編碼階段都會(huì)考慮代碼的可測(cè)試性,架構(gòu)設(shè)計(jì)的合理性等,QA也會(huì)有更多的精力投入到工具建設(shè)中,RD的測(cè)試效率也會(huì)更快,最終達(dá)到一種良性循環(huán)。在DevOps思想中就提過(guò),RD應(yīng)該承擔(dān)起需求分析,設(shè)計(jì),編碼,測(cè)試,上線,線上問(wèn)題oncall等整個(gè)流水線工作,這樣溝通的成本最低,效率最高,但這中間每一個(gè)環(huán)節(jié)都應(yīng)該足夠便利,所有人都有義務(wù)來(lái)改進(jìn)這里的每一個(gè)環(huán)節(jié),來(lái)使整個(gè)DevOps流程更順暢。這個(gè)時(shí)候可能又有人說(shuō),讓RD來(lái)測(cè)試,很容易陷入自己的思維定式,測(cè)試不充分,第三方測(cè)試可以跳出思維定式,這里我們更贊成《Google軟件測(cè)試之道》中提到的測(cè)試活動(dòng)管理者,如果組織PM,運(yùn)營(yíng),內(nèi)/外部用戶,借助灰度發(fā)布等手段,全方面的驗(yàn)證可能效果會(huì)更好。這里不是說(shuō)QA就徹底不進(jìn)行測(cè)試了,借助更多測(cè)試手段,最終QA的測(cè)試工作會(huì)變得輕松很多,也會(huì)有更多精力投入到更具創(chuàng)新和挑戰(zhàn)的工作當(dāng)中。
關(guān)注我,回復(fù) 「加群」 加入各種主題討論群。
對(duì)「服務(wù)端思維」有期待,請(qǐng)?jiān)谖哪c(diǎn)個(gè)在看
喜歡這篇文章,歡迎轉(zhuǎn)發(fā)、分享朋友圈