摘要:最近閱讀了很多優(yōu)秀的網(wǎng)站性能優(yōu)化的文章,所以自己也想總結(jié)一些最近優(yōu)化的手段和方法。個(gè)人感覺性能優(yōu)化的核心是減少延遲,加速展現(xiàn)。初步以為是這個(gè)功能導(dǎo)致的服務(wù)掛起,詢問相關(guān)操作人員,得到當(dāng)時(shí)的操作過程。
最近閱讀了很多優(yōu)秀的網(wǎng)站性能優(yōu)化的文章,所以自己也想總結(jié)一些最近優(yōu)化的手段和方法。
個(gè)人感覺性能優(yōu)化的核心是:減少延遲,加速展現(xiàn)。
本文主要從產(chǎn)品設(shè)計(jì)、前端、后端和網(wǎng)絡(luò)四個(gè)方面來訴說優(yōu)化過程。
在網(wǎng)上看到一句話:好的性能是設(shè)計(jì)出來的,而不是優(yōu)化出來的。
感覺好有道理,如果將性能瓶頸扼殺在搖籃里,那么后期的維護(hù)成本將變得非常低,并且在避免改造后,都不需要浪費(fèi)資源了。
1)聊天改版
最近公司有個(gè)聊天活動(dòng)做改版,改版上線后驚喜的發(fā)現(xiàn),監(jiān)控?cái)?shù)據(jù)居然減少了將近20W。
更深一步的探究,才知道在頁面初始化時(shí),會(huì)發(fā)一個(gè)請(qǐng)求,去獲取一些文案,但其實(shí)這些文案都是寫死的,完全可以寫到頁面本地。
如果在產(chǎn)品設(shè)計(jì)時(shí),就不是通過接口讀取的方式,那么就可以大大減少瀏覽器和服務(wù)器之間的通信。
2)數(shù)據(jù)遷移
公司有一個(gè)審核系統(tǒng),最近審核人員反應(yīng)系統(tǒng)使用起來越來越卡。排查后發(fā)現(xiàn),定位到性能瓶頸,是因?yàn)閿?shù)據(jù)表巨大導(dǎo)致的,目前已有6千萬條。
其實(shí)在一開始設(shè)計(jì)時(shí),就該能預(yù)估到,未來的數(shù)據(jù)量,感覺還是偷懶了,想快速完成。感嘆前人挖坑,后人埋坑。
起初是想分表,但思慮后還是決定不那么做,最后采用的是MySQL歸檔。
前前后后花了兩周的時(shí)間,才將方案落地實(shí)現(xiàn),涉及到運(yùn)維、QA和我們前端組,人力成本無疑是巨大的。
其實(shí)在每次完成優(yōu)化后,可以再想想能不能將問題泛化,擴(kuò)大維度,想想其他地方是否有類似問題,總結(jié)經(jīng)驗(yàn)供他人學(xué)習(xí),以及對(duì)未發(fā)生的問題進(jìn)行預(yù)判。
3)大批量的504
這是在上線監(jiān)控平臺(tái)后不久發(fā)現(xiàn)的,504 的請(qǐng)求量太多,這類通信錯(cuò)誤居然占了25%~30% 左右。
經(jīng)過排查定位到一個(gè)常規(guī)的翻卡活動(dòng)中,產(chǎn)品設(shè)計(jì)出現(xiàn)了嚴(yán)重的問題。
在進(jìn)行一個(gè)翻卡操作時(shí)會(huì)請(qǐng)求兩個(gè)接口,并且每個(gè)接口各自發(fā)送 3 次通信,這樣會(huì)很容易發(fā)生 504 錯(cuò)誤,每天大約有1500個(gè)這樣的請(qǐng)求。
首先是給其中一張表加了個(gè)索引,然后是將兩個(gè)接口合并成一個(gè),并且每次返回 20 條以上的數(shù)據(jù),這樣就不用頻繁的發(fā)起請(qǐng)求了。
經(jīng)過改造后,每日的 504 請(qǐng)求從 1500 個(gè)左右降低到 200 個(gè)左右,減少了整整 7.5 倍,效果立竿見影,大部分的 504 集中在 22 點(diǎn)到 0 點(diǎn)之間,這段時(shí)間的活躍度比較高。
還有一個(gè)令人意外的發(fā)現(xiàn),那就是監(jiān)控日志的量每天也減少了 50W 條?!?/p>
前端的優(yōu)化手段非常多,常規(guī)的其實(shí)就是延遲請(qǐng)求和減少頁面渲染次數(shù)。
1)預(yù)請(qǐng)求
數(shù)據(jù)預(yù)請(qǐng)求是將數(shù)據(jù)預(yù)請(qǐng)求的時(shí)機(jī)由業(yè)務(wù)發(fā)起請(qǐng)求的時(shí)機(jī),提前到用戶點(diǎn)擊時(shí),并行發(fā)送數(shù)據(jù)請(qǐng)求,縮短數(shù)據(jù)等待時(shí)間。
這個(gè)需要客戶端配合,在Webview啟動(dòng)的時(shí)候,并行的去請(qǐng)求首屏需要的數(shù)據(jù)。
經(jīng)過觀察發(fā)現(xiàn)每次請(qǐng)求后端數(shù)據(jù)的API大概要花100~200ms,如果把這段時(shí)間省下來,那么也能減少白屏?xí)r間。
在與客戶端溝通時(shí),他們還是表現(xiàn)的比較抗拒的,在他們看來這點(diǎn)時(shí)間微不足道,還會(huì)增加他們的工作量。
有個(gè)人還一直強(qiáng)調(diào)瀏覽器內(nèi)置的緩存規(guī)則是一劑靈藥,絕對(duì)可以提升頁面的性能,經(jīng)過討價(jià)還價(jià)后敲定最終的預(yù)請(qǐng)求方案。
2)預(yù)加載和懶加載
預(yù)加載和懶加載特指的是圖片的加載,其實(shí)就是延遲請(qǐng)求時(shí)機(jī)。
兩者的核心算法就是計(jì)算圖片的相對(duì)位置,具體參考于此。
這兩招非常有效,可以說是立竿見影,尤其是頁面中圖片量較多以及尺寸較大時(shí),能瞬間提升頁面加載。
之前做過一次偏動(dòng)畫的宣傳頁,在進(jìn)入頁面時(shí),立刻請(qǐng)求所有圖片,直接白屏好幾十秒。
3)串行變并行
有一張活動(dòng)頁面,交互并不多,但是要展示的數(shù)據(jù)需要經(jīng)過后臺(tái)比較復(fù)雜的計(jì)算后才能得到。
一開始是將所有的數(shù)據(jù)都包含在一個(gè)接口中,這就導(dǎo)致頁面發(fā)起請(qǐng)求后,要白屏好幾秒后,才能慢慢加載。
用戶的等待時(shí)間很長(zhǎng),經(jīng)過排查后發(fā)現(xiàn),其實(shí)可以將一些配置參數(shù)提取到多帶帶的一個(gè)接口中,核心的數(shù)據(jù)再抽取到另一個(gè)接口中。
這樣就是將一個(gè)串行的接口分離成兩個(gè)并行的接口,先快速的讓用戶看到整個(gè)頁面的大結(jié)構(gòu),例如頭圖、規(guī)則等信息。
然后在將數(shù)據(jù)渲染到合適的位置,形成了一個(gè)時(shí)間差,對(duì)用戶更加友好。
后端主要涉及是Node.js和數(shù)據(jù)庫的優(yōu)化,我們組涉及到的此類性能瓶頸并不多,但也會(huì)有一些。
1)內(nèi)存泄露
自研了監(jiān)控平臺(tái),在剛上線時(shí),就遇到了性能問題,首先是采集的參數(shù)在大批量的發(fā)送給存儲(chǔ)的服務(wù)器時(shí),服務(wù)器宕機(jī)了。
因?yàn)槊棵刖陀袔装偕踔翈浊У恼?qǐng)求發(fā)送過來,服務(wù)器需要整理數(shù)據(jù)后加入到數(shù)據(jù)庫中,當(dāng)數(shù)據(jù)量暴增時(shí),服務(wù)器就會(huì)來不及處理。
這個(gè)性能瓶頸發(fā)生后,馬上加入任務(wù)隊(duì)列,服務(wù)器就能平穩(wěn)的運(yùn)行了。
之后又出現(xiàn)了另一個(gè)問題,CPU會(huì)在不特定時(shí)間段(例如21~22、23~02等)飆到70%,內(nèi)存也是一路飆升不會(huì)下降,明顯是出現(xiàn)了內(nèi)存泄漏,具體的排查過程可以參考于此。
開通了阿里云的 Node.js 性能平臺(tái),在前前后后調(diào)試了三周,有點(diǎn)像探案的過程,才最終定位到一段最為可疑的代碼。
原來是為外部的一個(gè)對(duì)象反復(fù)注冊(cè)了一個(gè)事件,應(yīng)該是形成了一個(gè)閉包,讓閉包內(nèi)的變量都無法釋放。
2)數(shù)據(jù)庫
仍然是在研發(fā)監(jiān)控平時(shí)時(shí)遇到的性能瓶頸,這次主要體現(xiàn)在數(shù)據(jù)庫。
監(jiān)控的日志我都存儲(chǔ)在MySQL中,每日 70W 條記錄,數(shù)據(jù)量很快達(dá)到了千萬級(jí)別,在做查詢時(shí),變慢了很多。
那么就得讓索引上了,亞洲舞王尼庫拉斯趙四曾說過:一個(gè)索引解決不了的,那就來兩個(gè)索引。
我也是這么做的,加了好多個(gè)索引,但維度模糊查詢,這個(gè)不是加索引能解決的,嘗試了很久,最終還是決定遷移到ElasticSearch中。
效果也是立竿見影的,幾千萬條數(shù)據(jù),幾秒鐘就出了結(jié)果,令我驚嘆不已。
這里順便說下,我會(huì)在什么場(chǎng)景中選擇 MongoDB 作為數(shù)據(jù)庫的。
MySQL是一種關(guān)系型數(shù)據(jù)庫,會(huì)事先聲明表結(jié)構(gòu),那么對(duì)于數(shù)據(jù)結(jié)構(gòu)不定的記錄,存儲(chǔ)起來會(huì)比較費(fèi)勁。
例如記錄中有許多JSON格式的數(shù)據(jù),就比較適合存在 MongoDB,當(dāng)然了,這類數(shù)據(jù)也可以轉(zhuǎn)換成字符串存在 MySQL 的一個(gè)字段中。
只是在讀取和寫入時(shí),要經(jīng)過序列化和反序列化的操作,并且如果要查詢JSON數(shù)據(jù)的某一個(gè)字段時(shí),MySQL中就只能模糊查詢了。
但是平時(shí)的話,我還是會(huì)盡量將數(shù)據(jù)存在 MySQL 中,有個(gè)很直接的原因是因?yàn)榫€上的 MySQL 有一個(gè)功能完善的可視化界面,而 MongoDB 沒有,只有一個(gè)我自制的簡(jiǎn)陋工具。
3)管理后臺(tái)掛起
之前也會(huì)偶爾有管理后臺(tái)服務(wù)掛起的情況發(fā)生,但最近會(huì)在每天的10點(diǎn)左右發(fā)生。
在下圖中,一分鐘內(nèi)server服務(wù)瞬間飆到了 100%,不得不讓我引起注意。 ?
查找那段時(shí)間的日志,發(fā)現(xiàn)有很多送禮的記錄,反向查詢后,定位到一個(gè)導(dǎo)出鏈接。
初步以為是這個(gè)功能導(dǎo)致的服務(wù)掛起,詢問相關(guān)操作人員,得到當(dāng)時(shí)的操作過程。
在預(yù)發(fā)環(huán)境模擬,得到的結(jié)果是可以正常導(dǎo)出,所以應(yīng)該可以排除它的嫌疑。
回想到前天也發(fā)生了掛起(不過前天的CPU都比較正常),再次翻查日志,新發(fā)現(xiàn)直指審核模塊。
與審核人員溝通后,她們向我一頓吐槽,大倒苦水,說這系統(tǒng)11點(diǎn)后,經(jīng)常卡頓轉(zhuǎn)圈。
這個(gè)系統(tǒng)后續(xù)有很大的優(yōu)化空間,那么目前首要任務(wù)是解決服務(wù)掛起的問題。
可以想到的是將審核模塊多帶帶配置一臺(tái)服務(wù)器,做成獨(dú)立服務(wù),這樣也便于觀察。
服務(wù)切換其實(shí)就是將特定規(guī)則的API指向另一個(gè)服務(wù),代碼和邏輯都不需要改動(dòng),非常方面。
隔天發(fā)現(xiàn)仍然會(huì)掛起,但是掛起的服務(wù)可以定位到審核模塊,運(yùn)維也找到了一條發(fā)生504的接口。
前一天發(fā)生的掛起,也是這個(gè)接口引起的,順著這條接口查看代碼,并沒有發(fā)現(xiàn)什么異常。
打開日志,發(fā)現(xiàn)這個(gè)接口的響應(yīng)的確非常慢,要幾分鐘了,再去查其中涉及到的SQL查詢語句,發(fā)現(xiàn)也很耗時(shí)。
將語句拿到數(shù)據(jù)庫中執(zhí)行 EXPLAIN 命令,影響的行數(shù)要 311W 多條,命中的索引是 idx_create_time。
而去掉其中的一個(gè)日期限制后馬上降到 69 條,命中的是一個(gè)聯(lián)合索引,回到代碼中,查看邏輯后,發(fā)現(xiàn)這個(gè)時(shí)間限制是多余的,馬上就將其去除。
還有一條SQL語句運(yùn)行也很慢,影響的行數(shù)要 16W 多條,命中的索引是 idx_status,而這個(gè) status 其實(shí)只有幾個(gè)可選的關(guān)鍵字,會(huì)影響查詢效率。
于是再創(chuàng)建一個(gè)聯(lián)合索引,影響的行數(shù)降到 1785 條,優(yōu)化后,再反饋給審核人員。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/124132.html
摘要:而這里的單元格信息是唯一的,所以直接通過為一個(gè)空對(duì)象賦值即可。和相關(guān)的知識(shí)和技巧高亮的列單元格采用展示。在中,被選中的單元格會(huì)高亮相應(yīng)的行和列,以提醒用戶。 showImg(https://segmentfault.com/img/bVGkdk?w=900&h=500); XCEL 是一個(gè) Excel 數(shù)據(jù)清洗工具,其通過可視化的方式讓用戶輕松地對(duì) Excel 數(shù)據(jù)進(jìn)行篩選。 XCEL...
摘要:斬從第題開始,到現(xiàn)在也差不多快一年了,回顧紀(jì)念一下。當(dāng)時(shí)對(duì)回溯動(dòng)態(tài)規(guī)劃也都只是上課的時(shí)候?qū)W過,也并不熟練。最經(jīng)典的例子就是斐波那契數(shù)列了,求第項(xiàng)數(shù)列的值。 leetcode 100 斬!從第 1 題開始,到現(xiàn)在也差不多快一年了,回顧紀(jì)念一下。 showImg(https://segmentfault.com/img/bVbu461?w=661&h=191); 為什么開始刷題? 從大一就...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢娝氖褂茫陂_始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個(gè)名詞,今天我們首先來說說分布式。 探究...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)常可見它的使用,在開始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個(gè)名詞,今天我們首先來說說分布式。 探究...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢娝氖褂茫陂_始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個(gè)名詞,今天我們首先來說說分布式。 探究...
閱讀 1329·2021-11-24 09:38
閱讀 3268·2021-11-22 12:03
閱讀 4202·2021-11-11 10:59
閱讀 2333·2021-09-28 09:36
閱讀 1042·2021-09-09 09:32
閱讀 3434·2021-08-05 10:00
閱讀 2540·2021-07-23 15:30
閱讀 2984·2019-08-30 13:12