個(gè)人專題目錄
深入了解性能優(yōu)化
1.常用的性能評價(jià)/測試指標(biāo)
-
響應(yīng)時(shí)間
- 提交請求和返回該請求的響應(yīng)之間使用的時(shí)間,一般比較關(guān)注平均響應(yīng)時(shí)間。
-
并發(fā)數(shù)
- 同一時(shí)刻菜拓,對服務(wù)器有實(shí)際交互的請求數(shù)而克。
和網(wǎng)站在線用戶數(shù)的關(guān)聯(lián):1000個(gè)同時(shí)在線用戶數(shù),可以估計(jì)并發(fā)數(shù)在5%到15%之間乌庶,也就是同時(shí)并發(fā)數(shù)在50~150之間。
- 同一時(shí)刻菜拓,對服務(wù)器有實(shí)際交互的請求數(shù)而克。
-
吞吐量
- 對單位時(shí)間內(nèi)完成的工作量(請求)的量度
-
相互之間的關(guān)系
- 系統(tǒng)吞吐量和系統(tǒng)并發(fā)數(shù)以及響應(yīng)時(shí)間的關(guān)系:
理解為高速公路的通行狀況:
吞吐量是每天通過收費(fèi)站的車輛數(shù)目(可以換算成收費(fèi)站收取的高速費(fèi))契耿,
并發(fā)數(shù)是高速公路上的正在行駛的車輛數(shù)目瞒大,
響應(yīng)時(shí)間是車速。
車輛很少時(shí)搪桂,車速很快透敌。但是收到的高速費(fèi)也相應(yīng)較少;隨著高速公路上車輛數(shù)目的增多踢械,車速略受影響酗电,但是收到的高速費(fèi)增加很快;
隨著車輛的繼續(xù)增加内列,車速變得越來越慢撵术,高速公路越來越堵,收費(fèi)不增反降话瞧;
如果車流量繼續(xù)增加嫩与,超過某個(gè)極限后,任務(wù)偶然因素都會導(dǎo)致高速全部癱瘓移稳,車走不動蕴纳,當(dāng)然后也收不著,而高速公路成了停車場(資源耗盡)个粱。
2.常用的性能優(yōu)化手段
-
總原則
-
避免過早優(yōu)化
不應(yīng)該把大量的時(shí)間耗費(fèi)在小的性能改進(jìn)上古毛,過早考慮優(yōu)化是所有噩夢的根源。
所以都许,我們應(yīng)該編寫清晰稻薇,直接,易讀和易理解的代碼胶征,真正的優(yōu)化應(yīng)該留到以后塞椎,等到性能分析表明優(yōu)化措施有巨大的收益時(shí)再進(jìn)行。
但是過早優(yōu)化睛低,不表示我們應(yīng)該編寫已經(jīng)知道的對性能不好的的代碼結(jié)構(gòu)案狠。 -
進(jìn)行系統(tǒng)性能測試
所有的性能調(diào)優(yōu),都有應(yīng)該建立在性能測試的基礎(chǔ)上钱雷,直覺很重要骂铁,但是要用數(shù)據(jù)說話,可以推測罩抗,但是要通過測試求證拉庵。
-
尋找系統(tǒng)瓶頸,分而治之套蒂,逐步優(yōu)化
性能測試后钞支,對整個(gè)請求經(jīng)歷的各個(gè)環(huán)節(jié)進(jìn)行分析茫蛹,排查出現(xiàn)性能瓶頸的地方,定位問題烁挟,分析影響性能的的主要因素是什么婴洼?內(nèi)存、磁盤IO信夫、網(wǎng)絡(luò)窃蹋、CPU,還是代碼問題静稻?架構(gòu)設(shè)計(jì)不足警没?或者確實(shí)是系統(tǒng)資源不足?
-
-
前端優(yōu)化手段
-
瀏覽器/App
- 減少請求數(shù)振湾;
合并CSS杀迹,Js,圖片
- 使用客戶端緩沖押搪;
靜態(tài)資源文件緩存在瀏覽器中树酪,有關(guān)的屬性Cache-Control和Expires
如果文件發(fā)生了變化,需要更新大州,則通過改變文件名來解決续语。- 啟用壓縮
減少網(wǎng)絡(luò)傳輸量,但會給瀏覽器和服務(wù)器帶來性能的壓力厦画,需要權(quán)衡使用疮茄。
- 資源文件加載順序
css放在頁面最上面,js放在最下面
- 減少Cookie傳輸
cookie包含在每次的請求和響應(yīng)中根暑,因此哪些數(shù)據(jù)寫入cookie需要慎重考慮
- 給用戶一個(gè)提示
有時(shí)候在前端給用戶一個(gè)提示力试,就能收到良好的效果。畢竟用戶需要的是不要不理他排嫌。
- CDN加速
CDN畸裳,又稱內(nèi)容分發(fā)網(wǎng)絡(luò),本質(zhì)仍然是一個(gè)緩存淳地,而且是將數(shù)據(jù)緩存在用戶最近的地方怖糊。無法自行實(shí)現(xiàn)CDN的時(shí)候,可以考慮商用CDN服務(wù)颇象。
- 反向代理緩存
將靜態(tài)資源文件緩存在反向代理服務(wù)器上蓬抄,一般是Nginx。
- WEB組件分離
將js夯到,css和圖片文件放在不同的域名下∫鳎可以提高瀏覽器在下載web組件的并發(fā)數(shù)耍贾。因?yàn)闉g覽器在下載同一個(gè)域名的的數(shù)據(jù)存在并發(fā)數(shù)限制阅爽。
-
應(yīng)用服務(wù)性能優(yōu)化
-
存儲性能優(yōu)化
- 選擇合適的數(shù)據(jù)結(jié)構(gòu)
選擇ArrayList和LinkedList對我們的程序性能影響很大,為什么荐开?因?yàn)锳rrayList內(nèi)部是數(shù)組實(shí)現(xiàn)付翁,存在著不停的擴(kuò)容和數(shù)據(jù)復(fù)制。
- 選擇更優(yōu)的算法
舉個(gè)例子晃听,最大子列和問題:
給定一個(gè)整數(shù)序列百侧,a0, a1, a2, …… , an(項(xiàng)可以為負(fù)數(shù)),求其中最大的子序列和能扒。
如果所有整數(shù)都是負(fù)數(shù)佣渴,那么最大子序列和為0;
例如(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)時(shí)初斑,
最大子段和為20辛润,子段為a[2],a[3],a[4]。
最壞的算法:窮舉法见秤,所需要的的計(jì)算時(shí)間是O(n^3).
一般的算法:分治法的計(jì)算時(shí)間復(fù)雜度為O(nlogn).
最好的算法:最大子段和的動態(tài)規(guī)劃算法砂竖,計(jì)算時(shí)間復(fù)雜度為O(n)
n越大,時(shí)間就相差越大鹃答,比如10000個(gè)元素乎澄,最壞的算法和最好的算法之間的差距絕非多線程或者集群化能輕松解決的。- 編寫更少的代碼
同樣正確的程序测摔,小程序比大程序要快置济,這點(diǎn)無關(guān)乎編程語言。
3.應(yīng)用服務(wù)性能優(yōu)化
-
緩存
- 緩存的基本原理和本質(zhì)
- 緩存是將數(shù)據(jù)存在訪問速度較高的介質(zhì)中避咆≈廴猓可以減少數(shù)據(jù)訪問的時(shí)間,同時(shí)避免重復(fù)計(jì)算查库。
- 合理使用緩沖的準(zhǔn)則
- 頻繁修改的數(shù)據(jù)路媚,盡量不要緩存,讀寫比2:1以上才有緩存的價(jià)值樊销。
- 緩存一定是熱點(diǎn)數(shù)據(jù)整慎。
應(yīng)用需要容忍一定時(shí)間的數(shù)據(jù)不一致。 - 緩存可用性問題围苫,一般通過熱備或者集群來解決裤园。
- 緩存預(yù)熱,新啟動的緩存系統(tǒng)沒有任何數(shù)據(jù)剂府,可以考慮將一些熱點(diǎn)數(shù)據(jù)提前加載到緩存系統(tǒng)拧揽。
- 解決緩存擊穿:
1、布隆過濾器,或者2淤袜、把不存在的數(shù)據(jù)也緩存起來 痒谴,比如有請求總是訪問key = 23的數(shù)據(jù),但是這個(gè)key = 23的數(shù)據(jù)在系統(tǒng)中不存在铡羡,可以考慮在緩存中構(gòu)建一個(gè)( key=23 value = null)的數(shù)據(jù)积蔚。
- 分布式緩存與一致性哈希
- 以集群的方式提供緩存服務(wù),有兩種實(shí)現(xiàn)烦周;
- 需要更新同步的分布式緩存尽爆,所有的服務(wù)器保存相同的緩存數(shù)據(jù),帶來的問題就是读慎,緩存的數(shù)據(jù)量受限制漱贱,其次,數(shù)據(jù)要在所有的機(jī)器上同步贪壳,代價(jià)很大饱亿。
- 每臺機(jī)器只緩存一部分?jǐn)?shù)據(jù),然后通過一定的算法選擇緩存服務(wù)器闰靴。常見的余數(shù)hash算法存在當(dāng)有服務(wù)器上下線的時(shí)候彪笼,大量緩存數(shù)據(jù)重建的問題。所以提出了一致性哈希算法蚂且。
- 一致性哈希
- 首先求出服務(wù)器(節(jié)點(diǎn))的哈希值配猫,并將其配置到0~232的圓(continuum)上
- 然后采用同樣的方法求出存儲數(shù)據(jù)的鍵的哈希值,并映射到相同的圓上杏死。
- 然后從數(shù)據(jù)映射到的位置開始順時(shí)針查找泵肄,將數(shù)據(jù)保存到找到的第一個(gè)服務(wù)器上。如果超過232仍然找不到服務(wù)器淑翼,就會保存到第一臺服務(wù)器上腐巢。
- 一致性哈希算法對于節(jié)點(diǎn)的增減都只需重定位環(huán)空間中的一小部分?jǐn)?shù)據(jù),具有較好的容錯(cuò)性和可擴(kuò)展性玄括。
- 一致性哈希算法在服務(wù)節(jié)點(diǎn)太少時(shí)冯丙,容易因?yàn)楣?jié)點(diǎn)分部不均勻而造成數(shù)據(jù)傾斜問題,此時(shí)必然造成大量數(shù)據(jù)集中到Node A上遭京,而只有極少量會定位到Node B上胃惜。為了解決這種數(shù)據(jù)傾斜問題,一致性哈希算法引入了虛擬節(jié)點(diǎn)機(jī)制哪雕,即對每一個(gè)服務(wù)節(jié)點(diǎn)計(jì)算多個(gè)哈希船殉,每個(gè)計(jì)算結(jié)果位置都放置一個(gè)此服務(wù)節(jié)點(diǎn),稱為虛擬節(jié)點(diǎn)斯嚎。具體做法可以在服務(wù)器ip或主機(jī)名的后面增加編號來實(shí)現(xiàn)利虫。例如挨厚,可以為每臺服務(wù)器計(jì)算三個(gè)虛擬節(jié)點(diǎn),于是可以分別計(jì)算 “Node A#1”列吼、“Node A#2”幽崩、“Node A#3”、“Node B#1”寞钥、“Node B#2”、“Node B#3”的哈希值陌选,于是形成六個(gè)虛擬節(jié)點(diǎn):同時(shí)數(shù)據(jù)定位算法不變理郑,只是多了一步虛擬節(jié)點(diǎn)到實(shí)際節(jié)點(diǎn)的映射,例如定位到“Node A#1”咨油、“Node A#2”您炉、“Node A#3”三個(gè)虛擬節(jié)點(diǎn)的數(shù)據(jù)均定位到Node A上。這樣就解決了服務(wù)節(jié)點(diǎn)少時(shí)數(shù)據(jù)傾斜的問題役电。在實(shí)際應(yīng)用中赚爵,通常將虛擬節(jié)點(diǎn)數(shù)設(shè)置為32甚至更大,因此即使很少的服務(wù)節(jié)點(diǎn)也能做到相對均勻的數(shù)據(jù)分布法瑟。
- 以集群的方式提供緩存服務(wù),有兩種實(shí)現(xiàn)烦周;
- 緩存的基本原理和本質(zhì)
集群
-
異步
- 同步和異步冀膝,阻塞和非阻塞
- 常見異步的手段
- Servlet異步
- servlet3中才有,支持的web容器在tomcat7和jetty8以后霎挟。
- 多線程
- 消息隊(duì)列
- 集群
- 可以很好的將用戶的請求分配到多個(gè)機(jī)器處理窝剖,對總體性能有很大的提升
- 程序代碼級別
- Servlet異步
-
應(yīng)用相關(guān)
- 代碼級別
- 選擇合適的數(shù)據(jù)結(jié)構(gòu)
- 選擇更優(yōu)的算法
- 編寫更少的代碼
- 并發(fā)編程
- 充分利用CPU多核
- 實(shí)現(xiàn)線程安全的類,避免線程安全問題
- 同步下減少鎖的競爭
- 資源的復(fù)用
- 目的是減少開銷很大的系統(tǒng)資源的創(chuàng)建和銷毀酥夭,比如數(shù)據(jù)庫連接赐纱,網(wǎng)絡(luò)通信連接,線程資源等等熬北。
- JVM
- 對于程序來說疙描,通常只有一部分代碼被經(jīng)常執(zhí)行,這些關(guān)鍵代碼被稱為應(yīng)用的熱點(diǎn)讶隐,執(zhí)行的越多就認(rèn)為是越熱起胰。將這些代碼編譯為本地機(jī)器特定的二進(jìn)制碼,可以有效提高應(yīng)用性能整份。
- 存儲性能優(yōu)化
- 盡量使用SSD
- 定時(shí)清理數(shù)據(jù)或者按數(shù)據(jù)的性質(zhì)分開存放
- 代碼級別