05/25 16:10 java程序員思維
之前幾篇文章對(duì)cat進(jìn)行了簡(jiǎn)介陌兑、安裝部署诀紊、代碼埋點(diǎn)隅俘,今天分享一下如何利用cat幫助我們做接口優(yōu)化。
為什么要接口性能優(yōu)化碌宴?
1.用戶(hù)體驗(yàn)差:接口訪問(wèn)速度慢蒙畴、如果一個(gè)頁(yè)面打開(kāi)需要好幾秒膳凝,用戶(hù)可能在頁(yè)面沒(méi)有完全打開(kāi)時(shí),就關(guān)掉頁(yè)面離開(kāi)了上煤,造成用戶(hù)流失著淆,通過(guò)性能優(yōu)化永部,減少服務(wù)器響應(yīng)時(shí)長(zhǎng),可提高用戶(hù)體驗(yàn)苔埋,較少用戶(hù)的流失。
2.雪崩效應(yīng):接口訪問(wèn)速度慢荞膘,會(huì)帶來(lái)雪崩效應(yīng)衫画,在微服務(wù)時(shí)代瓮栗,一個(gè)功能頁(yè)面可能需要調(diào)用多個(gè)服務(wù)接口瞄勾,如果某一個(gè)接口響應(yīng)速度慢进陡,會(huì)導(dǎo)致調(diào)用這個(gè)接口的服務(wù)也變得很慢微服,最后會(huì)導(dǎo)致所有的服務(wù)整體變慢以蕴。
什么樣的接口值得優(yōu)化丛肮?
1.調(diào)用頻繁且調(diào)用時(shí)間長(zhǎng)的接口,值得優(yōu)化焚廊。接口a被調(diào)用10000次咆瘟,平均調(diào)用時(shí)長(zhǎng)500ms诽里,接口b被調(diào)用10次,平均調(diào)用時(shí)長(zhǎng)3秒匿乃。優(yōu)化接口a,假設(shè)從500ms優(yōu)化到300ms泄隔,每一次節(jié)省200ms佛嬉,總體優(yōu)化時(shí)長(zhǎng)是200萬(wàn)毫秒暖呕。優(yōu)化接口b,即使從3秒優(yōu)化到100ms瓤逼,總體優(yōu)化時(shí)長(zhǎng)也只有29000毫秒。碰到這種情況建議優(yōu)化接口a霸旗,性?xún)r(jià)比更高诱告,更值得優(yōu)化。
2.調(diào)用次數(shù)少锄禽,但每次調(diào)用都異常(如超時(shí)無(wú)返回)靴姿,這樣的接口也必須優(yōu)化空猜。
如何使用cat定位需要優(yōu)化的接口?
挑選性?xún)r(jià)比高的接口(Transaction)
如上圖選擇的是cache-service應(yīng)用坝疼,CacheService.mutliExecute調(diào)用最頻繁钝凶,調(diào)用72萬(wàn)次耕陷,調(diào)用時(shí)長(zhǎng)也比較多据沈,可以作為被優(yōu)化的接口。
2.通過(guò)條件篩選嗜诀,提供Long-url隆敢、Long sql崔慧、Long sevice惶室、Long call篩選條件玄货,可以自行組合,調(diào)整時(shí)間長(zhǎng)度捣作。(Promblem)
3.調(diào)用出錯(cuò)誉结,必須要修改處理(promblem)
接口如何優(yōu)化?
查看調(diào)用鏈券躁,定位哪個(gè)方法調(diào)用時(shí)間長(zhǎng)
通過(guò)上圖惩坑,發(fā)現(xiàn)接口存在循環(huán)調(diào)用,優(yōu)化方案:調(diào)用批量操作接口也拜,減少接口調(diào)用次數(shù)以舒。
2.慢sql優(yōu)化方法
第一步:explain查看sql執(zhí)行計(jì)劃,確認(rèn)sql是否走索引慢哈。
第二步:確認(rèn)數(shù)據(jù)庫(kù)表是否建立索引,如果沒(méi)有索引滥沫,創(chuàng)建合適的索引,保持最左原則缀辩。
第三步:如果存在索引臀玄,沒(méi)有索引,分析其中原因
第四步:如果sql走了索引睬涧,依然很慢,緩存中間結(jié)果(異構(gòu)一張中間表或者將結(jié)果緩存到redis中)
具體優(yōu)化例子:
1.查詢(xún)庫(kù)存接口,數(shù)據(jù)庫(kù)表存在索引屎媳,而沒(méi)有使用到索引风响,是因?yàn)閿?shù)據(jù)庫(kù)表屬性類(lèi)型是varchar状勤,sql中使用了in,然而傳參的時(shí)候使用的是數(shù)值類(lèi)型葫盼,導(dǎo)致發(fā)生了數(shù)據(jù)類(lèi)型轉(zhuǎn)換,導(dǎo)致沒(méi)有走索引孩灯。優(yōu)化方案钱反,修改傳參類(lèi)型,使用字符串進(jìn)行傳參尚卫,優(yōu)化之后從300ms降低到60ms。(如果數(shù)據(jù)庫(kù)中是數(shù)值類(lèi)型怎爵,參數(shù)使用字符串類(lèi)型鳖链,即便發(fā)生了類(lèi)型轉(zhuǎn)換逞敷,依然可以走索引推捐,很奇怪)。sql中使用in焰络,作為多條件查詢(xún),有時(shí)候能走索引畏腕,有時(shí)候不能走索引,當(dāng)in中只有1個(gè)值的時(shí)候铭污,一定會(huì)走索引嘹狞,當(dāng)in中查詢(xún)的結(jié)果,達(dá)到所有記錄的一定比例的時(shí)候涧偷,不會(huì)走索引。
2.大表分頁(yè)優(yōu)化,定時(shí)任務(wù)隅肥,需要對(duì)大表分頁(yè)查詢(xún),可以使用子查詢(xún)的方式進(jìn)行優(yōu)化秃症。舉例:商品表100萬(wàn)條記錄,需要每天定時(shí)更新商品的銷(xiāo)量聚请。一般做法使用多線程,每個(gè)線程處理200條數(shù)據(jù)
select * from item limit 900000煤傍,200
越往后執(zhí)行,時(shí)間會(huì)越長(zhǎng)龄恋,因?yàn)閙ysql需要定位前90萬(wàn)條記錄,之后再取出后面的200條數(shù)據(jù)铣卡,因?yàn)闆](méi)有走索引煮落,所以會(huì)比較慢。
優(yōu)化方案一:利用子查詢(xún)
select * from item i,(select id from item limit 900000,200) as g where g.id = i.id
因?yàn)榭梢宰咚饕良#易硬樵?xún)使用到了覆蓋索引,不需要進(jìn)行第二次查詢(xún),可以提高查詢(xún)速度腋么。
優(yōu)化方案二:主鍵Id區(qū)間法
前提條件表結(jié)構(gòu)中存在自增長(zhǎng)主鍵徐块。取出表的最小值和最大值,將這兩個(gè)值進(jìn)行分段庇绽,每個(gè)線程處理一個(gè)區(qū)間辟狈。這樣查詢(xún)可以利用主鍵索引。
select * from item where id in (1,2,3,4,5,..200)
3.Jvm優(yōu)化
查詢(xún)庫(kù)存優(yōu)化之后壹蔓,走了索引之后披摄,的確快了很多套像,通過(guò)cat發(fā)現(xiàn),庫(kù)存服務(wù)有兩個(gè)應(yīng)用實(shí)例,有一個(gè)實(shí)例接口非承颍快,一個(gè)很慢,通過(guò)cat的Heartbeat發(fā)現(xiàn)慢的那臺(tái)機(jī)器存在full gc聊记,每隔一段時(shí)間就發(fā)生一次fullgc。
查看jvm的Gc命令
jstat -gcutil pid 2000
如果存在大量的YGC可以通過(guò)jmap命令定位哪些對(duì)象創(chuàng)建的多挨队,然后進(jìn)行代碼優(yōu)化情臭,盡量減少對(duì)象的創(chuàng)建竟秫》拾埽或者調(diào)整jvm參數(shù)浅侨,增加Eden區(qū)的大小。如果存在大量的fullGC這種情況要引起注意,因?yàn)橐淮蝔ullGC會(huì)消耗時(shí)間比較長(zhǎng),嚴(yán)重影響性能慎陵,需要調(diào)整jvm參數(shù)撞蚕。
jmap -histo pid | grep com.galaxy(包路徑)
top命令查看cpu舶赔,內(nèi)存等使用情況
top
cpu使用過(guò)高優(yōu)化方案
首先顯示線程列表:
ps -mp pid -o THREAD,tid,time
找到了耗時(shí)最高的線程28802,占用CPU時(shí)間快兩個(gè)小時(shí)了!
其次將需要的線程ID轉(zhuǎn)換為16進(jìn)制格式:
printf ''%x\n'' tid
最后打印線程的堆棧信息:
jstack pid |grep tid -A 30
無(wú)法獲取數(shù)據(jù)庫(kù)連接
可能是因?yàn)閿?shù)據(jù)庫(kù)在執(zhí)行修改表結(jié)構(gòu)造成了鎖表
select * from information_schema.processlist where db = 'item' and state like '%lock%'
需要對(duì)查出來(lái)的進(jìn)程進(jìn)行kill掉维贺¢偶耄可以通過(guò)命令
kill 進(jìn)程Id
獲取redis連接失敗,可能存在某些地方?jīng)]有釋放連接,可通過(guò)jstack命令進(jìn)行定位
jstack –l pid > jstack.txt
下載jstack.txt進(jìn)行分析,搜索Lock關(guān)鍵詞血崭,可以方便定位問(wèn)題。最好的方法,對(duì)連接的操作钻洒,進(jìn)行統(tǒng)一的封裝,不留給開(kāi)發(fā)人員犯錯(cuò)的機(jī)會(huì)。
遇到問(wèn)題不可怕,可怕的是同樣的問(wèn)題重復(fù)犯。將開(kāi)發(fā)過(guò)程中遇到的問(wèn)題澜术,記錄下來(lái)盒延,總結(jié)定期復(fù)盤(pán),可避免重犯同樣的錯(cuò)誤畦贸。吃一塹君账,長(zhǎng)一智,特此記錄下來(lái)和大家分享,希望對(duì)你有所幫助。