一、交易型系統設計的一些原則
1.在設計系統時,應該多思考墨菲定律:
* 任何事情都沒有表面看起來那么簡單
* 所有的事都會比你預計的時間長
* 可能出錯的事總會出錯
* 如果你擔心某種情況發生,那么它就更有可能發生
2.系統劃分時,要思考康威定律:
* 系統架構是公司組織架構的反映
* 應該按照業務閉環進行系統拆分/組織架構劃分,實現閉環/高內聚/低耦合,減少溝通成本
* 如果溝通出現問題,那么就應該考慮進行系統和組織架構的調整
* 在合適時機進行系統拆分,不要一開始就把系統/服務拆得非常細,雖然閉環,但是每個人維護的系統多,維護成本高
3.在有限資源的情況下,一定是先解決當下最核心的問題,預測并發現未來可能出現的問題,一步步解決最痛點的問題,即滿足需求的系統是不斷迭代優化出來的
A.高并發原則
1.無狀態:比較容易進行水平擴展,應用無狀態,配置文件有狀態
2.拆分:在系統設計初期,是做一個大而全的系統還是按功能模塊拆分系統,這個需要根據環境進行權衡
* 系統維度:按照系統功能/業務拆分
* 功能維度:對一個系統進行功能再拆分
* 讀寫維度:根據讀寫比例特征進行拆分
* AOP維度:根據訪問特征,按照AOP進行拆分
* 模塊維度:按照基礎或者代碼維護特征進行拆分
3.服務化
* 判斷是不是只需要簡單的單點遠程服務調用,單機不行集群是不是就可以解決?在客戶端注冊多臺機器并使用Nginx進行負載均衡是不是就可以解決?隨著調用方越來越多,應該考慮使用服務自動注冊和發現(Dubbo使用ZooKeeper)
* 考慮服務的分組/隔離
* 后期隨著調用量的增加還要考慮服務的限流、黑白名單等
* 進程內服務->單機遠程服務->集群手動注冊服務->自動注冊和發現服務->服務的分組/隔離/路由->服務治理如限流/黑白名單
4.消息隊列
* 用來解耦一些不需要同步調用的服務或者訂閱一些自己系統關心的變化
* 可以實現服務解耦(一對多消費)、異步處理、流量削峰/緩沖等
* 要注意處理生產消息失敗,以及消息重復接收時的場景
* 大流量緩沖(電商大促等),犧牲強一致性,而保證最終一致性,需要考慮并發處理和重復處理的問題
* 在使用了消息異步機制的場景下,可能存在消息的丟失,需要考慮進行數據校對和修正來保證數據的一致性和完整性
5.數據異構
* 對訂單表進行異構,異構一套用戶訂單表,按照用戶ID進行分庫分表,還需要考慮對歷史訂單數據進行歸檔處理
* 數據閉環如商品詳情頁,通過如MQ機制接收數據變更,然后原子化存儲到合適的存儲引擎,如Redis或持久化KV存儲;使用數據聚合,前端就可以一個調用拿到所有數據,一般存儲在KV存儲中;前端通過一次或少量幾次調用拿到所需要的數據;
* 如果一次需要多個數據,可以考慮使用Hash Tag機制將相關的數據聚合到一個實例
6.緩存銀彈
* 瀏覽器緩存:設置請求過期時間,如對響應頭Expires、Cache-control進行控制,適用于對實時性不太敏感的數據
* APP客戶端緩存:一般會在大促之前把APP需要訪問的一些素材提前下發到客戶端進行緩存
* CDN緩存:將頁面、活動頁、圖片推送到離用戶最近的CDN節點,要考慮URL的設計
* 接入層緩存:考慮使用如Nginx搭建一層接入層,URL重寫、一致性哈希、proxy_cache、proxy_cache_lock、shared_dict
* 應用層緩存:Redis等
* 分布式緩存:Redis集群
7.并發化
B.高可用原則
1.降級
* 開關集中化管理:通過推送機制把開關推送到各個應用
* 可降級的多級讀服務:比如服務調用降級為只讀本地緩存、只讀分布式緩存、只讀默認降級數據
* 開關前置化:如架構是Nginx->Tomcat,可以將開關前置到Nginx接入層
* 業務降級:把一些同步調用改成異步調用,優先處理高優先級數據或特殊特征的數據
2.限流
* 惡意請求流量只訪問到cache
* 對于穿透到后端應用的流量可以考慮使用Nginx的limit模塊處理
* 對于惡意IP可以使用nginx deny進行屏蔽
3.切流量
* DNS:切換機房入口
* HttpDNS:主要APP場景下,在客戶端分配好流量入口,繞過運營商LocalDNS并實現更精準流量調度
* LVS/HaProxy:切換故障的Nginx接入層
4.可回滾:版本化
C.業務設計原則
1.防重設計:考慮防重key、防重表
2.冪等設計:在重復消息消費時進行冪等處理
3.流程可定義
4.狀態與狀態機:正向狀態(付款、發貨)和逆向狀態(取消、退款)應該根據系統和特征來決定要不要分離存儲,狀態設計時應有狀態軌跡,方便跟蹤當前訂單的軌跡并記錄相關日志,還有訂單狀態的變遷以及并發狀態修改問題
5.后臺系統操作可反饋:需要考慮效果的可預覽,可反饋
6.后臺系統審批化:對于有些重要的后臺功能需要設計審批流,并記錄日志,從而保證操作可追溯、可審計
7.文檔和注釋:在一個系統發展的一開始就應該有文檔庫(設計架構、設計思想、數據字典/業務流程、現有問題),業務代碼和特殊需求都要有注釋
8.備份:代碼備份和人員備份
二、負載均衡與反向代理
1.外網DNS應該用來實現用GSLB(全局負載均衡)進行流量調度,如將用戶分配到離他最近的服務器上以提升體驗
2.對于內網DNS,可以實現簡單的輪詢負載均衡,但會有一定的緩存時間并且沒有失敗重試機制,我們可以考慮選擇如HaProxy和Nginx
3.Nginx一用于七層負載,其吞吐量是有一定限制的,為了提升整體吞吐,會在DNS和Nginx之間引入接入層,如使用LVS、F5可以做四層負載均衡,即首先DNS解析到LVS/F5、然后LVS/F5轉發給Nginx,再由Nginx轉發給后端RealServer
4.Nginx目前提供了HTTP(ngx_http_upstreamm_module)七層負載均衡,1.9.0版本支持TCP(ngx_stream_upstream_module)四層負載均衡
5.二層負載均衡是通過改寫報文的目標MAC地址為上游服務器MAC地址,源IP地址和目標IP地址是沒有變的,負載均衡服務器和真實服務器共享同一個VIP,如LVS DR工作模式
6.四層負載均衡是根據端口將報文轉發到上游服務器(不同的IP地址+端口),如LVS NAT模式、HaProxy
7.七層負載均衡是根據端口號和應用層協議如HTTP協議的主機名、URL,轉發報文到上游服務器(不同的IP地址+端口),如HaProxy、Nginx
A.upstream配置
1.在http指令下配置upstream即可
2.主要配置:
* IP地址和端口
* 權重:默認是1,越高分配給這臺服務器的請求就越多
B.負載均衡算法
1.用來解決用戶請求到來時如何選擇upstream server進行處理,默認采用的是round-robin(輪詢),同時支持ip_hash
2.hash key [consistent],對某個key進行哈希或者使用一致性哈希算法進行負載均衡,建議考慮使用一致性哈希算法
3.least_conn,將請求均衡到最少活躍連接的上游服務器
C.失敗重試
1.主要兩部分配置:
* upstream server:server xxxx:80 max_fails=2 ?fail_timeout=10s weight=1;...
* proxy_pass:配置proxy_next_upstream相關配置,proxy_next_upstream、proxy_next_upstream_timeout、proxy_next_upstream_tries
D.健康檢查
1.nginx對上游服務器的健康檢查默認采用的是惰性策略
2.TCP心跳檢查:check interval=3000 rise=1 fall=3 timeout=2000 type=tcp;
3.HTTP心跳檢查:
* check_http_send "HEAD /status HTTP/1.0\r\n\r\n";
* check_http_expect_alive http_2xx http_3xx;
3.使用的是opensresty模塊,安裝nginx之前需要先打nginx_upstream_check_module補丁
E.其他配置
1.備份上游服務器,backup
2.不可用上游服務器,down
F.長連接
1.可以通過keepalive指令配置長連接數量
G.HTTP反向代理
1.反向代理除了實現負載均衡之外,還提供如緩存來減少上游服務器的壓力
2.還可以開啟gzip壓縮,減少網絡傳輸的數據包大小
H.HTTP動態負載均衡
1.Consul是一款開源的分布式服務注冊與發瑞系統,通過HTTP API可以使得服務注冊、發現實現起來非常簡單
2.Consul+Consul-template
2.Consul+OpenResty
I.Nginx四層負載均衡
1.靜態負載均衡
* 啟用ngx_stream_core_module,安裝Nginx時,添加--with-stream
* 配置在stream指令下
* 可配置數據庫連接
2.動態負載均衡
* nginx-upsync-module,提升了HTTP七層動態負載均衡,動態更新上游服務器不需要reload nginx
三、隔離術
1.隔離是指將系統或資源分割開,系統隔離是為了在系統發生故障時,能限定傳播范圍和影響范圍,即發生故障后不會出現滾雪球效應,從而保證只有出問題的服務不可用,其他服務還是可用的
2.資源隔離通過隔離來減少資源競爭,保障服務間的相互不影響和可用性
A.線程隔離
1.主要是指線程池隔離,在實際使用時,我們會把請求分類,然后交給不同的線程池處理
B.進程隔離
1.在公司發展初期,一般是先從零到一,不會一上來就進行系統拆分,這樣就會開發出一些大而全的系統,系統中的一個模塊/功能出現問題,整個系統就不可用了
2.通過將系統拆分為多個子系統來實現物理隔離,通過進程隔離使得某一個子系統出現問題時不會影響到其他子系統
C.集群隔離
1.隨著系統的發展,單實例服務無法滿足需求,此時需要服務化技術,通過部署多個服務形成服務集群,來提升系統容量
D.機房隔離
1.隨著對系統可用性的要求,會進行多機房部署,每個機房的服務都有自己的服務分組,本機房的服務應該只調用本機房服務,不進行跨機房調用
2.當一個機房服務發生問題時,可以通過DNS/負載均衡將請求全部切到另一個機房,或者考慮服務能自動重試其他機房的服務
3.一種辦法是根據IP(不同機房IP段不一樣)自動分組,還有一種較靈活的辦是通過在分組名中加上機房名
E.讀寫隔離
1.通過主從模式將讀和寫集群分離
F.動靜隔離
1.將動態內容和靜態資源分離,將靜態資源放在CDN上
G.爬蟲隔離
1.爬蟲和正常流量的比例能達到5:1,甚至更高,一種解決辦法是通過限流解決,另一種解決辦法是在負載均衡層面將爬蟲路由到單獨集群,Nginx即可配置
2.使用OpenResty,不僅對爬蟲user-agent過濾,還會過濾一些惡意IP ,可以考慮IP+Cookie的方式
H.資源隔離
1.最常見的資源,如磁盤、CPU、網絡,這些寶貴的資源,都會存在競爭問題
I.使用Hystrix實現隔離
1.Hystrix是Netflix開源的一款針對分布式系統的延遲和容錯庫,目的是用來隔離分布式服務故障
2.提供線程和信號量隔離,以減少不同服務之間資源競爭帶來的相互影響:提供優雅降級機制;提供熔斷機制使得服務可以快速失敗,而不是一直阻塞等待服務響應,并能從中快速恢復
3.解決的問題:
* 限制調用分布式服務的資源使用,某一個調用的服務出現問題不會影響其他服務調用,通過線程池隔離和信號量隔離實現
* 提供了優雅降級機制:超時降級、資源不足時(線程或信號量)降級,降級后可以配合降級接口返回拖底數據
* 提供了熔斷器實現,當失敗率達到閾值自動觸發降級(如因網絡故障/超時造成的失敗率高),熔斷器觸發的快速失敗會進行快速恢復
* 提供了請求緩存、請求合并實現
J.基于Servlet3實現請求隔離
四、限流詳解
1.限流的目的是通過對并發訪問/請求進行限速或者一個時間窗口內的請求進行限速來保護系統,一旦達到限制速率則可以拒絕服務(定向到錯誤頁或告知資源沒有了)、排隊或等待(比如秒殺、評論、下單)、降級(返回兜底數據或默認數據)
2.在壓測時我們能找出每個系統的處理峰值,然后通過設定峰值閾值,來防止系統過載時,通過拒絕處理過載的請求來保障系統可用,另外,也應根據系統的吞吐量、響應時間、可用率來動態調整限流閾值
3.常見的限流有
限制總并發數(比如數據庫連接池、線程池)
限制瞬時并發數(如Nginx的limit_conn模塊)
限制時間窗口內的平均速率(如Guava的RateLimiter、Nginx的limit_req模塊,用來限制每秒的平均速率)
限制遠程接口調用速率
限制MQ的消費速率
還可以根據網絡連接數、網絡流量、CPU或內存負載來限流
4.緩存目的是提升系統訪問速度和增大系統處理能力,可謂是抗高并發的銀彈。降級是當服務出問題或者影響到核心流程的性能,需要暫時屏蔽掉,待高峰過去或者問題解決后再打開的場景
A.限流算法
1.令牌桶算法:是一個存放固定容量令牌的桶,按照固定速率往桶里添加令牌
2.漏桶算法:漏桶作為計量工具(The Leaky Bucket Algorithm as a Meter)時,可以用于流量整形(Traffic Shaping)和流量控制(Traffic Policing)
B.應用級限流
1.限流總資源數:可以使用池化技術,如連接池、線程池
2.限流總并發/連接/請求數:Tomcat配置、MySQL(max_connections)、Redis(tcp-backlog)
3.限流某個接口的總并發/請求數:Java的AtomicLong或Semaphore
C.分布式限流
1.Redis+Lua
2.Nginx+Lua
D.接入層限流
1.接入層通常指請求流量的入口,該層的主要目的有:負載均衡、非法請求過濾、請求聚合、緩存、降級、限流、A/B測試、服務質量監控等
2.ngx_http_limit_conn_module,limit_conn是對某個key對應的總的網絡連接數進行限流,可以按照IP來限制IP維度的總連接數,或者按照服務域名來限制某個域名的總連接數,只有被Nginx處理的且已經讀取了整個請求頭的請求連接才會被計數器統計
3.ngx_http_limit_req_module,limit_req是漏桶算法實現,用于對指定key對應的請求進行限流,比如按照IP維度限制請求速率
4.lua-resty-limit-traffic,OpenResty了Lua限流模塊,可以按照更復雜的業務邏輯進行動態限流處理,提供了limit.conn和limit.req實現
E.節流
1.我們想在特定埋單窗口內對重復的相同事件最多只處理一次,或者想限制多個連續相同事件最小執行時間間隔,可使用節流(Throttle)實現,其防止多個相同事件連續重復執行,主要有:throttleFirst、throttleLast、throttleWithTimeout
2.throttleFirst/throttleLast
* 是指在一個時間窗口內,如果有重復的多個相同事件要處理,則只處理第一個或最后一個,其相當于一個事件頻率控制器,把一段時間內重復的多個相同事件變為一個,減少事件處理頻頻率,從而減少無用處理
* 前端開發可以使用jquery-throttle-debounce-plugin實現
* Android開發可以使用RxAndroid實現
3.throttleWithTimeout
* 也叫作debounce(去抖),限制兩個連續事件的先后執行時間不得小于某個時間窗口
* 當兩個連續事件的時間間隔小于最小間隔時間窗口,就會丟棄上一個事件,而如果最后一個事件等待了最小間隔時間窗口后還沒有新的事件到來,那么會處理最后一個事件
* 可用于搜索關鍵詞自動補全等功能
五、降級特技
1.當訪問量劇增、服務出現問題(如響應時間長或不響應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的,即使是有損服務。系統可以根據一些關鍵數據進行自動降級,也可以配置開關實現人工降級
2.降級的最終目的是保證核心服務可用,即使是有損的。而且有些服務是無法降級的(如購物車、結算)。降級也需要根據系統的吞吐量、響應時間、可用率等條件進行手工降級或自動降級
A.降級預案
1.參考日志級別設置預案
* 一般:有些服務偶爾因為網絡抖動或者服務正在上線而超時,可以自動降級
* 警告:有些服務在一段時間內成功率有波動,可以自動降級或人工降級并發送警告
* 錯誤:可用率低于90%,或數據庫連接池用完了,或訪問量突然猛增到系統能承受的最大閾值
* 嚴重錯誤:因為特殊原因數據出現錯誤,需要緊急人工降級
2.降級按照是否自動化可分為:自動開關降級和人工開關降級
3.降級按照功能可分為:讀服務降級和寫服務降級
4.降級按照處于系統層次可分為:多級降級
5.降級的功能點主要從服務器端鏈路考慮,即根據用戶訪問的服務調用鏈路來梳理哪里需要降級
* 頁面降級
* 頁面片段降級
* 頁面異步請求降級
* 服務功能降級
* 讀降級:如多級緩存模式,如果后端服務有問題,則可以降級為只讀緩存,適用于對讀一致性要求不高的場景
* 寫降級:秒殺搶購,可以只進行Cache的更新,然后異步扣減庫存到DB,保證最終一致性即可,此時可以將DB降級為Cache
* 爬蟲降級:大促活動時,可以將爬蟲流量導向靜態頁或者返回空數據,從而保護后端稀缺資源
* 風控降級:搶購/秒殺等業務,完全可以識別機器人、用戶畫像或者根據用戶風控級別進行降級處理,直接拒絕高風險用戶
B.自動開關降級
1.超時降級
* 當訪問的數據庫/HTTP服務/遠程調用響應慢或者長時間響應慢,且該服務不是核心服務的話,可以在超時后自動降級
* 如果是調用別人的遠程服務,則可以和對方定義一個服務響應最大時間,如果超時了,則自動降級
* 在實際場景中一定要配置好超時時間和超時重試次數及機制
2.統計失敗次數降級:當失敗調用次數達到一定閾值自動降級(熔斷器),然后通過異步線程去探測服務是否恢復了
3.故障降級:要調用的遠程服務掛掉了,則可以直接降級,降級后的處理方案:默認值(比如庫存掛了返回默認) 、兜底數據(比如廣告掛了返回提前準備好的靜態頁面)、緩存
4.限流降級:當達到限流閾值時,后續請求會被降級,降級后的處理方案:排隊頁面、無貨、錯誤頁
C.人工開關降級
1.開關可以存放到配置文件、數據庫、Redis/ZooKeeper,可以定期同步開關數據,然后通過判斷某個KEY的值來決定是否降級
2.對于新開發的服務進行灰度測試,就需要設置開關,還有多機房服務,也可以通過開關完成
3.還有一引起是因為功能問題需要暫時屏蔽掉某些功能
D.讀服務降級
1.一般采取的策略有:暫時切換讀(降級到讀緩存、降級走靜態化)、暫時屏蔽讀(屏蔽讀入口、屏蔽某個讀服務)
2.我們會在接入層、應用層設置開關,當分布式緩存、RPC服務/DB有問題時自動降級為不調用,適用于讀一致性要求不高的場景
3.頁面降級、頁面片段降級、頁面異步請求降級都是讀服務降級,目的是丟卒保帥
4.動態化降級為靜態化
5.靜態化降級為動態化
E.寫服務降級
1.大多數場景下是不可降級的,不過可以:將同步操作轉換為異步操作、限制寫的量/比例(如評論開關量大時不可見)
F.多級降級
1.降級是離用戶走越近越對系統保護得好,因為業務的復雜性導致越到后端QPS/TPS越低
* 頁面JS降級開關:控制頁面功能降級
* 接入層降級開關:控制請求入口的降級
* 應用層降級開關:控制業務的降級
G.配置中心
1.應用層API封裝
2.使用配置文件實現開關配置
3.使用配置中心實現開關配置:ZooKeeper、Diamond、Disconf、Etcd 3、Consul
H.使用Hystrix實現降級
I.使用Hystrix實現熔斷
六、超時與重試機制
A.簡介
1.如果應用不設置超時,則可能會導致請求響應慢,慢請求累積導致連鎖反應,甚至造成應用雪崩
2.讀服務天然適合重試,而寫服務大多不能重試(如果寫服務是冪等的,則重試是允許的),重試次數太多會導致多倍請求流量
3.在進行代碼Review時,一定記得Review超時與重試機制
4.超時與重試機制:
* 代理層超時與重試
* Web容器超時
* 中間件客戶端超時與重試
* 數據庫客戶端超時
* NoSQL客戶端超時
* 業務超時
* 前端Ajax超時
B.代理層超時與重試
1.Nginx
* client_header_timeout time:設置讀取客戶端請求頭超時時間,默認為60s,響應408,如果在些超時時間內客戶端沒有發送完請求頭
* client_body_timeout time:設置讀取客戶端內容體超時時間,默認為60s,響應408,兩次成功讀操作間隔時間,而不是發送整個請求體超時時間
* send_timeout_time:設置發送響應到客戶端的超時時間,默認60s,兩次成功寫操作間隔時間,而不是發送整個響應的超時時間
* keepalive_timeout timeout [header_timeout]:設置HTTP長連接超時時間,要配合keepalive_disable和keepalive_requests一起使用
2.DNS解析超時設置
* resolver_timeout 30s:設置DNS解析超時時間,默認30s,配合resolver address ... [valid=time]進行DNS域名解析
3.代理超時設置
* proxy_connect_timeout time:與后端/上游服務器建立連接的超時時間
* proxy_read_timeout time:設置從后端/上游服務器讀取響應的超時時間
* proxy_send_timeout time:設置往后端/上游服務器發送請求的超時時間
* proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | non_idempotent | off ...:配置什么情況下需要請求下一臺上游服務器進行重試ZXCV
* proxy_next_upstream_tries number:設置重試次數,指所有請求次數,默認0表示不限制
* proxy_next_upstream_timeout time:設置重試最大超時時間,默認0表示不限制
* upstream存活超時,max_fails和fail_timeout:配置什么時候Nginx將上游服務器認定為不可用/不存活
4.Twemproxy:Twitter開源的Redis和Memcache代理中間件,減少與后端緩存服務器的連接數
C.Web容器超時
D.中間件客戶端超時與重試
1.JSF是京東自研的SOA框架,主要有三個組件:注冊中心、服務提供端、服務消費端
2.JMQ是京東消息中間件,主要有四個組件:注冊中心、Broker(JMQ的服務器端實例,生產和消費消息都跟它交互)、生產者、消費者
E.數據庫客戶端超時
F.NoSQL客戶端超時
G.業務超時
1.任務型:可以通過Worker定期掃描數據庫修改狀態,有時需要遠程服務超時了,可以考慮使用隊列或者暫時記錄到本地稍后重試
2.服務調用型:可以簡單地使用Futrue來解決問題(Java)
H.前端Ajax超時
1.可以在請求時帶上timeout參數
2.使用setTimeout進行超時重試
七、回滾機制
A.事務回滾
1.對于單庫事務回滾直接使用相關SQL即可
2.分布式事務常見的如兩階段提交、三階段提交協議,可以考慮事務表、消息隊列、補償機制(執行/回滾)、TCC模式(預占/確認/取消)、Sagas模式(拆分事務+補償機制)等實現最終一致性
B.代碼庫回滾
1.SVN、Git等
C.部署版本回滾
1.部署版本化:發布時采用全量發布,避免增量發布
2.小版本增量發布:先發布1臺驗證,沒問題發布10臺,最后全部發布
3.大版本灰度發布:兩個版本并行跑一段時間
4.架構升級并發發布:通過A/B方式慢慢地將流量引入到新版本集群,如果新版本出現大面積故障,降級回老版本
D.數據版本回滾
1.兩種思路:全量和增量
* 全量版本化是指即使只變更了其中一個字段也將整體記錄進行歷史版本化
* 增量版本化是只保存變化的字段
八、壓測與預案
A.系統壓測
1.壓測一般指性能壓力測試,用來評估系統的穩定性和性能,從而決定是否需要擴容或縮容
2.壓測之前要有壓測方案【如壓測接口、并發量、壓測策略(突發、逐步加壓、并發量)、壓測指標(機器)】,之后要產出壓測報告【壓測方案、機器負載、QPS/TPS、響應時間(平均、最小、最大)、成功率、相關參數(JVM參數、壓縮參數)】,最后根據壓測報告分析的結果進行系統優化和容災
3.線下壓測:通過如JMeter、Apache ab壓測系統的某個接口或者某個組件
4.線上壓測:按讀寫分為讀壓測、寫壓測和混合壓測,按數據仿真度分為仿真壓測和引流壓測,按是否給用戶提供服務分為隔離集群壓測和線上集群壓測
5.讀壓測是壓測系統的讀流量,寫壓測是辱沒系統的寫流量,讀和寫是會相互影響 的,因此,這種情況下要進行混合壓測
6.仿真壓測是通過模擬請求進行系統壓測,數據可以是使用程序構造、人工構造,或者使用Nginx訪問日志
7.隔離集群壓測是指將對外提供服務的部分服務器從線上集群摘除,然后將線上流量引流到該集群進行壓測,這種方式很安全
8.單機壓測是指對集群中的一臺機器進行壓測,從而評估出單機極限處理能力,發現單機的瓶頸點,這樣可以把單機性能優化到極致
9.離散壓測,即選擇的數據應該是分散的或者長尾的
10.全鏈路壓測
B.系統優化和容災
1.拿到壓測報告 后,接下來會分析報告,然后進行一些有針對性的優化,如硬件升級、系統擴容、參數調優、代碼優化、架構優化
2.在進行系統優化時,要進行代碼走查,發現不合理的參數配置,如超時時間、降級策略、緩存時間等,在系統壓測中進行慢查詢排查,包括Redis、MySQL等,通過優化查詢解決慢查詢問題
3.在應用系統擴容方面,可以根據去年流量、與運營業務方溝通促銷力度、最近一段時間的流量來評估出是否需要進行擴容,需要擴容多少倍
4.在擴容時要考慮系統容災,比如分組部署、跨機房部署,容災是通過部署多組(單機房/多機房)相同應用系統,當其中一組出現問題時,可以切換到另一個分組
C.應急預案
1.系統分級:可以按照交易核心系統和交易支撐系統進行劃分
2.針對核心系統進行全鏈路分析,從用戶入口到后端存儲,梳理出各個關鍵路徑,對相關路徑進行評估并制定預案
* 網絡接入層:由系統工程師負責,關注機房不可用、DNS故障、VIP故障等預案處理
* 應用接入層:由開發工程師負責,關注上游應用路由切換、限流、降級、隔離等預案處理
* Web應用層和服務層:由開發工程師負責,關注依賴服務的路由切換、連接池(數據庫、線程池等)異常、限流、超時降級、服務異常降級、應用負載異常、數據庫故障切換、緩存故障切換等
* 數據層:由開發工程師或系統工程師負責,關注數據庫/緩存負載高、數據庫/緩存故障等
3.制定好預案后,應對預案進行演習,來驗證預案的正確性,在制定預案時也要設定故障的恢復時間
4.要對關聯路徑實施監控報警,包括服務器監控(CPU使用率、磁盤使用每戶、網絡帶寬等)、系統監控(系統存活、URL狀態/內容監控、端口存活等)、JVM監控(堆內存、GC次數、線程數等)、接口監控【接口調用量(每秒/每分鐘)、接口性能(TOP50/TOP99/TOP999)、接口可用率等】,然后配置報警策略如監控時間段、報警閾值、通知方式