Jordan Sitkin 和 Luke Demi 討論了 Coinbase 應(yīng)對(duì) 2017 年加密貨幣的激增的方式,以及工程師們是如何利用從這些經(jīng)歷中獲得的經(jīng)驗(yàn)教訓(xùn)來(lái)創(chuàng)建用
Jordan Sitkin 和 Luke Demi 討論了 Coinbase 應(yīng)對(duì) 2017 年加密貨幣的激增的方式,以及工程師們是如何利用從這些經(jīng)歷中獲得的經(jīng)驗(yàn)教訓(xùn)來(lái)創(chuàng)建用于容量規(guī)劃的新工具和技術(shù)、為加密貨幣熱潮的未來(lái)浪潮做準(zhǔn)備的。Luke Demi 是 Coinbase 可靠性團(tuán)隊(duì)(Reliability Team)的軟件工程師。Jordan Sitkin 是 Coinbase 的軟件工程師。本文整理自他們?cè)?QCon 的演講《Capacity Planning for Crypto Mania》。
正文
Demi:我就開(kāi)門見(jiàn)山地說(shuō)了。如果我們?cè)噲D在 2017 年 5 月訪問(wèn) Coinbase,那么,可能看到這么一個(gè)頁(yè)面。我們也許在嘗試檢查自己的余額、或在購(gòu)買新的加密貨幣,或者是想從 Coinbase 的網(wǎng)站提取資金,但是我們卻發(fā)現(xiàn)加密貨幣的價(jià)格在飛漲。人們突然對(duì)購(gòu)買加密貨幣真正感興趣了,所以加密貨幣的交易系統(tǒng)崩潰了。有點(diǎn)像 QCon 的網(wǎng)站,對(duì)吧?只是開(kāi)個(gè)玩笑,不過(guò)我們迫不及待地想從負(fù)責(zé)此事的人那里看到關(guān)于這一“貨幣戰(zhàn)爭(zhēng)”的故事。
但不管怎么說(shuō),冷靜。沒(méi)錯(cuò),這個(gè)現(xiàn)象很糟糕,原因有很多。但主要是因?yàn)?,如果?dāng)時(shí)你是 Coinbase 的客戶,那么你一定會(huì)產(chǎn)生擔(dān)心的情緒——你會(huì)擔(dān)心自己的錢不見(jiàn)了。Coinbase 剛剛被黑了,發(fā)生了什么事?我們開(kāi)始看到一些可怕的說(shuō)法,比如這種:“Coinbase 隨著比特幣和以太網(wǎng)而沒(méi)落了。”
好吧,這么說(shuō)很對(duì)。但是,很傷人。這些年我們一直低調(diào)行事,嘗試建立這個(gè)生態(tài)系統(tǒng),并試圖領(lǐng)導(dǎo)這場(chǎng)變革。這些 Reddit 上的評(píng)論,有點(diǎn)幽默,但抓住了那天的情緒。我再讀一條評(píng)論:“有趣的是,Coinbase 應(yīng)該使用了 AWS,因此容量不該是個(gè)問(wèn)題。除非他們不使用自動(dòng)擴(kuò)展或者太便宜而無(wú)法購(gòu)買更多的 AWS 資源,或者只是懶。”
這是某天我們?cè)谝粋€(gè)房間里的寫照。那天非常有趣,因?yàn)槲覀円徽於荚诎l(fā)愁。大概有 8 小時(shí),我們?cè)谝粋€(gè)有沙發(fā)的房間里就這么坐著,想找出方法來(lái)讓網(wǎng)站回復(fù)原狀。那天的《紐約時(shí)報(bào)》刊登了一篇文章,稱 Coinbase 宕機(jī)了,無(wú)法處理網(wǎng)絡(luò)負(fù)載。對(duì)我們公司來(lái)說(shuō),這是一個(gè)重要的轉(zhuǎn)折點(diǎn)。我們意識(shí)到,如果我們不能團(tuán)結(jié)一致,那么,Coinbase 就無(wú)法生存。
Siktin:我們把這個(gè)訪談叫做加密狂熱的容量規(guī)劃。該訪談的內(nèi)容是我們?nèi)绾握一刈罴褷顟B(tài)。也就是說(shuō),我們?nèi)绾螐?Luke 剛介紹的、去年那個(gè)黑暗的日子開(kāi)始把這個(gè)故事反轉(zhuǎn)。我們準(zhǔn)備介紹我們?cè)谀嵌螘r(shí)間學(xué)到的東西。在那段短短幾個(gè)月的時(shí)間里,Coinbase 的流量增加了 20 倍。
我們犯了一些錯(cuò),得到了一些教訓(xùn),而且我們有幸在工作的同時(shí)進(jìn)行了一些有趣的挑戰(zhàn)。當(dāng)然,在此期間,我們的工具和系統(tǒng)不得不快速成熟。我們將介紹 Coinbase 從那天開(kāi)始的故事,并會(huì)隨時(shí)提出一些見(jiàn)解和經(jīng)驗(yàn)。然后,我們計(jì)劃講講我們現(xiàn)在在做的事,為未來(lái)做更好的準(zhǔn)備。
先簡(jiǎn)單做個(gè)介紹。我是 Jordan,這位是 Luke。我們是 Coinbase 可靠性團(tuán)隊(duì)成員。需要說(shuō)明的是,在去年那場(chǎng)瘋狂的熱潮中,我們只是涉及其中的兩位。我們也是現(xiàn)在和未來(lái)負(fù)責(zé)維護(hù)系統(tǒng)可靠性的人。
買賣數(shù)字貨幣
正如你們中的很多人所指出的,大家已經(jīng)很熟悉 Coinbase 了。對(duì)于 Coinbase,大多數(shù)人都知道是個(gè)應(yīng)用程序。我們希望它成為最簡(jiǎn)單、最值得信任的數(shù)字貨幣交易及管理場(chǎng)所。但是現(xiàn)在,Coinbase 實(shí)際上遠(yuǎn)不止是個(gè)應(yīng)用程序。我們是圍繞著 Coinbase 這一名稱的一個(gè)其他品牌和服務(wù)的小集合。為了更全面地概述我們的技術(shù)棧,今天我們?cè)谶@里主要討論的是一個(gè)獨(dú)立 Rails 應(yīng)用程序。它由 MongoDB 數(shù)據(jù)庫(kù)支持,其基礎(chǔ)設(shè)施在 AWS 上部署和管理。
在今天的演講中,我們希望告訴大家兩件重要的事情。首先,今天演講的題目是跟容量規(guī)劃有關(guān)的,但是,我們實(shí)際上會(huì)用大多數(shù)時(shí)間來(lái)談負(fù)載測(cè)試。原因是,我們覺(jué)得負(fù)載測(cè)試(或者叫容量測(cè)試、壓力測(cè)試、批量測(cè)試)是我們?cè)谌萘恳?guī)劃工作中最重要的工具。我的意思是,通過(guò)容量測(cè)試(或同樣術(shù)語(yǔ)的不同其他叫法),實(shí)際上能夠模擬和研究生產(chǎn)中可能發(fā)生的真實(shí)故障。這樣說(shuō)應(yīng)該比較容易理解吧。
其次,我們希望告訴大家,在負(fù)載測(cè)試環(huán)境中,與生產(chǎn)完全對(duì)等不是從負(fù)載測(cè)試系統(tǒng)中獲得良好結(jié)果的必須要求。我們準(zhǔn)備解決它的方法之一是,引入我們稱之為容量周期的概念。這將是我們?cè)谡麄€(gè)演講中都要回歸的主題,因此,我希望現(xiàn)在就把它介紹給大家。我們準(zhǔn)備詳細(xì)介紹它的含義,但我們也打算通過(guò)這種方式分享我們的一些經(jīng)驗(yàn)。
后端 RPM
Demi:好,我們稍微回頭看看,再講一點(diǎn)關(guān)于這個(gè)故事的背景。其實(shí)只是展示一下我們的流量模式在事情變?cè)闱暗臉幼印N乙f(shuō)的是,它們很隨意。這是我們到 Rails 服務(wù)的后端流量。我們可以看到,流量一會(huì)兒增加一會(huì)兒下降,但其波動(dòng)處于一個(gè)相當(dāng)狹窄的范圍內(nèi)。這里畫了一條紅線,沒(méi)其他特別的原因,只是表示上面的情況很糟糕,但我們離那里還很遠(yuǎn)。
在這個(gè)時(shí)間點(diǎn),紅線就意味著人們真正開(kāi)始對(duì)加密貨幣、盈利能力這類東西感興趣了,它們不是我們擔(dān)心的事情類型。我們不認(rèn)為我們會(huì)碰到這條紅線。然而,這條紅線最終成為一場(chǎng)災(zāi)難。這是我們的流量圖。稍微提一下,該圖截止到 2017 年 7 月前后。這張圖展示了我們的流量變化,以及我們穿過(guò)這條紅線的方式。很顯然,這背后是以太坊和比特幣的熱潮。
我們?cè)谶@條紅線上方待了幾天。有幾天我們從太平洋時(shí)間凌晨 3 點(diǎn)開(kāi)始一直到半夜,每分鐘都有 10 萬(wàn)多個(gè)請(qǐng)求,因?yàn)槿藗冎皇遣粩鄧L試登錄以購(gòu)買產(chǎn)品。我們的系統(tǒng)崩了,但是沒(méi)關(guān)系,人們只是想繼續(xù)回來(lái)。對(duì)這一現(xiàn)象最恰當(dāng)?shù)拿枋鼍褪?ldquo;爆炸“,人們到處飛。這里再展示一下《紐約時(shí)報(bào)》的那篇文章。大家可以看出那段時(shí)間事情進(jìn)展得有多不順利。
網(wǎng)絡(luò)服務(wù)時(shí)間崩潰
事情進(jìn)展不順利的原因是,雖然事情進(jìn)展的方式正常,但進(jìn)展速度太快了。這是 New Relic,非常簡(jiǎn)單,它顯示了我們的的 Ruby 時(shí)間和 MongoDB 時(shí)間。我們可以看到,Ruby 時(shí)間顯然占了我們應(yīng)用程序內(nèi)部所做的一大塊,MongoDB 時(shí)間只有一點(diǎn)點(diǎn)。
這是我們?cè)L問(wèn)網(wǎng)站時(shí),通??吹降臉幼印?0% 的時(shí)間是 Ruby 的,一點(diǎn)點(diǎn)是 MongoDB 的,還有其他一些服務(wù)我們沒(méi)有算在這里。但是,當(dāng)我們經(jīng)歷這些問(wèn)題時(shí),也就是當(dāng)網(wǎng)站宕機(jī)時(shí),它看起來(lái)是這樣的。出于一大堆不同的原因,這讓人感到困惑。
首先,Ruby 和 MongoDB 緊密相連。我們可以看到,由于某些原因,它們是同步的。很顯然,它們上升了很多。我的意思是,大家看一下左側(cè)的圖表,這是 4 秒的響應(yīng)時(shí)間,只是為了獲取 Ruby 和 Monogo。我們可以想像在那個(gè)時(shí)間點(diǎn),沒(méi)人能通過(guò)。
這是個(gè)讓人非常困惑的圖表。但是,更讓人困惑的是,在那個(gè)時(shí)間點(diǎn),這是我們擁有的唯一圖表。我們當(dāng)時(shí)盯著這圖表看,坐在那里討論說(shuō):“好吧,顯然 Mongo 很慢,但是 Ruby 也很慢。”“還會(huì)有其他情況嗎?”“伙計(jì),圖表就是這樣顯示的”。我們沒(méi)有使用工具深入研究正在發(fā)生的事情。
實(shí)際上,這張圖表是錯(cuò)誤的。但是,它讓我們?cè)谶@段時(shí)間陷入了很難搞的事情。我們花了好多天做荒謬的事。我們當(dāng)時(shí)最靠譜的做法應(yīng)該是:“如果我們調(diào)整內(nèi)核參數(shù)會(huì)怎樣?”那在當(dāng)時(shí)是有道理的。是的,也許內(nèi)核就是問(wèn)題所在。難搞的事情有一大堆。
驚醒夢(mèng)中人
為了解釋 Jordan 提出的周期,我來(lái)描述一下當(dāng)時(shí)發(fā)生的事情。我們會(huì)在每天早上,或用一整天的時(shí)間,進(jìn)行一次細(xì)致的一致負(fù)載測(cè)試。當(dāng)我們進(jìn)而分析它時(shí),我們完全搞錯(cuò)了方向。對(duì)于工具和周期的改進(jìn)部分,我們應(yīng)該做的是添加工具以幫助我們理解在負(fù)載測(cè)試過(guò)程中發(fā)生的事。在那個(gè)時(shí)間點(diǎn),我們沒(méi)有那么做。我們只是再次盯著同樣的工具,并思考古怪的想法。
為了解決這一問(wèn)題及其中一些擴(kuò)展問(wèn)題,我們做了每個(gè)人都最愛(ài)做的事——把責(zé)任推到數(shù)據(jù)庫(kù)和升級(jí)版本上。我們升級(jí)了 MongoDB 的每一個(gè)版本,以讓自己保持最新的版本。如果你熟悉 MongoDB 就會(huì)知道,我們一開(kāi)始使用的版本非常糟糕,因此升級(jí)版本會(huì)有一些相當(dāng)大的改進(jìn)。我們還做了另外一些事,比如把我們的集群分開(kāi)。
舉個(gè)例子說(shuō),我們有一個(gè)用戶集和一個(gè)事務(wù)集被托管在同一個(gè)主機(jī)上,我們就把它們分開(kāi)。這樣它們各自就會(huì)有更多的增長(zhǎng)空間,這讓我們擺脫了當(dāng)時(shí)的困境。然而,我們意識(shí)到,如果我們希望能夠承受更多的負(fù)載,還需要更好的方法。因?yàn)樵谶@個(gè)時(shí)間點(diǎn)上,我還是感覺(jué)流量一直在增加,也就是事情仍然在變壞。情況確實(shí)如此。
然而,我們?cè)谶@里得到了一個(gè)重大的教訓(xùn)。這比較明顯,但是把它說(shuō)清楚真的非常重要。好的工具會(huì)讓問(wèn)題顯現(xiàn)出來(lái)。但是,糟糕的工具會(huì)讓問(wèn)題變得模糊,讓人感到困惑,總有一天會(huì)讓我們看上去像個(gè)白癡。
Sitkin:回到我們的時(shí)間線,假設(shè)我們現(xiàn)在處于 2017 年中期?;氐竭@張我們一直在看的流量圖表。我們可以看到,在這次突破之后,我們被迫經(jīng)歷了一些慌亂、快速改進(jìn)了系統(tǒng),存活下來(lái)了。流量增加而又相對(duì)穩(wěn)定了。我們的流量到達(dá)了新基線水平。我們基本上在這個(gè)時(shí)間點(diǎn)處理這個(gè)問(wèn)題。我們可以看到,雖然有些波動(dòng),但我們基本上處于一種新的流量平衡中。
此時(shí),那些來(lái)自用戶的負(fù)載測(cè)試再也沒(méi)有使我們的站點(diǎn)以相同的方式宕機(jī)了。我們沒(méi)有跳進(jìn)這個(gè)周期,這個(gè)周期是我們后來(lái)才明白的。結(jié)果,我們對(duì)我們的工具做了很大變換,優(yōu)化了我們已有的工具。但是,我們沒(méi)有足夠的創(chuàng)造力來(lái)強(qiáng)迫我們的系統(tǒng)創(chuàng)建下一個(gè)故障模式。因此,我們?nèi)杂悬c(diǎn)不安,擔(dān)心未來(lái)。為了從周期的角度來(lái)說(shuō)明這一點(diǎn),最終我們將其親切地稱為 YOLO 負(fù)載測(cè)試階段,可以在這里看到我們的負(fù)載測(cè)試步驟的一周版本。
我們意識(shí)到,我們需要人為地返回這個(gè)負(fù)載測(cè)試,以便回到快速改進(jìn)周期。于是,我們只做了我們可以想到的最簡(jiǎn)單的事。我們基本上只是采用了一些現(xiàn)成的工具,運(yùn)行了一些合成負(fù)載測(cè)試。我們?cè)俅胃鶕?jù)開(kāi)發(fā)環(huán)境進(jìn)行了測(cè)試。我們不是很確定從哪里開(kāi)始最好,于是,我們就這么開(kāi)始工作了。
實(shí)際負(fù)載測(cè)試的支柱
在繼續(xù)詳細(xì)介紹我們所做的工作之前,現(xiàn)在是介紹我們稱之為實(shí)際負(fù)載測(cè)試支柱概念的好時(shí)機(jī)。這是一種在三個(gè)類別中分解負(fù)載測(cè)試策略的方法,是評(píng)估實(shí)際可行性的一種更好的方法。其中一個(gè)重點(diǎn)是,這三個(gè)類別中的每一個(gè)都可以單獨(dú)解決,同時(shí)提高了我們負(fù)載測(cè)試的真實(shí)性。我們不一定需要把它們一起提高,或者它們彼此之間甚至不必同樣重要。
第一個(gè)我們稱為數(shù)據(jù);現(xiàn)在展示的是我們數(shù)據(jù)庫(kù)中數(shù)據(jù)的形狀。類似于:在我們的測(cè)試環(huán)境中,每種類型有幾行?跟在生產(chǎn)中所有的相比,這些記錄之間的關(guān)系是否真實(shí)?接下來(lái)的是流量。這是從負(fù)載測(cè)試系統(tǒng)中出來(lái)的流量形狀。
我們可以問(wèn)問(wèn)自己,出現(xiàn)了多少請(qǐng)求?速率是多少?這些請(qǐng)求到達(dá)哪些端點(diǎn)?這些請(qǐng)求的分布是否匹配我們?cè)谏a(chǎn)環(huán)境中實(shí)際看到的流量類型?第三類是三者中最簡(jiǎn)單的,那就是構(gòu)成我們負(fù)載測(cè)試環(huán)境的物理系統(tǒng)是否匹配我們?cè)谏a(chǎn)中實(shí)際運(yùn)行的東西?我們?cè)谪?fù)載測(cè)試環(huán)境中運(yùn)行的這類服務(wù)器有多少?它們之間是如何關(guān)聯(lián)的?網(wǎng)絡(luò)層看起來(lái)都一樣嗎?
在這種情況下,回到我們?cè)谶@個(gè)時(shí)間點(diǎn)真正在做的。我們從一個(gè)名為 Locust 的現(xiàn)成開(kāi)源工具開(kāi)始。我們覺(jué)得,對(duì)我們來(lái)說(shuō),這是開(kāi)始實(shí)施分布式負(fù)載測(cè)試最容易的方法。我們知道,我們可以從中得到相當(dāng)大的吞吐量。大家如果不熟悉 Locust,我就簡(jiǎn)單介紹一下。
這是一個(gè)工具,允許我們用 Python 編寫模擬的用戶流,然后在多個(gè)節(jié)點(diǎn)上回放它們,以實(shí)施分布式負(fù)載測(cè)試。這其中,我們擁有的一個(gè)主控件是調(diào)試我們的模擬用戶池中的用戶數(shù)量,然后添加到這個(gè)池中的速度快慢。
再多講一些細(xì)節(jié)。這是 Locust 的基本架構(gòu)圖。我們有一個(gè)主節(jié)點(diǎn),我們與它交互來(lái)控制測(cè)試,然后,它控制一群從屬節(jié)點(diǎn)。這些從屬節(jié)點(diǎn)中的每一個(gè)負(fù)責(zé)維護(hù)一個(gè)小用戶池,這些用戶正運(yùn)行在我們用 Python 編寫的模擬用戶流中。
在這個(gè)時(shí)間點(diǎn)上,這是我們的第一次嘗試。最終,這個(gè)測(cè)試對(duì)我們來(lái)說(shuō)就是個(gè)玩具。它沒(méi)有真正提供我們所需的結(jié)果類型。但是,我們沒(méi)有真正理解它沒(méi)有提供的原因,也沒(méi)有真正相信它提供給我們的結(jié)果。但是,盡管存在這些問(wèn)題,它確實(shí)有助于我們更好地理解一個(gè)良好的負(fù)載測(cè)試系統(tǒng)應(yīng)有的樣子。
從我們剛剛介紹的這些支柱的角度來(lái)看,我們知道,數(shù)據(jù)和系統(tǒng)與生產(chǎn)不匹配。這是一種設(shè)計(jì)。我們知道,我們剛剛的測(cè)試只是用一種幼稚的先通過(guò)方式來(lái)實(shí)驗(yàn)。但真正的問(wèn)題是,我們不了解系統(tǒng)輸出流量的方式在哪些方面是不現(xiàn)實(shí)的。我們還沒(méi)有建立一個(gè)提高現(xiàn)實(shí)性的流程,甚至沒(méi)有創(chuàng)建這個(gè)初始用戶流。我們并沒(méi)有根據(jù)基本原理來(lái)做這件事。因此,該系統(tǒng)永遠(yuǎn)不會(huì)成為我們工具箱中的重要工具,因?yàn)槲覀儾恍湃嗡G珊系氖?,這也很快變得無(wú)關(guān)緊要。
圣杯(the holy grail)
Demi:因?yàn)樵?2017 年稍晚的時(shí)候,也就是 2017 年 10 月,加密貨幣真正成為主流?,F(xiàn)在,我們把我們工作的公司稱為“媽媽都知道“的公司了。我們的應(yīng)用程序在應(yīng)用程序商店下載排行榜上排名第一,新聞報(bào)道開(kāi)始的風(fēng)格變成這樣了:“比特幣狂熱”,“加密貨幣狂熱”,“我們應(yīng)該買點(diǎn)加密貨幣嗎?”,“我們是否應(yīng)該把錢都投資到加密貨幣上?”
我們的流量現(xiàn)在呈現(xiàn)這種趨勢(shì)。這條紅線是我為了擴(kuò)展而隨意畫的。并且對(duì)更大規(guī)模,流量會(huì)有更大的躍升,這也就是我們之前宕機(jī)的原因。而在這段時(shí)間里,情況沒(méi)有那么糟糕。我們肯定會(huì)在某些地方出故障,這取決于我們跟得有多近,信不信由你們。但是,我們能夠生存下來(lái)的原因是,我們這里有個(gè)東西,我們把它稱為“容量周期的圣杯“。
為了解決這個(gè)問(wèn)題,也就是我們認(rèn)識(shí)到的基本問(wèn)題,我們進(jìn)入了這個(gè)周期的節(jié)奏。比如,我們會(huì)在凌晨 4:30 醒來(lái),這時(shí)候東海岸的人們會(huì)在想:“我應(yīng)該買比特幣嗎?”他們就開(kāi)始對(duì)我們的網(wǎng)站進(jìn)行狂轟濫炸。我們花了一個(gè)早上只是為了保持網(wǎng)站在線。午餐時(shí),我們會(huì)分析結(jié)果:今天宕機(jī)的原因是什么?明天我們又會(huì)因?yàn)槭裁村礄C(jī)?
例如,假設(shè)我們?cè)?Mongo 上的用戶集合現(xiàn)在已經(jīng)被分解成一個(gè)新的集群,我們沒(méi)有更多空間進(jìn)行垂直擴(kuò)展。那么我們能做些什么?于是,我們花上一個(gè)晚上試圖改進(jìn)。我們添加檢測(cè)以增加清晰度,也就是可以通過(guò)添加新功能來(lái)改進(jìn)。然后,第 2 天,我們?cè)俅螠y(cè)試負(fù)載。這個(gè)周期會(huì)繼續(xù)下去。每天我們醒來(lái),喝杯咖啡,“好,現(xiàn)在來(lái)個(gè)負(fù)載測(cè)試,”然后,下午來(lái)分析發(fā)生的事,并改進(jìn)工具。
這是在這段時(shí)間,我們?yōu)樵撚脩艏核龅钠渲幸恍┲匾虑?。在一個(gè)周末,我們利用了我們稱之為 Memcached 的標(biāo)識(shí)緩存添加了一個(gè)完整的緩存層。這使用戶集群的負(fù)載下降了 90%。這給我們帶來(lái)了足夠的余量,至少夠用幾周。
它允許我們堅(jiān)持到第二天并解決下一個(gè)問(wèn)題。這個(gè)流程讓我們解決了問(wèn)題。它也告訴了我們一個(gè)重要的道理:當(dāng)我們?cè)诮鉀Q問(wèn)題時(shí),反饋越快,進(jìn)展也越快。每次我們經(jīng)歷這個(gè)周期,就是一個(gè)改進(jìn)的機(jī)會(huì)。我們經(jīng)歷的次數(shù)越多,能夠做出的改進(jìn)次數(shù)也越多。
Sitkin:讓我們回到我們的時(shí)間線。現(xiàn)在是 2018 年,我們剛剛經(jīng)歷過(guò)這個(gè)讓人痛苦、非常累人的周期。在這個(gè)周期中,我們得到了快速反饋周期和快速改進(jìn),并我們的系統(tǒng)上取得很多進(jìn)展。我們進(jìn)入了一個(gè)平穩(wěn)期,不是每天都能創(chuàng)下歷史新高。我們開(kāi)始不那么頻繁地創(chuàng)歷史新高了。你可能會(huì)認(rèn)為,我們會(huì)因?yàn)轶w驗(yàn)到這一點(diǎn)而感到寬慰。是的,相信我,在這幾天能多睡點(diǎn)真是太好了。
但是,每天早上我們都會(huì)有一種潛在的焦慮感,因?yàn)槲覀儾辉龠M(jìn)行這個(gè)奇妙的負(fù)載測(cè)試了。在增加我們的容量方面,我們沒(méi)有這種真正的催化想法,即我們要做的最重要的事情是什么。就周期而言,基本上,這是當(dāng)我們的負(fù)載測(cè)試逐步脫離我們控制的時(shí)候。有一點(diǎn)點(diǎn)害怕,因?yàn)槲覀冎廊匀淮嬖谝恍]之不去的性能問(wèn)題。很顯然,仍然要添加新功能,因?yàn)樾虑闆r還在繼續(xù)出現(xiàn)。
事實(shí)上,現(xiàn)在我們非常關(guān)注推出新貨幣。每次我們進(jìn)行這項(xiàng)工作時(shí),都可以看到略微不同的有趣的流量峰值,我們希望為這些情況做好準(zhǔn)備的不同流量模式。因此,我們?cè)谶@個(gè)時(shí)間點(diǎn)覺(jué)得有必要回到現(xiàn)實(shí),恢復(fù)這個(gè)負(fù)載測(cè)試步驟。我們需要能夠在測(cè)試環(huán)境中看到實(shí)際負(fù)載。
生產(chǎn)流量的捕獲及回放
基于我們?cè)?YOLO 合成負(fù)載測(cè)試方法上的經(jīng)驗(yàn),我們對(duì)來(lái)自合成系統(tǒng)的流量并不十分自信。在我們處理這個(gè)問(wèn)題的過(guò)程中,這個(gè)揮之不去的問(wèn)題出現(xiàn)了好幾次,那就是,我們?yōu)槭裁床荒茉谪?fù)載測(cè)試中使用實(shí)際的生產(chǎn)數(shù)據(jù)。這看起來(lái)是個(gè)很自然的問(wèn)題,非常有趣。這樣,在我們的負(fù)載測(cè)試中創(chuàng)建宕機(jī)的方式就會(huì)自然地與我們?cè)谏a(chǎn)中看到的宕機(jī)類型相匹配。其原因就是,我們實(shí)際上在利用實(shí)際的用戶行為。
此外,我們非常確定 MongoDB 是目前堆棧中最敏感的部分。它是共享最多的資源,這也就是之前我們宕機(jī)的原因。但是,一般來(lái)說(shuō),單獨(dú)測(cè)試某些東西不是好主意,我希望在這里使用另一個(gè)概念,以證明我們?yōu)槭裁从X(jué)得在像數(shù)據(jù)庫(kù)之類的東西中進(jìn)行單獨(dú)測(cè)試是有用的。
Neil Gunther 有一個(gè)通用可擴(kuò)展性定律(Universal Scalability Law)的概念。這是眾多描述系統(tǒng)拓?fù)鋽U(kuò)展的不同方法的其中之一。在這里的這張簡(jiǎn)單圖表上,我們已經(jīng)有了兩條線;虛線代表沒(méi)有共享資源的系統(tǒng)可以如何擴(kuò)展。隨著吞吐量的增長(zhǎng),負(fù)載和它有完美的線性關(guān)系,因此它可以進(jìn)行完美的線性擴(kuò)展。這兩者之間的關(guān)系沒(méi)有理由隨著負(fù)載的增加而變化,在該系統(tǒng)中沒(méi)有共享資源。
但是,與此相反,我們有這條紅線,它代表有共享資源的系統(tǒng)可以如何擴(kuò)展,因?yàn)橐獱?zhēng)奪共享資源(如數(shù)據(jù)庫(kù))。隨著負(fù)載的增加,吞吐量根據(jù)圍繞著共享資源的爭(zhēng)奪情況會(huì)下降。這個(gè)曲線的形狀會(huì)根據(jù)系統(tǒng)的實(shí)際設(shè)計(jì)變化。但是,這里的關(guān)鍵是,隨著系統(tǒng)的增長(zhǎng),我們?cè)谶@些資源上的收益遞減。
然后,隨著負(fù)載更多的增長(zhǎng),我們甚至開(kāi)始后退了一點(diǎn)點(diǎn)。這是一種說(shuō)法,在數(shù)據(jù)庫(kù)上的負(fù)載幾乎總是讓我們失敗。正是這個(gè)原因,它才是共享資源。大多數(shù)時(shí)候,我們對(duì)像應(yīng)用程序節(jié)點(diǎn)的東西有個(gè)相當(dāng)清晰的擴(kuò)展描述。這些節(jié)點(diǎn)是無(wú)狀態(tài)的,本身并不是共享資源,但它們通常會(huì)加載到有問(wèn)題的數(shù)據(jù)庫(kù)上。
mongoreplay 加農(nóng)炮(mongoreplay cannon)
因此,我們?cè)O(shè)計(jì)了圍繞負(fù)載測(cè)試數(shù)據(jù)庫(kù)的捕獲回放。最終,我們構(gòu)建了被稱為 Mongoreplay 加農(nóng)炮(Mongoreplay cannon)的東西。它由兩個(gè)主要部分組成;我們已經(jīng)有了 Mongoreplay 捕獲流程,和我們的應(yīng)用程序節(jié)點(diǎn)及后端工作人員有機(jī)地結(jié)合在一起。
它在數(shù)據(jù)庫(kù)驅(qū)動(dòng)上創(chuàng)建了一個(gè)額外的套接字,用于監(jiān)聽(tīng) Mongo 的有線流量并存儲(chǔ)它。然后,我們有另一個(gè)流程:稍后當(dāng)我們準(zhǔn)備實(shí)施負(fù)載測(cè)試時(shí),能夠交互并處理這些捕獲文件,把它們合成一個(gè)文件,然后以實(shí)際卷的倍數(shù)回放到測(cè)試環(huán)境。這些文件通常是我們生產(chǎn)數(shù)據(jù)庫(kù)的克隆。
這是一個(gè)巨大的勝利。當(dāng)我們?cè)谟懻搯为?dú)測(cè)試數(shù)據(jù)庫(kù)時(shí),這對(duì)我們來(lái)說(shuō)非常好。我們使用它可以很好地完成一些事情,如充滿信心地正確調(diào)整我們的集群規(guī)模。因?yàn)槲覀冎牢覀兛梢愿鶕?jù)數(shù)據(jù)庫(kù)的更改參數(shù)調(diào)整不同的可調(diào)參數(shù),并確切知道它在現(xiàn)實(shí)世界中的響應(yīng)方式。
又因?yàn)?,我們?cè)趹?yīng)用程序?qū)嶋H生成的數(shù)據(jù)庫(kù)上回放相同的負(fù)載。我們能夠在我們的測(cè)試環(huán)境中創(chuàng)建這些非?,F(xiàn)實(shí)的故障。當(dāng)然,接下來(lái)我們要考慮的是,如果這招真的好用,那么我們可以單獨(dú)測(cè)試數(shù)據(jù)庫(kù)。但是,用同樣的策略測(cè)試我們系統(tǒng)的其余部分會(huì)怎樣呢?
Demi:正如我們能看到的,很顯然,我們能夠單獨(dú)測(cè)試 MongoDB。因此,從字面上看,我們能夠在 Rails 和 Mongo 之間捕獲流量并回放之。這是我們能夠獲得的最接近的結(jié)果。然而,我們意識(shí)到,在我們的系統(tǒng)中有很多邊界,我們不得不想出一種方法來(lái)測(cè)試,該方法能夠與我們的 Mongoreplay 故事的成功相匹配。
這一切努力是為了確保我們不會(huì)在適當(dāng)?shù)臅r(shí)機(jī)宕機(jī)。如果我們不測(cè)試負(fù)載測(cè)試中的關(guān)系和邊界,那么,它可以告訴我們很多關(guān)于單獨(dú)系統(tǒng)的事情。但是,如果在我們的環(huán)境中稍微不那么突出的系統(tǒng)或其他共享資源之間發(fā)生新的回歸,那怎么辦?因此,我們知道我們需要嘗試找到不同的方法。
流量、數(shù)據(jù)及系統(tǒng)
讓我們從流量開(kāi)始,回顧現(xiàn)實(shí)主義的三層或三個(gè)支柱。這些是我們以有效性為標(biāo)準(zhǔn)對(duì)它們進(jìn)行的排序。例如,最底層的、最不切實(shí)際或基本的測(cè)試方法是使用這種簡(jiǎn)單的單用戶流。因此,這意味著只測(cè)試當(dāng)用戶點(diǎn)擊三或四個(gè)頁(yè)面時(shí)所發(fā)生的事,就像我們?cè)谶\(yùn)行 A/B 測(cè)試或類似的東西一樣。
第二種,也許是更現(xiàn)實(shí)的方法,可以根據(jù)真實(shí)的用戶流做些像合成流量生成這類的事情。比如,我們可能會(huì)有個(gè)工具可以綜合地生成流量,但卻需要查看我們的日志數(shù)據(jù),以找出如何在新環(huán)境中進(jìn)行回放。最后,Holy Grail 是這種捕獲回放的想法。我們用的是完全真實(shí)的生產(chǎn)流量,我們只是把它指向其他內(nèi)容,并看看它的響應(yīng)情況。
順便提一下,捕獲回放聽(tīng)起來(lái)不錯(cuò)。我們碰到的主要問(wèn)題是,特別對(duì)流量來(lái)說(shuō),記錄 post body 是極其困難的。我們?cè)?post body 中存儲(chǔ)了很多敏感信息,針對(duì)非生產(chǎn)環(huán)境或者在生產(chǎn)環(huán)境中重放這些信息時(shí),會(huì)存在很多問(wèn)題。此外,很多用于后續(xù)請(qǐng)求的 ID 并沒(méi)有被確定地生成。因此,當(dāng)我們嘗試重放流量時(shí),很難匹配那些請(qǐng)求。結(jié)果,我們需要做的是以某種方式重寫它們,使其工作,這有損于現(xiàn)實(shí)性。
然后,回過(guò)來(lái)談?wù)剶?shù)據(jù)。最簡(jiǎn)單的方法就是,用 siege 測(cè)試開(kāi)發(fā)環(huán)境的方法來(lái)測(cè)試數(shù)據(jù)庫(kù),以便創(chuàng)建它們。只需要?jiǎng)?chuàng)建一些基本用戶,把它們插入負(fù)載測(cè)試框架中就可以了。下一個(gè)最佳選擇是,綜合生成數(shù)據(jù),但用更實(shí)際的方法來(lái)實(shí)現(xiàn)。實(shí)際查看用戶的布局、擁有很多賬號(hào)的用戶是否有很多以及這些用戶之間的關(guān)系,然后在我們的環(huán)境中綜合地創(chuàng)建這些東西。
最后,這里有排在前兩位的清除數(shù)據(jù)的方法。因此,我們可以使用生產(chǎn)數(shù)據(jù)庫(kù),把它放到較少的生產(chǎn)環(huán)境中或另一個(gè)生產(chǎn)環(huán)境中。但是,重要的是,要明確地刪除那些我們要保護(hù)的重要客戶信息。很顯然,獲取一個(gè)真實(shí)負(fù)載測(cè)試的最佳可能方法是在生產(chǎn)環(huán)境中對(duì)數(shù)據(jù)進(jìn)行實(shí)際的測(cè)試。
最后,來(lái)講講系統(tǒng),這是有道理的。但是,如果我們?cè)谝粋€(gè)簡(jiǎn)單的開(kāi)發(fā)環(huán)境中進(jìn)行測(cè)試,那得不到實(shí)際的結(jié)果。如果我們的集群大小有問(wèn)題,那么就不會(huì)產(chǎn)生實(shí)際的結(jié)果。然后,是創(chuàng)建生產(chǎn)平價(jià)環(huán)境。也許我們想做一個(gè)編譯框架,該框架可以創(chuàng)建我們的所有生產(chǎn)資源,只要把它指向另一個(gè) AWS 賬號(hào)并運(yùn)行就可以。這很現(xiàn)實(shí)。但是,很顯然,在生產(chǎn)中測(cè)試是最終的策略。我們得到了確切的生產(chǎn)環(huán)境,它具有所有的問(wèn)題和節(jié)點(diǎn)等等東西。
然而,我們開(kāi)始思考這個(gè)問(wèn)題時(shí),意識(shí)到捕獲回放方法很難,合成方法也很難。但是,我們是區(qū)塊鏈公司。我們?yōu)槭裁床荒苡脜^(qū)塊鏈解決方案來(lái)解決這個(gè)問(wèn)題?于是,我們決定采用大膽的新方法。因此,今天,我們很高興地宣布,在 Coinbase 發(fā)布 Load Testing Coin。
Load Testing Coin 是兼容 ERC20 的 coin,允許你告訴你的用戶來(lái)加載測(cè)試你的負(fù)載。我在開(kāi)玩笑。我們不希望把大家搞得太興奮。我們不得不這樣做,沒(méi)有隨便搞個(gè) Load Testing Coin,那是假的。但是,事實(shí)上,那會(huì)很酷,對(duì)嗎?如果你只需要告訴用戶來(lái),… ,不是 coin,這個(gè) coin 是愚蠢的。說(shuō)真的,你會(huì)買它嗎?
Sitkin:是的,我也許會(huì)考慮買。
Demi:我們會(huì)加油的。抱歉,這個(gè)講話是要轉(zhuǎn)錄的,對(duì)嗎?可以掐掉這段嗎?所以這里的關(guān)鍵在于,理想的解決方案是告訴實(shí)際用戶到網(wǎng)站來(lái)做真實(shí)的事情。就像發(fā)生在我們身上的一樣,我們希望根據(jù)需要?jiǎng)?chuàng)建密碼狂熱,但是,如果我們能激勵(lì)人們加入,那就好了。
不幸的是,這個(gè)想法被否決了。但是,事實(shí)是,我們決定要做的是,回到我們跟 Locust 的最初策略上。我們決定看看,根據(jù)這些層,我們可以對(duì)這個(gè)策略做多少改進(jìn)?我們?nèi)绾窝刂@些層往上走,并把這個(gè)策略改進(jìn)為我們?nèi)粘9ぷ髦锌梢杂玫膶?shí)際東西?
實(shí)踐中的容量周期
Sitkin:因此,正如 Luke 所說(shuō)的,我們回到我們之前被稱為 YOLO 的測(cè)試策略。但是,我們從這個(gè)新起點(diǎn)開(kāi)始,更好地了解我們需要負(fù)載測(cè)試系統(tǒng)做什么。因此,在這一節(jié)里,我將逐步介紹在我們的實(shí)際日常工作中應(yīng)用這個(gè)容量周期可能的感覺(jué)。就采取負(fù)載系統(tǒng)而言,負(fù)載系統(tǒng)處于一個(gè)非?;镜臓顟B(tài),然后,使用我們的周期來(lái)增加其真實(shí)性。最終,找到我們系統(tǒng)的一些有趣的擴(kuò)展問(wèn)題。
這個(gè)示例的設(shè)置在這里,我們打算盡快開(kāi)始。我們將其范圍縮小到剛夠用規(guī)范工廠創(chuàng)建種子數(shù)據(jù)。我們可以通過(guò)數(shù)據(jù)獲得現(xiàn)實(shí)基線水平。然后,對(duì)于流量,我們剛打算重新創(chuàng)建腳本,只是一個(gè)單用戶流的單個(gè)簡(jiǎn)化版本,只是那些最基本的可能工作。然后,系統(tǒng)變成基于我們已經(jīng)在運(yùn)行的開(kāi)發(fā)環(huán)境,即位于負(fù)載平衡器背后的少數(shù)節(jié)點(diǎn),沒(méi)有后臺(tái)工作人員。然后,我們的三個(gè)主要后臺(tái)數(shù)據(jù)庫(kù)每個(gè)只有一個(gè)實(shí)例。因此很直接,很簡(jiǎn)單,很精簡(jiǎn)。
我們開(kāi)始吧。我們進(jìn)行第一個(gè)負(fù)載測(cè)試,每秒最多 400 個(gè)請(qǐng)求。首先,Redis 上的 CPU 得到了充分利用。我們到達(dá)了上限。因此,很自然地,我們會(huì)深入查看系統(tǒng)是如何布局的。很明顯,這里的問(wèn)題是,我們通過(guò)運(yùn)行幾個(gè)不同的 Redis 集群來(lái)隔離生產(chǎn)中的工作負(fù)載,然后在我們的測(cè)試環(huán)境中,我們只運(yùn)行這個(gè)服務(wù)一切的集群。
因此,這是一個(gè)快速的循環(huán)周期。很明顯,我們?cè)谶@里能做的最簡(jiǎn)單的事情是,讓我們的系統(tǒng)更加真實(shí)。于是,我們打算通過(guò)打破 Redis 集群和測(cè)試環(huán)境來(lái)改進(jìn)層,以匹配我們?cè)谏a(chǎn)環(huán)境中所運(yùn)行的東西。
好了,那么,讓我們?cè)俅谓?jīng)歷這個(gè)周期。結(jié)果,這一次,我們?cè)谕粋€(gè)時(shí)間點(diǎn)宕機(jī)了??纯次覀?Redis 集群 CPU 的統(tǒng)計(jì)數(shù)據(jù),我們又一次看到其中之一滿負(fù)荷運(yùn)作。事實(shí)證明,我們實(shí)際上只是忘了禁用一個(gè)跟蹤工具,該工具消耗了大量計(jì)算資源,而在生產(chǎn)中我們不使用它。因此,我們又有了一個(gè)好機(jī)會(huì)來(lái)提高我們的負(fù)載測(cè)試環(huán)境中的系統(tǒng)類別的真實(shí)性,即只需要禁用該工具。因此,這是又一個(gè)快速反饋周期。
好,我們?cè)賮?lái)測(cè)試一下。這次,我們走得更遠(yuǎn)一些,每秒有 850 個(gè)請(qǐng)求。再我們的系統(tǒng)中查看這些指標(biāo),這次發(fā)生了不同的事情。我們查看 Redis 狀態(tài),看上去都沒(méi)問(wèn)題。我們查看 Mongo 統(tǒng)計(jì)數(shù)據(jù),看上去也沒(méi)問(wèn)題。所以我們縮小了查看范圍,我們只查看了在這個(gè)端點(diǎn)上我們實(shí)際看到的生產(chǎn)中的請(qǐng)求,還有我們?cè)谪?fù)載測(cè)試系統(tǒng)中看到的請(qǐng)求的端到端跟蹤,并且所有內(nèi)容看起來(lái)幾乎相同。 但顯然,出現(xiàn)問(wèn)題比我們預(yù)期的時(shí)間要早。 但事實(shí)證明,我們注意到我們的應(yīng)用程序節(jié)點(diǎn)上的 CPU 滿負(fù)荷了。 基本上,Ruby 時(shí)間是問(wèn)題的根源。
我們?cè)谶@里有另一個(gè)機(jī)會(huì)來(lái)提高系統(tǒng)中的真實(shí)性,可以通過(guò)匹配應(yīng)用程序節(jié)點(diǎn)和我們?cè)谏a(chǎn)中實(shí)際運(yùn)行的支持服務(wù)之間的比例來(lái)實(shí)現(xiàn)。最簡(jiǎn)單的方法是增加在測(cè)試環(huán)境中運(yùn)行的應(yīng)用程序節(jié)點(diǎn)數(shù)量,因?yàn)檫@讓我們與生產(chǎn)系統(tǒng)更為接近。因此,我們可以很快地做出改變,并再次完成該周期。
第四次的時(shí)候,我們走得更遠(yuǎn),每秒有 1500 個(gè)請(qǐng)求。這一次,出現(xiàn)的第一件事是,我們 MongoDB 集群上的 CPU 負(fù)載太高了。如果你們經(jīng)常使用 MongoDB,應(yīng)該知道 mloginfo 這個(gè)出色的工具。我們使用了這個(gè)工具。這確實(shí)是個(gè)非常好的工具,可以用于解析 MongoDB 服務(wù)日志,并提供特定排序細(xì)分,特別是那些查詢形狀在系統(tǒng)中是又昂貴又慢的。
并且,它給我們指出,有一個(gè)單獨(dú)的、從未出現(xiàn)過(guò)的昂貴的查詢?cè)谶@里排名很高。這種情況向我們指出一個(gè)事實(shí),即在負(fù)載測(cè)試系統(tǒng)和生產(chǎn)中的數(shù)據(jù)形狀之間可能有重大的差異。因此,這里我們意識(shí)到,在每次負(fù)載測(cè)試運(yùn)行之間,我們沒(méi)有正確地重置我們的數(shù)據(jù)庫(kù)狀態(tài)。這給我們指出了一個(gè)事實(shí),我們需要增加數(shù)據(jù)類別的真實(shí)性,例如修復(fù)此重置腳本。
現(xiàn)在,我們使用改進(jìn)的負(fù)載測(cè)試環(huán)境進(jìn)行另一次測(cè)試運(yùn)行。我們?cè)诿棵?1400 次請(qǐng)求時(shí)出錯(cuò),非常類似的范圍。但是這一次,在 MongoDB 上的 CPU 統(tǒng)計(jì)數(shù)據(jù)又一次沒(méi)問(wèn)題。但是,通過(guò)查看跟蹤,我們看到,事實(shí)上來(lái)自 Memcached 的響應(yīng)很慢。那絕對(duì)是我們不習(xí)慣看到的。因此,我們對(duì)這個(gè)問(wèn)題進(jìn)行了一點(diǎn)研究,查看硬件級(jí)的統(tǒng)計(jì)數(shù)據(jù)。第一件事情是,我們嘗試針對(duì)單個(gè) T2 micro 運(yùn)行生產(chǎn)級(jí)的負(fù)載。T2 micro 是一個(gè)運(yùn)行 Memcached 的很小實(shí)例。因此,很顯然,很快就崩潰了。
同樣,這里有個(gè)簡(jiǎn)單的增加現(xiàn)實(shí)性的方法,就是提高 MongoDB 節(jié)點(diǎn)上實(shí)例的大小。這給我們另一個(gè)機(jī)會(huì)來(lái)完成一個(gè)周期。這一次,我們事實(shí)上做得相當(dāng)好;在這個(gè)用戶流上每秒有 1700 個(gè)請(qǐng)求。從資源的角度看,這實(shí)際上是特別昂貴的流。通常,我們?cè)谏a(chǎn)中不經(jīng)常碰到這種負(fù)載。在測(cè)試環(huán)境中達(dá)到每秒 1750 個(gè)請(qǐng)求是非常令人鼓舞的;這是個(gè)好結(jié)果。
Mongo 上的 CPU 統(tǒng)計(jì)數(shù)據(jù)看起來(lái)相當(dāng)不錯(cuò),就像我們的跨堆棧硬件統(tǒng)計(jì)數(shù)據(jù)一樣,看起來(lái)相當(dāng)健康。這讓我們稍作停頓,因?yàn)?,假如我們這里的用戶流事實(shí)上以非常逼真的方法來(lái)運(yùn)行的話,那么,我們自然不會(huì)期望能夠提供這類負(fù)載。
因此,這讓我們意識(shí)到,我們?cè)谏a(chǎn)環(huán)境中所看到的和我們?cè)谪?fù)載測(cè)試環(huán)境中所看到的之間,可能在流量類別上有差異。再深入一點(diǎn),我們注意到,這絕對(duì)是事實(shí)。為了在我們的應(yīng)用程序中重現(xiàn)這個(gè)用戶行為,我們只是運(yùn)行了一小部分真正需要點(diǎn)擊的端點(diǎn)。通過(guò)更好地調(diào)查和編寫更好的腳本,以更好地重建用戶在實(shí)際執(zhí)行該流程時(shí)在日志中所看到的內(nèi)容,那么,我們能夠提高流量類別的真實(shí)性。
最后一次運(yùn)行這個(gè)周期,這次,我們每秒最多得到 700 個(gè)請(qǐng)求。根據(jù)我們可能期望看到的情況,這可能更為現(xiàn)實(shí)。分析表明,我們大部分堆棧的硬件統(tǒng)計(jì)數(shù)據(jù),特別是 Mongo 沒(méi)有問(wèn)題。我們習(xí)慣于看到 Mongo 中的故障,因此,這常常是我們?cè)跀?shù)據(jù)庫(kù)層首先查看硬件統(tǒng)計(jì)數(shù)據(jù)的地方。
然而,我們 web 節(jié)點(diǎn)上的 CPU 也滿負(fù)荷。上次我們遇到這個(gè)問(wèn)題時(shí),我們覺(jué)得測(cè)試環(huán)境中的應(yīng)用程序節(jié)點(diǎn)增加了一倍,因?yàn)椋@讓我們到了更接近生產(chǎn)環(huán)境的地方。但是,這次我們不打算這么做,因?yàn)樵谪?fù)載測(cè)試中運(yùn)行的節(jié)點(diǎn)數(shù)量與在生產(chǎn)環(huán)境中的節(jié)點(diǎn)數(shù)量的比例是準(zhǔn)確的。因此,這么做就不對(duì),會(huì)因?yàn)樘砑痈喙?jié)點(diǎn)而破壞我們的真實(shí)性。
但是,當(dāng)我們真正挖掘一些分析以查看我們的應(yīng)用程序在 CPU 方面做了什么事、實(shí)際上占用了什么的時(shí)候,我們發(fā)現(xiàn)了一些有趣的事情。這是一個(gè)我們已經(jīng)意識(shí)到的問(wèn)題。但是,我們注意到,這個(gè)特定的性能問(wèn)題是造成我們這次測(cè)試失敗的瓶頸。我們有一些事件跟蹤的處理十分低效。
因此,這里,這是我們希望得到的結(jié)果。我們實(shí)際上發(fā)現(xiàn)了一個(gè)令人信服的現(xiàn)實(shí)瓶頸。當(dāng)我們達(dá)到這個(gè)負(fù)載水平時(shí),這可能會(huì)讓我們?cè)谏a(chǎn)中宕機(jī)。實(shí)際上,這里要做的正確的事情是應(yīng)用修復(fù)。因此,我們改進(jìn)了系統(tǒng)?,F(xiàn)在我們可以跳回到循環(huán)周期中,并獲得更多的見(jiàn)解。
我把這個(gè)例子留在這里。但是,我希望,通過(guò)講解這個(gè)真實(shí)世界的例子,我已經(jīng)讓你知道,這個(gè)快速反饋周期有多么的強(qiáng)大。它可以在測(cè)試下改進(jìn)系統(tǒng),也可以改進(jìn)測(cè)試系統(tǒng)本身。循環(huán)周期的每次迭代都是一個(gè)改進(jìn)這些東西其中之一的機(jī)會(huì)。不久之后你就會(huì)發(fā)現(xiàn),事實(shí)上最重要的問(wèn)題在哪里。
關(guān)于這些問(wèn)題,還要注意一件重要的事情,即我們也許意識(shí)到我們的系統(tǒng)有很多潛在的性能問(wèn)題。但是,真正的價(jià)值在于,它迫使這些問(wèn)題中的其中一個(gè)變?yōu)樽钔怀龅?、最可能讓我們失敗的?wèn)題。于是,這讓我們的工作計(jì)劃變得非常容易。這是最重要的事,它實(shí)際會(huì)把能力提升到一個(gè)新的水平。
現(xiàn)在,我們?cè)谶@里,對(duì)未來(lái)有一些更大的計(jì)劃。但是,我希望在本節(jié)留下一個(gè)經(jīng)驗(yàn),即我們都在負(fù)載測(cè)試環(huán)境中追求真實(shí)性。但是,關(guān)鍵在于,隨著我們每一步都在增加真實(shí)性,這個(gè)過(guò)程就和最終目標(biāo)一樣重要,因?yàn)槲覀円宦飞弦獙W(xué)很多東西。
未來(lái)
Demi:我們今天就是為此事而來(lái)的。我們現(xiàn)在在用的這個(gè)負(fù)載是為新貨幣的發(fā)行做準(zhǔn)備的。現(xiàn)在,這更像是 Luke 和 Jordan 的工具。我們能夠用它來(lái)找出和確認(rèn)每次我們發(fā)行新貨幣時(shí)會(huì)引發(fā)流量激增的任何事情。我們可以測(cè)試那些已知的在這些過(guò)程中將會(huì)變得突出的流,并確保沒(méi)有在它們發(fā)生前就存在,而我們卻還沒(méi)有發(fā)現(xiàn)的瓶頸。
我們目前正在增加這些測(cè)試的真實(shí)性。構(gòu)建自動(dòng)化方法來(lái)了解最新的流量模式,并把它們應(yīng)用到我們實(shí)際在運(yùn)行的測(cè)試方法中,這是我們目前的首要任務(wù)。同時(shí),我們要繼續(xù)改進(jìn)我們使用數(shù)據(jù)的方法。我們希望很快得到的結(jié)論是,我們的流量基于完全真實(shí)的流量,并且,我們的數(shù)據(jù)基于真實(shí)的清洗用戶數(shù)據(jù)。理想情況下,我們的系統(tǒng)也是一樣的。
這個(gè)周期將繼續(xù)指導(dǎo)我們。我們對(duì)這個(gè)容量周期感到非常興奮。我們?cè)趦?nèi)部對(duì)每個(gè)人宣傳此周期的有效性;有些人相信也有些人不信。但是,我們內(nèi)部真正要做的就是堅(jiān)持這個(gè)想法。我們不希望這只是個(gè) Luke 和 Jordan 的工具。因?yàn)?Luke 和 Jordan 的工具無(wú)法長(zhǎng)久存活。當(dāng)我們?cè)谧銎渌虑闀r(shí)分心了,怎么辦?如果這個(gè)工具開(kāi)始分離崩析,怎么辦?它會(huì)變得毫無(wú)用途。
我們正在嘗試做的是,創(chuàng)建一個(gè)可重復(fù)的持續(xù)元素以實(shí)現(xiàn)把我們的代碼交付到生產(chǎn)中。我們希望為大家創(chuàng)建這個(gè)本質(zhì)上是快速反饋的循環(huán)周期。因此,當(dāng)有人推動(dòng)新的生產(chǎn)變革時(shí),他們應(yīng)該知道它會(huì)不會(huì)影響生產(chǎn)工作中的績(jī)效。因此,我們處理這個(gè)問(wèn)題的一些方法可能成為壓縮測(cè)試環(huán)境中構(gòu)建過(guò)程的一部分,比如一個(gè)非常一致的環(huán)境。我們能夠處理多少請(qǐng)求來(lái)掌控最重要的流?這些是我們現(xiàn)在要關(guān)注的事情。
教訓(xùn)
但是,在我們離開(kāi)之前,我想再快速回顧一下我們的教訓(xùn)。首先,良好的工具會(huì)讓問(wèn)題浮現(xiàn)出來(lái),而糟糕的工具會(huì)使問(wèn)題變得模糊不清,讓我們感到困惑。我認(rèn)為,這適用于幾乎任何事情,特別是,如果我們是那些經(jīng)常在生產(chǎn)中挖掘問(wèn)題的人。如果我們沒(méi)有合適的工具,那么就添加合適的工具。如果我們不了解我們的工具,那么要保持好奇,去研究它。不要以為我們看到的就是實(shí)際存在的。
更快的反饋意味著更快的進(jìn)展。這適用于一切,但是,特別適用于我們的生存能力,以及在這些瘋狂流量增長(zhǎng)時(shí)期有所發(fā)展。這只是因?yàn)椋覀兡軌蚴褂眠@個(gè)快速反饋來(lái)指導(dǎo)我們采取的行動(dòng)。最終,我們使用簡(jiǎn)化的負(fù)載測(cè)試環(huán)境獲得出色的負(fù)載測(cè)試結(jié)果,并增加了真實(shí)性。
因此,當(dāng)我們進(jìn)行負(fù)載測(cè)試時(shí),過(guò)程和目標(biāo)一樣有價(jià)值。不要害怕深入,立即開(kāi)始以取得成果。我們過(guò)去曾經(jīng)遇到問(wèn)題,我們已經(jīng)經(jīng)歷了無(wú)數(shù)次宕機(jī)。我們一開(kāi)始就想到真實(shí)性,并試圖讓一切都和生產(chǎn)環(huán)境中的一樣,但是,在這個(gè)過(guò)程中,我們失去了一路上所學(xué)到的東西。
演講到此結(jié)束。最終,我們學(xué)到了關(guān)于容量規(guī)劃的很多真正有價(jià)值的經(jīng)驗(yàn)教訓(xùn)。我們當(dāng)然希望這個(gè)演講能幫助你避免犯我們已經(jīng)犯過(guò)的錯(cuò)。這是我們的推特號(hào)。但是,我們真的很想知道你們是如何在現(xiàn)場(chǎng)進(jìn)行負(fù)載測(cè)試的。希望這能激發(fā)一些有趣的對(duì)話。當(dāng)然,也可以在會(huì)議的其他時(shí)間通過(guò)推特聯(lián)系我們。
問(wèn)與答
參與者 1:謝謝你們的演講。很有見(jiàn)解,真實(shí)地反映了我們團(tuán)隊(duì)現(xiàn)在正在進(jìn)行的一些活動(dòng)。我很想從你們的經(jīng)驗(yàn)中學(xué)到東西,并把它應(yīng)用到我的團(tuán)隊(duì)中。我的一個(gè)問(wèn)題是,你們是從哪里觸發(fā)這些任務(wù)的?如果負(fù)載測(cè)試從生產(chǎn)負(fù)載中減去 5 倍、10 倍、50 倍,那么,你們會(huì)延伸到什么程度?你們是否會(huì)滿足于“好吧,目前的設(shè)計(jì)就這樣了,它能夠支持什么”?
Sitkin:Locust 提供了一個(gè) web UI,讓我們真正開(kāi)始測(cè)試。因此,這是使用這個(gè)開(kāi)源工具的好處之一。為了回答你關(guān)于我們?nèi)绾螞Q定將測(cè)試提升到什么程度的問(wèn)題,到目前為止,我們基本上把它設(shè)置在一個(gè)荒謬的程度上,我們?cè)趯ふ倚阅荛_(kāi)始下降、服務(wù)崩潰的時(shí)間點(diǎn)。
因此,在這個(gè)時(shí)間點(diǎn)上,我們真正在做壓力測(cè)試。我們?cè)趯ふ蚁到y(tǒng)停止工作的時(shí)間,然后只是測(cè)量這個(gè)程度是什么,不斷地將它增加。我們對(duì)想要達(dá)到的目標(biāo)有個(gè)粗略的想法,這是上次在解決中讓我們宕機(jī)原因的一個(gè)粗略倍數(shù)。但是,其中很大一部分只是意識(shí)到特定用戶流從哪里開(kāi)始消失。
參與者 1:還有一個(gè)問(wèn)題。由于依賴服務(wù)不受你們控制,你們是如何使用依賴服務(wù)的?如果這些是瓶頸,你們有什么建議來(lái)解決它們,甚至和這些團(tuán)隊(duì)合作來(lái)解決問(wèn)題?
Sitkin:是的,這就是我說(shuō)的負(fù)載測(cè)試中有點(diǎn)藝術(shù)性的一部分。我們?cè)陂_(kāi)始時(shí)非常簡(jiǎn)單的一個(gè)好處是,如果很難開(kāi)始,那么就放一邊。然后,當(dāng)你對(duì)一小部分流的真實(shí)性有信心時(shí),就可以開(kāi)始逐個(gè)把這些依賴項(xiàng)添加進(jìn)去。它們中的每一個(gè)都會(huì)有自己的特性,關(guān)于刪除或模擬的最好方法。
例如,作為加密貨幣公司,我們最終觸及的很多事情都是區(qū)塊鏈。當(dāng)然,我們必須創(chuàng)造性地剔除這些東西。我們用這樣的東西只能實(shí)現(xiàn)一定程度的真實(shí)性。因此,我發(fā)現(xiàn)很難對(duì)這類問(wèn)題給出一個(gè)普遍的答案。但是,我認(rèn)為,回到流程,一切都是關(guān)于逐一解決它們的問(wèn)題。獲得快速反饋周期,并一次只添加一個(gè)。不是一下子就追求完全的真實(shí)性。因?yàn)橥ㄟ^(guò)添加一個(gè)更改獲得的觀察結(jié)果可能非常有用。
參與者 2:謝謝你的精彩演講。我的問(wèn)題是,作為一家快速發(fā)展的公司,當(dāng)你們飛快地發(fā)布新產(chǎn)品和新功能時(shí),你們是否在生產(chǎn)中看到,數(shù)據(jù)的形狀和請(qǐng)求的模式經(jīng)常變化?如果是這樣,你們?nèi)绾巫屇銈兊呢?fù)載測(cè)試環(huán)境跟得上這些改變?
Demi:是的,特別是在流量方面,這是使用捕獲回放的主要好處之一。你可以保證捕獲并再次運(yùn)行,你可以保證流量是最新的。但是。我們現(xiàn)在的處理方法是。通過(guò)一個(gè)腳本運(yùn)行于數(shù)據(jù)的各個(gè)部分,然后我們提取其中存在的流。因此,存在一定的有狀態(tài)流。因此,你不能只是按順序回放請(qǐng)求,需要把它們拉出來(lái)。
我們能夠做的是,生成數(shù)據(jù)形狀,然后把它們應(yīng)用到 Locust 上。這個(gè)部分事實(shí)上更容易。數(shù)據(jù)的形狀實(shí)際上極其困難。這是我們完全沒(méi)解決的問(wèn)題。我們知道數(shù)據(jù)的形狀是什么樣的,我們實(shí)際上能夠使用我們數(shù)據(jù)團(tuán)隊(duì)在用的分析工具。
它們能夠在我們擁有的最大用戶上指導(dǎo)我們,比方說(shuō),10000 個(gè)不同的交易,對(duì)嗎?因此,我們可以在那里構(gòu)建一個(gè)分布,但是要保持它是最新的,我們根本沒(méi)解決這個(gè)問(wèn)題。這很難。但是,理想情況下,我們可以做的是,與這些工具進(jìn)行交互,并在我們清除和更新測(cè)試時(shí)進(jìn)行調(diào)整。
參與者 3:很棒的演講。我想知道,因?yàn)樯韶?fù)載測(cè)試是相當(dāng)昂貴的,基本上像攻擊,因?yàn)槲覀冊(cè)噲D讓網(wǎng)站宕機(jī)。我想知道,你是否找到一個(gè)方法可以計(jì)算實(shí)際情況下的理論極限值?是否可以根據(jù)一些例子,據(jù)此推斷并找到下一個(gè)瓶頸在哪里?
Sitkin:我接觸過(guò)一點(diǎn)通用擴(kuò)展理論的概念。當(dāng)我們實(shí)施這個(gè)有點(diǎn)巧妙的方法進(jìn)行負(fù)載測(cè)試時(shí),這些是我們要注意的事情。這也有助于我們形成關(guān)于什么可能出錯(cuò)的假設(shè)。但是,我認(rèn)為,我們發(fā)現(xiàn)進(jìn)入循環(huán)周期的好事是,我們很快就能測(cè)試這些假設(shè)。這也有點(diǎn)讓我們的性能理論方法變得更好,看到這些東西與現(xiàn)實(shí)世界的真實(shí)關(guān)系。但是,為了更直接地回答你的問(wèn)題,我們還沒(méi)有做類似學(xué)術(shù)研究的方法。我們一直在實(shí)踐中關(guān)注那些我們系統(tǒng)中產(chǎn)生的啟發(fā)。你有什么不同意見(jiàn)嗎?
Demi:代價(jià)不菲。現(xiàn)在我們要做的是,構(gòu)建一些真正復(fù)雜的技術(shù),以讓我們不因?yàn)樨?cái)務(wù)問(wèn)題而失敗。這就涉及到如何進(jìn)行擴(kuò)展。幸運(yùn)的是,AWS 使這個(gè)變得非常簡(jiǎn)單。數(shù)據(jù)庫(kù)擴(kuò)展的方式,應(yīng)用程序服務(wù)擴(kuò)展的方式,我們有一個(gè)腳本來(lái)啟動(dòng)和關(guān)閉。這是有幫助的。
但是,我們喜歡做的是,當(dāng)我們接受這種擠壓測(cè)試的想法時(shí),每一個(gè)進(jìn)入我們主要項(xiàng)目的拉取請(qǐng)求或提交,這就是我們打算做的事。我認(rèn)為,我們還沒(méi)有真正討論作為一個(gè)開(kāi)始,我們可以做什么,但是,使用我們?cè)跀D壓測(cè)試環(huán)境中目前所有的相同數(shù)據(jù),并在完整的生產(chǎn)環(huán)境中也這么做,來(lái)看看它們能處理多少。然后,我們可以進(jìn)行推斷,那將是個(gè)相當(dāng)不錯(cuò)的處理方法。你對(duì)這個(gè)想法有什么看法?
Sitkin:好主意。Luke。
Demi:一起做個(gè)演講不容易。我們必須對(duì)每個(gè)想法進(jìn)行交流。我很高興你喜歡這樣。