1. 程式人生 > >報告老闆,微服務高可用神器已祭出,您花巨資營銷的高流量來了沒?

報告老闆,微服務高可用神器已祭出,您花巨資營銷的高流量來了沒?

![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200428090217643.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0phNW9u,size_16,color_FFFFFF,t_70) > 我得意地來到老闆的辦公室:“報告老闆,高可用神器已祭出,您花巨資營銷的高流量什麼時候到?” > 老闆呵呵一聲:“高流量下週一來報道,你可以準備下和他做工作交接了” > 窗戶外一陣冷風吹過,接下來是不是會發生點什麼。 @[TOC](目錄) # 一、從阿里雙11的高併發高流量開始 正如眾所周知,每年的雙11除了是購物狂歡節,同樣也成了科技的大考和狂歡,讓我們得以看到那麼多高階的充滿想象力的黑技術。在整個雙11高併發高流量的過程中,Sentinel 承接了核心場景,完美地保障了阿里巴巴歷年雙十一的穩定性。 > 隨著微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200425173033524.png) 通過Sentinel可以應對或支撐以下場景: 1. 持續峰值:限流、慢呼叫降級 2. 秒殺(也可稱之為脈衝流量):限流、慢呼叫降級 3. 削峰填谷:消費端可能會出現大批量的訊息同時到達,若瞬時請求所有訊息會導致系統負載過高。Sentinel利用勻速器模式將訊息均攤到一段時間內,讓系統負載保持在處理能力水位的同時儘可能地處理更多訊息,從而起到“削峰填谷”的效果。 4. 冷啟動:當流量突然增大的時候,我們希望系統從空閒狀態到繁忙狀態的切換的時間長一些,即如果系統在此之前長期處於空閒的狀態,我們希望處理請求的速率緩慢增加,經過預期的時間以後,到達系統處理請求速率的設定值; 5. 熱點商品自動探測、防護:自動統計訪問頻次最高的熱點引數並進行流量控制; 6. 叢集流量不均勻:通過叢集限流來解決叢集各個機器的流量不均導致整體限流效果不精確的問題; 7. 完備的實時監控:Sentinel 同時提供實時的監控功能。可以在控制檯中看到接入應用的單臺機器秒級資料,甚至 500 臺以下規模的叢集的彙總執行情況。 作為一個功能完備的高可用流量控制框架,核心的 sentinel-core 打包後只有 286KB(最新的1.7.2版本),非常輕量級,可以放心地引入 sentinel-core 而不需擔心依賴問題(**打臉,沒有坑是不可能的**)。根據官方提供的資料,引入 Sentinel 帶來的效能損耗非常小,單機 QPS 不太大的時候損耗幾乎可以忽略不計(單機 4.3W QPS 的損耗約為 2.36%) # 二、核心功能及原理說明 ## 2.1 模組說明 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200425201552660.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0phNW9u,size_16,color_FFFFFF,t_70) - sentinel-core 核心模組,限流、降級、系統保護等都在這裡實現 - sentinel-dashboard 控制檯模組,可以對連線上的sentinel客戶端實現視覺化的管理 - sentinel-transport 傳輸模組,提供了基本的監控服務端和客戶端的API介面,以及一些基於不同庫的實現 - sentinel-extension 擴充套件模組,主要對DataSource進行了部分擴充套件實現 - sentinel-adapter 介面卡模組,主要實現了對一些常見框架的適配 - sentinel-demo 樣例模組,可參考怎麼使用sentinel進行限流、降級等 - sentinel-benchmark 基準測試模組,對核心程式碼的精確性提供基準測試 - sentinel-logging 日誌模組,可將sentinel的日誌通過slf4j整合到專案中 - sentinel-cluster 叢集,1.4版本中提供了叢集流控的功能 從使用上來看,主要分為兩大部分: **核心庫(Java 客戶端)**:不依賴任何框架/庫,能夠運行於 Java 7 及以上的版本的執行時環境,同時對 Dubbo / Spring Cloud 等框架也有較好的支援(見 主流框架適配)。 **控制檯(Dashboard)**:Dashboard 主要負責管理推送規則、監控、管理機器資訊等。 ## 2.2 總體框架 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/2020042521364880.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0phNW9u,size_16,color_FFFFFF,t_70) sentinel主要是基於7種不同的Slot形成了一個連結串列,每個Slot都各司其職,自己做完分內的事之後,會把請求傳遞給下一個Slot,直到在某一個Slot中命中規則後丟擲BlockException而終止。前三個Slot負責做統計,後面的Slot負責根據統計的結果結合配置的規則進行具體的控制,是Block該請求還是放行。 - NodeSelectorSlot 負責收集資源的路徑,並將這些資源的呼叫路徑,以樹狀結構儲存起來,用於根據呼叫路徑來限流降級; - ClusterBuilderSlot 則用於儲存資源的統計資訊以及呼叫者資訊,例如該資源的 RT, QPS, thread count 等等,這些資訊將用作為多維度限流,降級的依據; - StatisticSlot 則用於記錄、統計不同緯度的 runtime 指標監控資訊; - FlowSlot 則用於根據預設的限流規則以及前面 slot 統計的狀態,來進行流量控制; - AuthoritySlot 則根據配置的黑白名單和呼叫來源資訊,來做黑白名單控制; - DegradeSlot 則通過統計資訊以及預設的規則,來做熔斷降級; - SystemSlot 則通過系統的狀態,例如 load1 等,來控制總的入口流量; ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200425164224143.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0phNW9u,size_16,color_FFFFFF,t_70) Sentinel 還提供簡單易用、完善的 SPI 擴充套件介面。讓開發人員可以通過實現擴充套件介面來快速地定製邏輯。例如定製規則管理、適配動態資料來源等。 ## 2.3 核心概念:Resource/Entry/Context/Node ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200425212955898.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0phNW9u,size_16,color_FFFFFF,t_70) - Resource 在Sentinel中把所有要保護的東西都稱之為資源,它可以是服務,服務裡的**方法,甚至是一段程式碼**。只要通過 Sentinel API 定義的程式碼,就是資源,能夠被 Sentinel 保護起來。大部分情況下,可以使用方法簽名,URL,甚至服務名稱作為資源名來標示資源。 - Context Context是一個用來儲存呼叫鏈當前狀態的元資料的類,每次進入一個資源時,就會建立一個Context,相同的資源名可能會建立多個Context。一個Context中包含了三個核心的物件: 1)當前呼叫鏈的根節點:EntranceNode 2)當前的入口:Entry 3)當前入口所關聯的節點:Node Context中只會儲存一個當前正在處理的入口Entry,另外還會儲存呼叫鏈的根節點。需要注意的是,每次進入一個新的資源時,都會建立一個新的Context。 - Entry 每次呼叫 SphU#entry() 都會生成一個Entry入口,該入口中會儲存了以下資料:入口的建立時間,當前入口所關聯的節點,當前入口所關聯的呼叫源對應的節點。Entry是一個抽象類,他只有一個實現類,在CtSph中的一個靜態類:CtEntry - Node 節點是用來儲存某個資源的各種實時統計資訊的,他是一個介面,通過訪問節點,就可以獲取到對應資源的實時狀態,以此為依據進行限流和降級操作。 ## 2.4 簡單上手及dashboard一覽 官方有比較完善的演示程式碼: ```java /** * 配置規則 */ private static void initFlowRules(){ List