本文結合專案經驗,整理一份大綱,供參考。
常用指標
-
RT(Response Time):響應時間。可能會衍生出 TP999、TP99、TP95、TP90等指標。一般在幾毫秒到幾百毫秒之間。
-
QPS(Query Per Second):每秒查詢量。這是我們最常說的一個指標了。視業務複雜度不同而不同,輕量級的可能單機上萬,重量級的可能就幾百,這是主要依靠水平擴容來解決。
-
TPS(Transaction per second):每秒事務量。主要衡量資料庫效能,一般比 QPS 低 1~3 個數量級。
-
吞吐量(Throughput):單位時間內處理的請求數量。該指標概念比較寬泛:
-
從業務角度看,吞吐量可以用QPS、TPS等單位來衡量。
-
從網路角度看,吞吐量可以用bps來衡量。一般用於排查網路抖動等問題,尤其是弱網環境下的RPC請求會更加關注。
-
PV(Page View):頁面瀏覽量。一般用於統計頁面訪問頻次,每次重新整理頁面即被計算一次。高併發系統的單日 PV 基本上會超過千萬。
-
UV(Unique Visitor):獨立訪客量。用於統計單位時間內頁面訪問的使用者數,同一個使用者多次重新整理頁面只會被算做一次。高併發系統的單日 UV 基本上會過萬。
提升系統效能的兩個維度
-
垂直擴充套件:提升單機效能。包括硬體配置和軟體編寫方式兩種維度。
-
水平擴充套件:叢集整體效能。無狀態服務加機器可解決;有狀態服務還要額外考慮狀態儲存及遷移。實踐中儘量做成無狀態服務。
災備管理
多區域部署機房,通常存在冷備、熱備、雙活等幾種形式。主要用於流量分攤和故障轉移。
故障處理
-
Failover 失敗自動切換:當出現失敗,重試其它伺服器,通常用於讀操作。一般核心服務會使用該策略。
-
Failfast 快速失敗:只發起一次呼叫,失敗立即報錯,通常用於非冪等性的讀寫操作。多數場景均有重試機制。
-
Failsafe 失敗安全:出現異常時,直接忽略。通常用於寫入日誌等操作。
-
Failback 失敗自動恢復:後臺記錄失敗請求,定時重發。通常用於訊息通知等操作。
-
Forking 並行呼叫多個服務方:其中一個成功即可返回,通常用於實時性要求較高的讀操作。
-
Broadcast廣播呼叫:所有提供方逐個呼叫,任意一臺報錯則報錯。主要用於RPC框架註冊節點使用(更新提供方本地狀態),應用型服務基本不會使用。
負載均衡
-
監控機器效能,並配置機器的權重(靜態或動態)。
-
處理能力越強,分到的流量越多。
-
某臺機器故障時自動摘除流量。
-
服務剛啟動時的小流量預熱,防止瞬間高流量把機器打崩。主要是各類中介軟體資源初始化可能會很耗時,導致請求響應慢,此時如果大量流量湧入會導致 Cpu Load急劇升高,甚至可能打崩。
-
自動擴縮容。業務高峰時段自動擴容,低峰時段自動縮容,節約成本。
區分服務等級
-
核心服務:一般都存在Backup,出錯時自動切換,同時觸發中高階別告警。
-
非核心服務:出錯時可執行(手動或自動)降級甚至熔斷,同時觸發中低階別告警。
使用快取
主要針對不易變化的資料,可能是多級快取,可能橫跨客戶端和多個服務端。
-
本地快取。如 ConcurrentMap、Guava Cache、Caffeine。
-
分散式快取。如 Redis、GemFire/Geode。
非同步操作
-
架構層面:
-
如使用MQ訊息佇列進行削峰、解耦處理,日誌處理也用得比較多。
-
若追求 Cpu 的穩定性,可使用 Spring WebFlux 等全鏈路非同步化技術,需要上下游服務都改造,才能有顯著效果。
-
程式碼層面:如 Java 中的 Future 機制(常用 CompletableFuture),同時發起多個微服務的呼叫,隔一段時間後統一 get 結果。
批量執行
-
框架層面:可參考 Hystrix 的請求合併機制 HystrixCollapser。
-
程式碼層面:服務介面批量呼叫資料,拿到批量結果後再分派結果。
池化技術
-
執行緒池:常用如 ThreadPoolExecutor。
-
連線池:常用如 HikariCP、Druid、c3p0、DBCP。
-
物件池:常用如 Apache Commons Pool2。另外,如 Integer 等包裝類針對(-127~128)的物件快取,其實也是一種物件池的體現。
限流處理
-
服務入口:監控近實時統計QPS,達到閾值時拒絕請求。
-
常見的幾種限流框架:
-
單機版(JDK自帶的鎖、訊號量、Guava Limiter)
-
分散式(基於 Redis 的 redis-cell 模組和 Redisson、重量級的 Sentinel,以及老牌框架Hystrix)
-
常見的幾種限流演算法:
-
計數器法。存在臨界流量問題,基本不會使用。
-
滑動視窗。時間片劃分精度不好控制,基本不會使用。
-
漏桶演算法。難以應對突發流量,使用較少。
-
令牌桶演算法。常用。
-
常見的執行緒池拒絕策略:
-
CallerRunsPolicy 由呼叫者執行。
-
AbortPolicy 拋棄並拋異常。這是預設策略,也是最常用的策略,可以讓應用層快速發現失敗,進而介入處理。
-
DiscardPolicy 靜靜地拋棄,應用層無法感知到。
-
DiscardOldestPolicy 拋棄最老的請求。
防刷分流
搭建兩套服務叢集,將存在爬蟲標記(依賴於專業的爬蟲識別演算法)的流量分流到另一套叢集,甚至可以返回假資料,做蜜罐處理。
靜態資源分發
主要依賴 CDN 技術進行資源的就近部署,可提前預熱。常見如html、js、css、image等資源。
資料庫併發
-
單機:MVCC、事務隔離、做好索引優化。
-
叢集:分庫分表、讀寫分離。
-
結合其他中介軟體:如簡單的查詢、統計,或者文字搜尋等場景,可使用 ElasticSearch,必要時進行二級檢索( ElasticSearch 檢索出 id,再到 SQL 中查詢)。
壓力測試 /效能測試
-
Apache JMeter。
-
搭建壓測叢集,平時抓取服務真實流量,節日或大促前進行必要的壓測,以暴露效能瓶頸。
日常巡檢/故障演練
用於提前發現問題,如介面掃描、混沌工程就是做這些事情的。
大綱就寫到這裡,你還有其他解決方案嗎?歡迎評論區討論。