這是圍繞 Sentinel 的使用場景、技術對比和實現、開發者實踐等維度推出的系列文章的第四篇。git
Dubbo 的流量防衛兵 | Sentinel如何經過限流實現服務的高可用性 - 傳送門github
RocketMQ 的保險絲| Sentinel 如何經過勻速請求和冷啓動來保障服務的穩定性 - 傳送門緩存
技術選型:Sentinel vs Hystrix - 傳送門架構
Sentinel 是阿里中間件團隊研發的面向分佈式服務架構的輕量級高可用流量控制組件,於今年7月正式開源。Sentinel 主要以流量爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度來幫助用戶提高服務的穩定性。app
Sentinel 項目地址:分佈式
Sentinel 控制檯做爲 Sentinel 的一大利器,提供了多個維度的監控和規則配置功能。Sentinel 客戶端目前已可用於生產環境,但若但願在生產環境中使用 Sentinel 控制檯還須要進行一些改造。本文將介紹如何對 Sentinel 控制檯進行改造以便在生產環境中使用。性能
在生產環境中使用 Sentinel 控制檯只須要兩步改造:測試
Sentinel 的動態規則數據源用於從中讀取及寫入規則。從 0.2.0 版本開始,Sentinel 將動態規則數據源分爲兩種類型:讀數據源(ReadableDataSource
)和寫數據源(WritableDataSource
):this
其中讀數據源常見的實現方式有:
在實際的場景中,不一樣的存儲類型對應的數據源類型也不一樣。對於 push 模式的數據源,通常不支持寫入;而 pull 模式的數據源則是可寫的。
下面咱們分別來分析一下它們結合 Sentinel 控制檯的使用場景,以及相應的須要改造的點。
若應用未註冊任何數據源,直接從 Sentinel 控制檯推送規則的過程很是簡單:
Sentinel 控制檯經過 API 將規則推送至客戶端並直接更新到內存中。這種狀況下應用重啓規則就會消失,僅用於簡單測試,不能用於生產環境。通常在生產環境中,咱們須要在應用端配置規則數據源。
pull 模式的數據源(如本地文件、RDBMS 等)通常是可寫入的。使用時須要在客戶端註冊數據源:將對應的讀數據源註冊至對應的 RuleManager,將寫數據源註冊至 transport 的 WritableDataSourceRegistry
中。以本地文件數據源爲例:
public class FileDataSourceInit implements InitFunc { @Override public void init() throws Exception { String flowRulePath = "xxx"; ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>( flowRulePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}) ); // 將可讀數據源註冊至 FlowRuleManager. FlowRuleManager.register2Property(ds.getProperty()); WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson); // 將可寫數據源註冊至 transport 模塊的 WritableDataSourceRegistry 中. // 這樣收到控制檯推送的規則時,Sentinel 會先更新到內存,而後將規則寫入到文件中. WritableDataSourceRegistry.registerFlowDataSource(wds); } private <T> String encodeJson(T t) { return JSON.toJSONString(t); } }
本地文件數據源會定時輪詢文件的變動,讀取規則。這樣咱們既能夠在應用本地直接修改文件來更新規則,也能夠經過 Sentinel 控制檯推送規則。以本地文件數據源爲例,推送過程以下圖所示:
首先 Sentinel 控制檯經過 API 將規則推送至客戶端並更新到內存中,接着註冊的寫數據源會將新的規則保存到本地的文件中。使用 pull 模式的數據源時通常不須要對 Sentinel 控制檯進行改造。
對於 push 模式的數據源(如遠程配置中心),推送的操做不該由 Sentinel 數據源進行,而應該經控制檯進行推送,數據源僅負責獲取配置中心推送的配置並更新到本地。
假設寫入的操做也由數據源進行,那麼 Sentinel 客戶端收到控制檯推送的規則後,將新的規則更新到內存中,同時將規則推送至遠程的配置中心。此時,數據源監聽到配置中心推送過來的新規則,又一次更新到內存中。也就是說應用在本地更新完規則並推送到遠程後,又要接收變動並更新一次,這樣顯然是不合理的。所以推送規則正確作法應該是 配置中心控制檯/Sentinel 控制檯 → 配置中心 → Sentinel 數據源 → Sentinel,而不是經 Sentinel 數據源推送至配置中心。這樣的流程就很是清晰了:
注意因爲不一樣的生產環境可能使用不一樣的數據源,從 Sentinel 控制檯推送至配置中心的實現須要用戶自行改造。以 ZooKeeper 爲例,咱們能夠按照以下步驟進行改造(假設推送維度爲應用維度):
/sentinel_rules/{appName}/{ruleType}
,e.g. sentinel_rules/appA/flowRule
)。InMemFlowRuleStore
),能夠對其進行改造使其支持應用維度的規則緩存(key 爲 appName),每次添加/修改/刪除規則都先更新內存中的規則緩存,而後須要推送的時候從規則緩存中獲取全量規則,而後經過上面實現的 Client 將規則推送到 ZooKeeper 便可。Sentinel 會記錄資源訪問的秒級數據(若沒有訪問則不進行記錄)並保存在本地日誌中,具體格式請見 秒級監控日誌文檔。Sentinel 控制檯經過 Sentinel 客戶端預留的 API 從秒級監控日誌中拉取監控數據,並進行聚合。目前 Sentinel 控制檯中監控數據聚合後直接存在內存中,未進行持久化,且僅保留最近 5 分鐘的監控數據。若須要監控數據持久化的功能,能夠自行擴展實現 MetricsRepository
接口(0.2.0 版本),而後註冊成 Spring Bean 並在相應位置經過 @Qualifier
註解指定對應的 bean name 便可。MetricsRepository
接口定義瞭如下功能:
save
與 saveAll
:存儲對應的監控數據queryByAppAndResourceBetween
:查詢某段時間內的某個應用的某個資源的監控數據listResourcesOfApp
:查詢某個應用下的全部資源其中默認的監控數據類型爲 MetricEntity
,包含應用名稱、時間戳、資源名稱、異常數、請求經過數、請求 block 數、平均響應時間等信息。
同時用戶能夠自行進行擴展,適配 Grafana 等可視化平臺,以便將監控數據更好地進行可視化。
在生產環境中使用 Sentinel 控制檯還須要考慮如下問題:
同時也能夠到 Awesome Sentinel 去參考社區用戶的一些擴展和解決方案,也歡迎你們將一些比較好的擴展實現添加進來。
原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。