6. 堪比JMeter的.Net压测工具 - Crank 实战篇 - 收集诊断跟踪信息与如何分析瓶颈
1. 前言
上面我們已經(jīng)做到了接口以及場(chǎng)景壓測(cè),通過控制臺(tái)輸出結(jié)果,我們只需要將結(jié)果收集整理下來,最后匯總到excel上,此次壓測(cè)報(bào)告就可以完成了,但收集報(bào)告也挺麻煩的,交給誰(shuí)呢……
找了一圈、沒找到愿意接手的人,該怎么辦呢……思考了會(huì)兒還是決定看看能否通過程序解決我們的難題吧,畢竟整理表格太累╯﹏╰
2. 收集結(jié)果
通過查閱官方文檔,我們發(fā)現(xiàn)官方提供了把數(shù)據(jù)保存成Json、csv、以及數(shù)據(jù)庫(kù)三種方式,甚至還有小伙伴積極的對(duì)接要把數(shù)據(jù)保存到Es中,那選個(gè)最簡(jiǎn)單的吧!
要不選擇Json吧,不需要依賴外部存儲(chǔ),很簡(jiǎn)單,我覺得應(yīng)該可試,試一下看看:輸入命令:
crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --json 1.json --profile local --profile crankAgent1 --description "wrk2-獲取用戶詳情" --profile defaultParamLocal最后得到結(jié)果:
{"returnCode": 0,"jobResults": {"jobs": {"load": {"results": {"http/firstrequest": 85.0,"wrk2/latency/mean": 1.81,"wrk2/latency/max": 1.81,"wrk2/requests": 2.0,"wrk2/errors/badresponses": 0.0,"wrk2/errors/socketerrors": 0.0,"wrk2/latency/50": 1.81,"wrk2/latency/distribution": [[{"latency_us": 1.812,"count": 1.0,"percentile": 0.0},{"latency_us": 1.812,"count": 1.0,"percentile": 1.0}]]}}}} }完整的導(dǎo)出結(jié)果
好吧,數(shù)據(jù)有點(diǎn)少,好像數(shù)據(jù)不太夠吧,這些信息怎么處理能做成報(bào)表呢,再說了數(shù)據(jù)不對(duì)吧,QPS、延遲呢?好吧,被看出來了,因?yàn)樾畔⑻?#xff0c;我刪了一點(diǎn)點(diǎn)(也就1000多行指標(biāo)信息吧),看來這個(gè)不行,用json的話還得配合個(gè)程序好難……
csv不用再試了,如果也是單個(gè)文本的話,也是這樣,還得配個(gè)程序,都不能單干,干啥都得搭伴,那試試數(shù)據(jù)庫(kù)如何
crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --sql "Server=localhost;DataBase=crank;uid=sa;pwd=P@ssw0rd;" --table "local" --profile local --profile crankAgent1 --description "wrk2-獲取用戶詳情" --profile defaultParamLocal我們根據(jù)壓測(cè)環(huán)境,把不同的壓測(cè)指標(biāo)存儲(chǔ)到不同的數(shù)據(jù)庫(kù)的表中,當(dāng)前是本地環(huán)境,即 table = local
最后我們把數(shù)據(jù)保存到了數(shù)據(jù)庫(kù)中,那這樣做回頭需要報(bào)告的時(shí)候,我查詢下數(shù)據(jù)庫(kù)搞出來就好了,終于松了一口氣,但好景不長(zhǎng),發(fā)現(xiàn)數(shù)據(jù)庫(kù)存儲(chǔ)也有個(gè)坑,之前json中看到的結(jié)果竟然在一個(gè)字段中存儲(chǔ),不過幸好SqlServer 2016之后支持了json,可以通過json解析搞定,但其中參數(shù)名有/等特殊字符,sql server處理不了,難道又得寫個(gè)網(wǎng)站才能展示這些數(shù)據(jù)了嗎??真的繞不開搭伴干活這個(gè)坑嗎?
微軟不會(huì)就做出個(gè)這么雞肋的東西,還必須要配個(gè)前端才能清楚的搞出來指標(biāo)吧……還得用vue、好吧,我知道雖然現(xiàn)在有blazer,可以用C#開發(fā),但還是希望不那么麻煩,又仔細(xì)查找了一番,發(fā)現(xiàn)Crank可以對(duì)結(jié)果做二次處理,可以通過script,不錯(cuò)的東西,既然sql server數(shù)據(jù)庫(kù)無法支持特殊字符,那我加些新參數(shù)取消特殊字符不就好了,新建scripts.profiles.yml
scripts: changeTarget: |benchmarks.jobs.load.results["cpu"] = benchmarks.jobs.load.results["benchmarks/cpu"]benchmarks.jobs.load.results["cpuRaw"] = benchmarks.jobs.load.results["benchmarks/cpu/raw"]benchmarks.jobs.load.results["workingSet"] = benchmarks.jobs.load.results["benchmarks/working-set"]benchmarks.jobs.load.results["privateMemory"] = benchmarks.jobs.load.results["benchmarks/private-memory"]benchmarks.jobs.load.results["totalRequests"] = benchmarks.jobs.load.results["bombardier/requests;http/requests"]benchmarks.jobs.load.results["badResponses"] = benchmarks.jobs.load.results["bombardier/badresponses;http/requests/badresponses"]benchmarks.jobs.load.results["requestSec"] = benchmarks.jobs.load.results["bombardier/rps/mean;http/rps/mean"]benchmarks.jobs.load.results["requestSecMax"] = benchmarks.jobs.load.results["bombardier/rps/max;http/rps/max"]benchmarks.jobs.load.results["latencyMean"] = benchmarks.jobs.load.results["bombardier/latency/mean;http/latency/mean"]benchmarks.jobs.load.results["latencyMax"] = benchmarks.jobs.load.results["bombardier/latency/max;http/latency/max"]benchmarks.jobs.load.results["bombardierRaw"] = benchmarks.jobs.load.results["bombardier/raw"]以上處理的數(shù)據(jù)是基于bombardier的,同理大家可以完成對(duì)wrk或者其他的數(shù)據(jù)處理
通過以上操作,我們成功的把特殊字符的參數(shù)改成了沒有特殊字符的參數(shù),那接下來執(zhí)行查詢sql就可以了。
SELECT Description as '場(chǎng)景',JSON_VALUE (Document,'$.jobs.load.results.cpu') AS 'CPU使用率(%)',JSON_VALUE (Document,'$.jobs.load.results.cpuRaw') AS '多核CPU使用率(%)',JSON_VALUE (Document,'$.jobs.load.results.workingSet') AS '內(nèi)存使用(MB)',JSON_VALUE (Document,'$.jobs.load.results.privateMemory') AS '進(jìn)程使用的私有內(nèi)存量(MB)',ROUND(JSON_VALUE (Document,'$.jobs.load.results.totalRequests'),0) AS '總發(fā)送請(qǐng)求數(shù)',ROUND(JSON_VALUE (Document,'$.jobs.load.results.badResponses'),0) AS '異常請(qǐng)求數(shù)',ROUND(JSON_VALUE (Document,'$.jobs.load.results.requestSec'),0) AS '每秒支持請(qǐng)求數(shù)',ROUND(JSON_VALUE (Document,'$.jobs.load.results.requestSecMax'),0) AS '每秒最大支持請(qǐng)求數(shù)',ROUND(JSON_VALUE (Document,'$.jobs.load.results.latencyMean'),0) AS '平均延遲時(shí)間(us)',ROUND(JSON_VALUE (Document,'$.jobs.load.results.latencyMax'),0) AS '最大延遲時(shí)間(us)',CONVERT(varchar(100),DATEADD(HOUR, 8, DateTimeUtc),20) ?as '時(shí)間' FROM dev;3. 如何分析瓶頸
通過上面的操作,我們已經(jīng)可以輕松的完成對(duì)場(chǎng)景的壓測(cè),并能快速生成相對(duì)應(yīng)的報(bào)表信息,那正題來了,可以模擬高并發(fā)場(chǎng)景,那如何分析瓶頸呢?畢竟報(bào)告只是為了知曉當(dāng)前的系統(tǒng)指標(biāo),而我們更希望的是知道當(dāng)前系統(tǒng)的瓶頸是多少,怎么打破瓶頸,完成突破呢……
首先我們要先了解我們當(dāng)前的應(yīng)用的架構(gòu),比如我們現(xiàn)在使用的是微服務(wù)架構(gòu),那么
應(yīng)用拆分為幾個(gè)服務(wù)?了解清楚每個(gè)服務(wù)的作用
服務(wù)之間的調(diào)用關(guān)系
各服務(wù)依賴的基礎(chǔ)服務(wù)有哪些、基礎(chǔ)服務(wù)基本的信息情況
舉例我們當(dāng)前的微服務(wù)架構(gòu)如下:
通過架構(gòu)圖可以快速了解到項(xiàng)目結(jié)構(gòu),我們可以看到用戶訪問web端,web端根據(jù)請(qǐng)求對(duì)應(yīng)去查詢r(jià)edis或者通過http、grpc調(diào)用服務(wù)獲取數(shù)據(jù)、各服務(wù)又通過redis、db獲取數(shù)據(jù)。
首先我們先通過crank把當(dāng)前的數(shù)據(jù)指標(biāo)保存入庫(kù)。調(diào)出其中不太理想的接口開始分析。
在這里我們拿兩個(gè)壓測(cè)接口舉例:
獲取首頁(yè)Banner、QPS:3800 /s (Get)
下單、QPS:8 /s (Post)
3.1. 獲取首頁(yè)Banner
通過單測(cè)首頁(yè)banner的接口,QPS是3800多不到4000這樣,雖然這個(gè)指標(biāo)還不錯(cuò),但我們?nèi)匀挥X得很慢,畢竟首頁(yè)banner就是很簡(jiǎn)單幾個(gè)圖片+標(biāo)題組合的數(shù)據(jù),數(shù)據(jù)量不大,并且是直連Redis,僅在Redis不存在時(shí)才查詢對(duì)應(yīng)服務(wù)獲取banner數(shù)據(jù),這樣的QPS實(shí)在不應(yīng)該,并且這個(gè)還是僅壓測(cè)單獨(dú)的banner,如果首頁(yè)同時(shí)壓測(cè)十幾個(gè)接口,那其性能會(huì)暴降十倍不止,這樣肯定是不行的
我們又壓測(cè)了一次首頁(yè)banner接口,發(fā)現(xiàn)有幾個(gè)疑點(diǎn):
redis請(qǐng)求數(shù)徘徊在3800左右的樣子,網(wǎng)絡(luò)帶寬占用1M的樣子,無法繼續(xù)上漲
查看web服務(wù),發(fā)現(xiàn)時(shí)不時(shí)的會(huì)有調(diào)用服務(wù)超時(shí)出錯(cuò)的問題,Db的訪問量有上漲,但不明顯,很快就下去了
思考: Redis的請(qǐng)求數(shù)與最后的壓測(cè)結(jié)果差不多,最后倒也對(duì)上了,但為什么redis的請(qǐng)求數(shù)這么低呢?難道是帶寬限制!!
雖然是單機(jī)redis,但4000也絕對(duì)不可能是它的瓶頸,懷疑是帶寬被限制了,應(yīng)該就是帶寬被限制了,后來跟運(yùn)維一番切磋后,得到結(jié)論是redis沒限制帶寬……
那為什么不行呢,這么奇怪,redis不可能就這么點(diǎn)并發(fā)就不行了,算了還是寫個(gè)程序試一下吧,看看是不是真的測(cè)試環(huán)境不給力,redis配置太差了,一番操作后發(fā)現(xiàn),同一個(gè)redis數(shù)據(jù),redis讀可以到6萬(wàn)8,不到7萬(wàn)、帶寬占用10M,redis終于洗清了它的嫌疑,此接口的QPS不行與Redis無關(guān),但這么簡(jiǎn)單的一個(gè)結(jié)構(gòu)為什么QPS就上不去呢……,如果不是redis的問題,那會(huì)不會(huì)是因?yàn)檎?qǐng)求就沒到redis上,是因?yàn)閴簻y(cè)機(jī)的強(qiáng)度不夠,導(dǎo)致請(qǐng)求沒到redis……當(dāng)時(shí)冒出來這個(gè)有點(diǎn)愚蠢的想法,那就增加壓測(cè)機(jī)的數(shù)量,通過更改負(fù)載壓測(cè)機(jī)配置,1臺(tái)壓測(cè)機(jī)升到了3臺(tái),但可惜的是單臺(tái)壓測(cè)機(jī)的指標(biāo)不升反降,最后所有壓測(cè)機(jī)的指標(biāo)加到一起正好與之前一臺(tái)壓測(cè)機(jī)的壓測(cè)結(jié)果差不多一樣,那說明QPS低與壓測(cè)機(jī)無關(guān),后來想到試試通過增加多副本來提升QPS,后來web副本由1臺(tái)提升到了3臺(tái),之前提到的服務(wù)調(diào)用報(bào)錯(cuò)的情況更加嚴(yán)重,之前只是偶爾有一個(gè)錯(cuò)誤,但提升web副本后,看到一大片的錯(cuò)誤
提示Thread is busy,很多線程開始等待
大量的服務(wù)調(diào)用超時(shí),DB查詢緩慢
最后QPS 1000多一點(diǎn),有幾千個(gè)失敗的錯(cuò)誤,這盲目的提升副本貌似不大有效,之前盡管Qps不高,但起碼也在4000,DB也沒事,這波神操作后QPS直降4分之3,DB還差點(diǎn)崩了,思想滑坡了,做了負(fù)優(yōu)化……
繼續(xù)思考,為何提升副本,QPS不升反降,為何出現(xiàn)大量的調(diào)用超時(shí)、為何DB會(huì)差點(diǎn)被干崩,我只是查詢個(gè)redis,跟DB有毛關(guān)系啊!奇了怪了,看看代碼怎么寫的吧……燒腦
public async Task<List<BannerResponse>> GetListAsync() {List<BannerResponse> result = new List<BannerResponse>();try{var cacheKey = "banner_all";var cacheResult = await _redisClient.GetAsync<List<BannerResponse>>(cacheKey);if (cacheResult == null){result = this.GetListServiceAsync().Result;_redisClient.SetAsync(cacheKey, result, new(){DistributedCacheEntryOptions = new(){AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(5)}}).Wait();}else{result = cacheResult;} }catch (Exception e){result = await this.GetListServiceAsync();}return result; }看了代碼后發(fā)現(xiàn),僅當(dāng)Reids查詢不到的時(shí)候,會(huì)調(diào)用對(duì)應(yīng)服務(wù)查詢數(shù)據(jù),對(duì)應(yīng)服務(wù)再查詢DB獲取數(shù)據(jù),另外查詢異常時(shí),會(huì)再次調(diào)用服務(wù)查詢結(jié)果,確保返回結(jié)果一定是正確的,看似沒問題,但為何壓測(cè)會(huì)出現(xiàn)上面那些奇怪現(xiàn)象呢……
請(qǐng)求超時(shí)、大量等待,那就是正好redis不存在,穿透到對(duì)應(yīng)的服務(wù)查詢DB了,然后壓測(cè)同一時(shí)刻數(shù)據(jù)量過大,同一時(shí)刻查詢到的Reids都是沒有數(shù)據(jù),最后導(dǎo)致調(diào)用服務(wù)的數(shù)量急劇上升,導(dǎo)致響應(yīng)緩慢,超時(shí)加劇,線程因超時(shí)釋放不及時(shí),又導(dǎo)致可用線程較少。
這塊我們查找到對(duì)應(yīng)的日志顯示以下信息
System.TimeoutException: Timeout performing GET MyKey, inst: 2, mgr: Inactive, queue: 6, qu: 0, qs: 6, qc: 0, wr: 0, wq: 0, in: 0, ar: 0, IOCP: (Busy=6,Free=994,Min=8,Max=1000), WORKER: (Busy=152,Free=816,Min=8,Max=32767)那么我們可以調(diào)整Startup.cs:
web服務(wù)調(diào)用底層服務(wù)太慢,那么提升底層服務(wù)的響應(yīng)速度(優(yōu)化代碼)或者提高處理能力(提升副本)
防止高并發(fā)情況下全部穿透到下層,增加底層服務(wù)的壓力
前兩點(diǎn)也是一個(gè)好的辦法,但不是最好的解決辦法,最好還是不要穿透到底層服務(wù),如果reids不存在,就放一個(gè)請(qǐng)求過去是最好的,拿到數(shù)據(jù)就持久化到redis,不要總穿透到下層服務(wù),那么怎么做呢,最簡(jiǎn)單的辦法就是使用加鎖,但加鎖會(huì)影響性能,但這個(gè)我們能接受,后來調(diào)整加鎖測(cè)試,穿透到底層服務(wù)的情況沒有了,但很可惜,請(qǐng)求數(shù)確實(shí)會(huì)隨著副本的增加而增加,但是實(shí)在是有點(diǎn)不好看,后來又測(cè)試了下另外一個(gè)獲取緩存數(shù)據(jù)的結(jié)果,結(jié)果QPS:1000多一點(diǎn),比banner還要低的多,兩邊明明都使用的是Reids,性能為何還有這么大的差別,為何我們寫的redis的demo就能到6萬(wàn)多的QPS,兩邊都是拿的一個(gè)緩存,差距有這么大?難道是封裝redis的sdk有問題?后來仔細(xì)對(duì)比了后來寫的redis的demo與banner調(diào)用redis的接口發(fā)現(xiàn),一個(gè)是直接查詢的redis的字符串,一個(gè)是封裝redis的sdk,多了一個(gè)反序列化的過程,最后經(jīng)過測(cè)試,反序列化之后性能降低了十幾倍,好吧看來只能提升副本了……但為何另外的接口也是從redis獲取,性能跟banner的接口不一樣呢!!
經(jīng)過仔細(xì)對(duì)比發(fā)現(xiàn),差別是信息量,QPS更低的接口的數(shù)據(jù)量更大,那結(jié)果就有了,隨著數(shù)據(jù)量的增加,QPS會(huì)進(jìn)一步降低,那這樣一來的話,增加副本的作用不大啊,誰(shuí)知道會(huì)不會(huì)有一個(gè)接口的數(shù)據(jù)量很大,那性能豈不是差的要死,那還怎么玩,能不能提升反序列化的性能或者不反序列化呢,經(jīng)過認(rèn)真思考,想到了二級(jí)緩存,如果用到了二級(jí)緩存,內(nèi)存中有就不需要查詢r(jià)edis,也不需要再反序列化,那么性能應(yīng)該有所提升,最后的結(jié)構(gòu)如下圖:
最后經(jīng)過壓測(cè)發(fā)現(xiàn),單副本QPS接近50000,比最開始提升12倍,并且也不會(huì)出現(xiàn)服務(wù)調(diào)用超時(shí),DB崩潰等問題、且內(nèi)存使用平穩(wěn)
此次壓測(cè)發(fā)現(xiàn)其banner這類場(chǎng)景的性能瓶頸在反序列化,而非Redis、DB,如果按照一開始不清楚其工作原理、盲目的調(diào)整副本數(shù),可能最后會(huì)加劇系統(tǒng)的雪崩,而如果我們把DB資源、Redis資源盲目上調(diào)、并不會(huì)對(duì)最后的結(jié)果有太大幫助,最多也只是延緩崩潰的時(shí)間而已
3.2. 下單
下單的QPS是8,這樣的QPS已經(jīng)無法忍受了,每秒只有十個(gè)請(qǐng)求可以下單成功,如果中間再出現(xiàn)一個(gè)庫(kù)存不足、賬戶余額不足、活動(dòng)資格不夠等等,實(shí)際能下單的人用一個(gè)手可以數(shù)過來,真的就這么慘……雖然下單確實(shí)很費(fèi)性能,不過確實(shí)不至于這么低吧,先看下下單流程吧
簡(jiǎn)化后的下單流程就這么簡(jiǎn)單,web通過dapr的actor服務(wù)調(diào)用order service,然后就是漫長(zhǎng)的查詢db、操作redis操作,因涉及業(yè)務(wù)代碼、具體代碼就不再放出,但可以簡(jiǎn)單說一下其中做的事情,檢查賬戶余額、反復(fù)的增加redis庫(kù)存確保庫(kù)存安全、檢查是否滿足活動(dòng)、為推薦人計(jì)算待結(jié)算傭金等等一系列操作,整個(gè)看下來把人看懵了,常常是剛看了上面的,看下面代碼的時(shí)候忘記上面具體干了什么事,代碼太多了,一個(gè)方法數(shù)千行,其中再調(diào)用一些數(shù)百行的代碼,真的吐血了,不免感嘆我司的開發(fā)小哥哥是真的強(qiáng)大,這么復(fù)雜的業(yè)務(wù)居然能這么"順暢"的跑起來,后面還有N個(gè)需求等待加到下單上,果然不是一般人
不過話說回來,雖然是業(yè)務(wù)是真的多,也真的亂,不過這樣搞也不至于QPS才只有8這么可憐吧,服務(wù)器的處理能力可不是二十幾年前的電腦可以比擬的,單副本8核16G的配置不支持這么拉胯吧,再看一下究竟誰(shuí)才是真正的幕后黑手……
但究竟哪里性能瓶頸在哪里,這塊就要出殺手锏了
通過Tracing可以很清楚的看到各節(jié)點(diǎn)的耗時(shí)情況,這將對(duì)我們分析瓶頸提供了非常大的幫助、我們看到了雖然有幾十次的查詢DB操作,但DB還挺給力,基本也再很短時(shí)間內(nèi)就給出了響應(yīng),那剩余時(shí)間耗費(fèi)到了哪里呢?我們看到整體耗時(shí)11s、但查詢Db加起來也僅僅不到1s,那么剩余操作都在哪里?要知道哪怕我們優(yōu)化DB查詢性能,減少DB查詢,那提升的性能對(duì)現(xiàn)在的結(jié)果也是微乎其微
結(jié)合Tracing以及下單流程圖,我們發(fā)現(xiàn)從Web到Order Service是通過actor來實(shí)現(xiàn)的,那會(huì)不是這里耗時(shí)影響的呢?
但dapr是個(gè)新知識(shí)、開發(fā)的小哥哥速度真快,這么快就用上dapr了(ˇ?ˇ)不知道小哥哥的頭發(fā)還有多少……
快速去找到下單使用actor的地方,如下:
[HttpPost] [Authorize] public async Task<CreateOrderResponse> CreeateOrder([FromBody] CreateOrderModel request) {string actionType = "SalesOrderActor";var salesOrderActor = ActorProxy.Create<ISalesOrderActor>(new ActorId(request.SkuList.OrderBy(sku => sku.Sku).FirstOrDefault().Sku), actionType);request.AccountId = Account.Id;var result = await salesOrderActor.CreateOrderAsync(request);return new Mapping<ParentSalesOrderListViewModel, CreateOrderResponse>().Map(result); }我們看到了這邊代碼十分簡(jiǎn)單,獲取商品信息的第一個(gè)sku編號(hào)作為actor的actorid使用,然后得到下單的actor,之后調(diào)用actor中的創(chuàng)建訂單方法最后得到下單結(jié)果,這邊的代碼太簡(jiǎn)單了,讓人心情愉快,那這塊會(huì)不會(huì)有可能影響下單速度呢?它是不是那個(gè)性能瓶頸最大的幕后黑手?
首先這塊我們就需要了解下什么是Dapr、Actor又是什么,不了解這些知識(shí)我們只能靠抓鬮來猜這塊是不是瓶頸了……
Dapr 全稱是Distributed Application Runtime,分布式應(yīng)用運(yùn)行時(shí),并于今年加入了 CNCF 的孵化項(xiàng)目,目前Github的star高達(dá)16k,相關(guān)的學(xué)習(xí)文檔在文檔底部可以找到,我也是看著下面的文檔了解dapr
通過了解actor,我們發(fā)現(xiàn)用sku作為actorid是極不明智的選擇,像秒殺這類商品不就是搶的指定規(guī)格的商品嗎?如果這樣一來,這不是在壓測(cè)actor嗎?這塊我們跟對(duì)應(yīng)的開發(fā)小哥哥溝通了下,通過調(diào)整actorid順利將Qps提升到了60作用,后面又通過優(yōu)化減少db查詢、調(diào)整業(yè)務(wù)規(guī)則的順序等操作順利將QPS提升到了不到一倍,雖然還是很低,不過接下來的優(yōu)化工作就需要再深層次的調(diào)整業(yè)務(wù)代碼了……
4. 總結(jié)
通過實(shí)戰(zhàn)我們總結(jié)出分析瓶頸從以下幾步走:
通過第一輪的壓測(cè)獲取性能差的接口以及指標(biāo)
通過與開發(fā)溝通或者自己查看源碼的方式梳理接口流程
通過分析其項(xiàng)目所占用資源情況、依賴第三方基礎(chǔ)占用資源情況以及Tracing更進(jìn)一步的確定瓶頸大概的點(diǎn)在哪幾塊
通過反復(fù)測(cè)試調(diào)整確定性能瓶頸的最大黑手
將最后的結(jié)論與相關(guān)開發(fā)、運(yùn)維人員溝通,確保都知曉瓶頸在哪里,最后優(yōu)化瓶頸
知識(shí)點(diǎn):
Dapr
手把手教你學(xué)Dapr系列
Tracing
Masa.BuildingBlocks
Masa.Contrib
OpenTracing 簡(jiǎn)介、關(guān)于OpenTracing后續(xù)我們也會(huì)開源,可以提前關(guān)注我們的開源項(xiàng)目
開源地址
MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks
MASA.Contrib:https://github.com/masastack/MASA.Contrib
MASA.Utils:https://github.com/masastack/MASA.Utils
MASA.EShop:https://github.com/masalabs/MASA.EShop
MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor
如果你對(duì)我們的 MASA Framework 感興趣,無論是代碼貢獻(xiàn)、使用、提 Issue,歡迎聯(lián)系我們
總結(jié)
以上是生活随笔為你收集整理的6. 堪比JMeter的.Net压测工具 - Crank 实战篇 - 收集诊断跟踪信息与如何分析瓶颈的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这是Blazor上传文件的最佳方式吗?
- 下一篇: 接口返回json对象出现套娃递归问题 |