聲明
本文爲Gleasy原創文章,轉載請指明引自Gleasy團隊博客 css
問題初級定位方法: 一感三看
一感,憑我的感受,操做不流暢,有挫折感確定有問題。
三看:
一看ajax請求的執行時間,網絡條件好的狀況下,超過400MS的確定有問題;
二看靜態內容(html,圖片,js,css)等是否cache,沒有cache確定有問題;
三看同一個ajax請求的數量,若是連續有N個(N>3)以上同一個AJAX請求,確定有問題; html
問題深刻定位方法
方法一:使用stopwatch,在程序中植入log記錄執行時間,經過查看執行時間以定位出問題的代碼段;
方法二:間隔重複可疑操做,觀察記錄CPU變化狀況。用以觀察是否有死循環或者大規模遍歷。
方法三:惡意快速重複點擊同一個功能按鍵20次,觀察是否會重複發起後端請求20次,若是是,那麼,也是有問題的。
方法四:使用SQL監控(druid)來觀察每個SQL執行次數,執行時間,從而發現熱點問題 前端
應用技巧
NO1. 弱化數據庫
1.將數據庫弱化爲「存儲」,避免使用數據庫查詢能力,儘可能使用主鍵或惟一鍵進行精確讀取動做,數據量不太大的表可使用普通索引進行精確讀取,避免使用範圍查詢(> < != between in),禁止使用like,禁止使用子查詢,聯合查詢,exists查詢;
2.範圍查詢和like查詢,一概使用索引平臺CloudIndex替代;
3.子查詢,聯合查詢,exists查詢:一概在應用層進行邏輯拼裝(若是數據量太大,可使用Map-Reduce進行多線程計算,若是再大可使用cloudjob進行分佈式調度) web
NO2. 善用緩存
1.提升緩存命中率爲終極目標;
2.容易忽視的緩存問題:大量訪問己被刪除數據,因爲數據不存在,緩存確定不命中,致使頻頻訪問數據庫;解決方法是對己刪除的數據作特殊緩存標記;
3.對寫入性能要求極爲苛刻的場景可使用redis緩存-存儲切換的方式進行異步寫入:寫入redis(標記爲存儲),馬上返回,另起獨立線程將寫入數據同步至數據庫,同步成功以後,將redis中相應數據標記爲緩存。 ajax
NO3. 用好中間件
1. 對於寫入性能要求苛刻(或寫入併發量特別大的)且容許寫入延遲的狀況,使用CloudMQ中間件;好比發郵件,發微博,發留言等;
2. 定時任務(好比定時發送郵件,定時提醒),特別適合使用CloudJob中間件;
3. 對於消耗性任務(好比執行時間長且任務量大,消耗CPU資源),可使用CloudJob進行分佈式任務調度,將衆多大任務放到N臺後臺機器上執行; redis
NO4. 批量操做(從前端到後端)
1. 前端批量,針對大量重複調用某一接口的狀況,因爲AJAX的異步性,能夠將N個請求合併成一個請求,串行執行AJAX,策略以下(僞代碼): 數據庫
01 |
var getDepartmentLinkByUid = function(uid,callback){ |
02 |
if(loading){cache.push({uid:uid,callbackup:callback}); return;} |
07 |
var realGet = function(){ |
08 |
var tmp = cache.splice(0); |
12 |
for(var i=0;i<tmp.length;i++){ |
15 |
tmp[i].callback(rdata); |
17 |
if(cache.length>0) realGet(); |
2. 緩存批量(承接上面的例子) 後端
2 |
notcached = new ArrayList(); |
4 |
if(objects 不包含uid) notcached.add(uid); |
3. 數據庫批量查詢(承接上面的例子),批量更新緩存 緩存
1 |
notcachedData = select * from department where uid in (notcached列表); |
2 |
mset(notcachedData 生成的 map); |