sentinel 端口_Sentinel原理:控制臺是如何獲取到實時數據的

Sentinel 系列教程,現已上傳到 github 和 gitee 中:

  • GitHub:

    https://github.com/all4you/sentinel-tutorial

  • Gitee:

    https://gitee.com/all_4_you/sentinel-tutorial

8d3e55af82b1e222b565c2735e2a6c0d.png

Sentinel 能夠被大家所認可,除了他自身的輕量級,高性能,可擴展之外,跟控制臺的好用和易用也有著莫大的關系,因為通過控制臺極大的方便了我們日常的運維工作。

我們可以在控制臺上操作各種限流、降級、系統保護的規則,也可以查看每個資源的實時數據,還能管理集群環境下的服務端與客戶端機器。

但是控制臺只是一個獨立的 spring boot 應用,他本身是沒有任何數據的,他的數據都是從其他的 sentinel 實例中獲取的,那他是如何獲取到這些數據的呢?帶著這個疑問我們從源碼中尋找答案。

最簡單的方法莫過于啟動一個控制臺的實例,然后從頁面上查看每個接口請求的url,然后再到 dashboard 的代碼中去深挖下去。

怎么啟動控制臺,這里就不再詳細描述了,大家可以看 Sentinel實戰:使用控制臺管理規則 這篇文章去了解下,簡單的幾步就可以啟動一個控制臺了。

我們就以一個簡單的查看【流控規則】為例來描述,點擊【流控規則】進入頁面后,按F11打開network就可以看到請求的url了,如下圖所示:

76a5f763f2aa4b356ab3794f395ffafd.png

可以看到,請求的 url 是 /v1/flow/rules 我們直接在源碼中全局搜索 /rules ,為什么不搜索 /v1/flow/rules 呢,因為有可能 url 被拆分成兩部分,我們直接搜完整的 url 可能搜不到結果。如下圖所示:

11b796f43befa54682c26f9eb34c0d97.png

我們要找的應該就是 FlowControllerV1 這個類了,打開這個類看下類上修飾的值是不是 /v1/flow 如下圖所示:

7c62d36cbda2eab0051fffa8de1f780e.png

從圖中可以看出來,dashboard 是通過一個叫 SentinelApiClient 的類去指定的 ip 和 port 處獲取數據的。這個 ip 和 port 是前端頁面直接提交給后端的,而前端頁面又是通過 /app/{app}/machines.json 接口獲取機器列表的。

連接 dashboard

這里的機器列表中展示的就是所有連接到 dashboard 上的 sentinel 的實例,包括普通限流的 sentinel-core 和集群模式下的 token-server 和 token-client。我們可以回想一下,一個 sentinel-core 的實例要接入 dashboard 的幾個步驟:

  1. 引入 dashboard 的依賴

  2. 配置 dashboard 的 ip 和 port

  3. 初始化 sentinel-core,連接 dashboard

sentinel-core 在初始化的時候,通過 JVM 參數中指定的 dashboard 的 ip 和 port,會主動向 dashboard 發起連接的請求,該請求是通過 HeartbeatSender 接口以心跳的方式發送的,并將自己的 ip 和 port 告知 dashboard。這里 sentinel-core 上報給 dashboard 的端口是 sentinel 對外暴露的自己的 CommandCenter 的端口。

HeartbeatSender 有兩個實現類,一個是通過 http,另一個是通過 netty,我們看 http 的實現類:

SimpleHttpHeartbeatSender.java

private final HeartbeatMessage heartBeat = new HeartbeatMessage();

private final SimpleHttpClient httpClient = new SimpleHttpClient();

@Override

public boolean sendHeartbeat() throws Exception {

? ?if (TransportConfig.getRuntimePort() <= 0) {

? ? ? ?RecordLog.info("[SimpleHttpHeartbeatSender] Runtime port not initialized, won't send heartbeat");

? ? ? ?return false;

? ?}

? ?InetSocketAddress addr = getAvailableAddress();

? ?if (addr == null) {

? ? ? ?return false;

? ?}

? ?SimpleHttpRequest request = new SimpleHttpRequest(addr, HEARTBEAT_PATH);

? ?request.setParams(heartBeat.generateCurrentMessage());

? ?try {

? ? ? ?SimpleHttpResponse response = httpClient.post(request);

? ? ? ?if (response.getStatusCode() == OK_STATUS) {

? ? ? ? ? ?return true;

? ? ? ?}

? ?} catch (Exception e) {

? ? ? ?RecordLog.warn("[SimpleHttpHeartbeatSender] Failed to send heartbeat to " + addr + " : ", e);

? ?}

? ?return false;

}

通過一個 HttpClient 向 dashboard 發送了自己的信息,包括 ip port 和版本號等信息。

其中 consoleHost 和 consolePort 的值就是從 JVM 參數 csp.sentinel.dashboard.server 中獲取的。

dashboard 在接收到 sentinel-core 的連接之后,就會與 sentinel-core 建立連接,并將 sentinel-core 上報的 ip 和 port 的信息包裝成一個 MachineInfo 對象,然后通過 SimpleMachineDiscovery 將該對象保存在一個 map 中,如下圖所示:

705e44b9452a9b08d78abed71d74beba.png

定時發送心跳

sentinel-core 連接上 dashboard 之后,并不是就結束了,事實上 sentinel-core 是通過一個 ScheduledExecutorService 的定時任務,每隔 10 秒鐘向 dashboard 發送一次心跳信息。發送心跳的目的主要是告訴 dashboard 我這臺 sentinel 的實例還活著,你可以繼續向我請求數據。

這也就是為什么 dashboard 中每個 app 對應的機器列表要用 Set 來保存的原因,如果用 List 來保存的話就可能存在同一臺機器保存了多次的情況。

心跳可以維持雙方之間的連接是正常的,但是也有可能因為各種原因,某一方或者雙方都離線了,那他們之間的連接就丟失了。

1.sentinel-core 宕機

如果是 sentinel-core 宕機了,那么這時 dashboard 中保存在內存里面的機器列表還是存在的。目前 dashboard 只是在接收到 sentinel-core 發送過來的心跳包的時候更新一次機器列表,當 sentinel-core 宕機了,不再發送心跳數據的時候,dashboard 是沒有將 “失聯” 的 sentinel-core 實例給去除的。而是頁面上每次查詢的時候,會去用當前時間減去機器上次心跳包的時間,如果時間差大于 5 分鐘了,才會將該機器標記為 “失聯”。

所以我們在頁面上的機器列表中,需要至少等到 5 分鐘之后,才會將具體失聯的 sentinel-core 的機器標記為 “失聯”。如下圖所示:

4fdbd00063e7d10b1acd86d3fa826f5c.png

2.dashboard 宕機

如果 dashboard 宕機了,sentinel-core 的定時任務實際上是會一直請求下去的,只要 dashboard 恢復后就會自動重新連接上 dashboard,雙方之間的連接又會恢復正常了,如果 dashboard 一直不恢復,那么 sentinel-core 就會一直報錯,在 sentinel-record.log 中我們會看到如下的報錯信息:

1f237594d80aa61f0ee55a24c964db88.png

不過實際生產中,不可能出現 dashboard 宕機了一直沒人去恢復的情況的,如果真出現這種情況的話,那就要吃故障了。

請求數據

當 dashboard 有了具體的 sentinel-core 實例的 ip 和 port 之后,就可以去請求所需要的數據了。

讓我們再回到最開始的地方,我在頁面上查詢某一臺機器的限流的規則時,是將該機器的 ip 和 port 以及 appName 都傳給了服務端,服務端通過這些信息去具體的遠程實例中請求所需的數據,拿到數據后再封裝成 dashboard 所需的格式返回給前端頁面進行展示。

具體請求限流規則列表的代碼在 SentinelApiClient 中,如下所示:

SentinelApiClient.java

public List<FlowRuleEntity> fetchFlowRuleOfMachine(String app, String ip, int port) {

? ?String url = "http://" + ip + ":" + port + "/" + GET_RULES_PATH + "?type=" + FLOW_RULE_TYPE;

? ?String body = httpGetContent(url);

? ?logger.info("FlowRule Body:{}", body);

? ?List<FlowRule> rules = RuleUtils.parseFlowRule(body);

? ?if (rules != null) {

? ? ? ?return rules.stream().map(rule -> FlowRuleEntity.fromFlowRule(app, ip, port, rule))

? ? ? ? ? ?.collect(Collectors.toList());

? ?} else {

? ? ? ?return null;

? ?}

}

可以看到也是通過一個 httpClient 請求的數據,然后再對結果進行轉換,具體請求的過程是在 httpGetContent 方法中進行的,我們看下該方法,如下所示:

private String httpGetContent(String url) {

? ?final HttpGet httpGet = new HttpGet(url);

? ?final CountDownLatch latch = new CountDownLatch(1);

? ?final AtomicReference<String> reference = new AtomicReference<>();

? ?httpClient.execute(httpGet, new FutureCallback<HttpResponse>() {

? ? ? ?@Override

? ? ? ?public void completed(final HttpResponse response) {

? ? ? ? ? ?try {

? ? ? ? ? ? ? ?reference.set(getBody(response));

? ? ? ? ? ?} catch (Exception e) {

? ? ? ? ? ? ? ?logger.info("httpGetContent " + url + " error:", e);

? ? ? ? ? ?} finally {

? ? ? ? ? ? ? ?latch.countDown();

? ? ? ? ? ?}

? ? ? ?}

? ? ? ?@Override

? ? ? ?public void failed(final Exception ex) {

? ? ? ? ? ?latch.countDown();

? ? ? ? ? ?logger.info("httpGetContent " + url + " failed:", ex);

? ? ? ?}

? ? ? ?@Override

? ? ? ?public void cancelled() {

? ? ? ? ? ?latch.countDown();

? ? ? ?}

? ?});

? ?try {

? ? ? ?latch.await(5, TimeUnit.SECONDS);

? ?} catch (Exception e) {

? ? ? ?logger.info("wait http client error:", e);

? ?}

? ?return reference.get();

}

從代碼中可以看到,是通過一個異步的 httpClient 再結合 CountDownLatch 等待 5 秒的超時時間去獲取結果的。

獲取數據的請求從 dashboard 中發出去了,那 sentinel-core 中是怎么進行相應處理的呢?看過我其他文章的同學肯定還記得, sentinel-core 在啟動的時候,執行了一個 InitExecutor.init 的方法,該方法會觸發所有 InitFunc 實現類的 init 方法,其中就包括兩個最重要的實現類:

  • HeartbeatSenderInitFunc

  • CommandCenterInitFunc

HeartbeatSenderInitFunc 會啟動一個 HeartbeatSender 來定時的向 dashboard 發送自己的心跳包,而 CommandCenterInitFunc 則會啟動一個 CommandCenter 對外提供 sentinel-core 的數據服務,而這些數據服務是通過一個一個的 CommandHandler 來提供的,如下圖所示:

57f86deb5ea14f8247d736c85b13cf52.png

總結

現在我們已經知道了 dashboard 是如何獲取到實時數據的了,具體的流程如下所示:

1.首先 sentinel-core 向 dashboard 發送心跳包

2.dashboard 將 sentinel-core 的機器信息保存在內存中

3.dashboard 根據 sentinel-core 的機器信息通過 httpClient 獲取實時的數據

4.sentinel-core 接收到請求之后,會找到具體的 CommandHandler 來處理

5.sentinel-core 將處理好的結果返回給 dashboard

思考

1.數據安全性

sentinel-dashboard 和 sentinel-core 之間的通訊是基于 http 的,沒有進行加密或鑒權,可能會存在數據安全性的問題,不過這些數據并非是很機密的數據,對安全性要求并不是很高,另外增加了鑒權或加密之后,對于性能和實效性有一定的影響。

2.SentinelApiClient

目前所有的數據請求都是通過 SentinelApiClient 類去完成的,該類中充斥著大量的方法,都是發送 http 請求的。代碼的可讀性和可維護性不高,所以需要對該類進行重構,目前我能夠想到的有兩種方法:

1)通過將 sentinel-core 注冊為 rpc 服務,dashboard 就像調用本地方法一樣去調用 sentinel-core 中的方法,不過這樣的話需要引入服務注冊和發現的依賴了。

2)通過 netty 實現私有的協議,sentinel-core 通過 netty 啟動一個 CommandCenter 來對外提供服務。dashboard 通過發送 Packet 來進行數據請求,sentinel-core 來處理 Packet。不過這種方法跟目前的做法沒有太大的區別,唯一比較好的可能就是不需要為每種請求都寫一個方法,只需要定義好具體的 Packet 就好了。

更多原創好文

請關注「逅弈逐碼」

2b31d6cda77da562457d40ffdb802120.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533818.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533818.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533818.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux桌面時區設置,如何在Ubuntu 20.04上設置或更改時區

對于許多與系統相關的任務和進程&#xff0c;使用正確的時區至關重要。 例如&#xff0c;cron守護程序使用系統的時區執行cron作業&#xff0c;而日志文件中的時間戳基于系統的同一時區。在Ubuntu上&#xff0c;系統的時區是在安裝過程中設置的&#xff0c;但以后可以輕松更改。…

ironpython2.7.9_IronPython下載

IronPython是一種在 .NET 及 Mono上的 Python 實現&#xff0c;由微軟的 Jim Hugunin所發起&#xff0c;是一個開源的項目&#xff0c;基于微軟的DLR引擎&#xff1b;托管于微軟的開源網站 CodePlex。IronPython 的官方并未實現 Python通用類庫&#xff0c;僅實現了部分核心類。…

python 最小二乘回歸 高斯核_「機器學習」一文讀懂線性回歸、嶺回歸和Lasso回歸...

點擊上方藍色字體&#xff0c;關注AI小白入門喲作者 | 文杰編輯 | yuquanle本文介紹線性回歸模型&#xff0c;從梯度下降和最小二乘的角度來求解線性回歸問題&#xff0c;以概率的方式解釋了線性回歸為什么采用平方損失&#xff0c;然后介紹了線性回歸中常用的兩種范數來解決過…

天宮初級認證答案_跨境電商人才初級認證試題以及答案

跨境電商人才初級認證試題以及答案跨境電商人才初級認證試題一&#xff0c;單選題(共40題,每題1分,共40分)1.在拍攝反光性產品時,就是從哪個角度進行拍攝的A、正面B、側面參考答案:B2.信用證就是一種( )信用A、商業B、銀行C、民間D、企業參考答案:B3、阿里巴巴專業術語中,MA的全…

Linux打包軟件版本帶時間,帶你寫一個 linux 下的打包軟件 tar

相信你對 linux 的 .tar.gz 有點熟悉&#xff0c;這就是先 tar 打包(.tar 后綴)&#xff0c;再對此 tar 文件用 gzip 壓縮(.tar.gz)的后綴名。值得注意的是&#xff0c; tar 不是壓縮軟件&#xff0c;它只做把一堆文件/文件夾打包到一個文件(tar 文件)里的事情&#xff0c;而文…

優先隊列默認是小頂堆嗎_一分鐘帶你讀懂什么是堆?

堆其實就是一種特殊的隊列——優先隊列。 普通的隊列游戲規則很簡單&#xff1a;就是先進先出&#xff1b;但這種優先隊列搞特殊&#xff0c;不是按照進隊列的時間順序&#xff0c;而是按照每個元素的優先級來比拼&#xff0c;優先級高的在堆頂。 這也很容易理解吧&#xff0c;…

螺旋測微器b類不確定度_物理實驗直測量不確定度評估.ppt

物理實驗直測量不確定度評估直接測量不確定度評估 Gauss分布 測量列的平均值、標準差 A類不確定度 t分布 B類不確定度 直接測量的合成不確定度 Gauss分布 也稱正態分布。 δ的平均值等于0、方差為σ。 特征&#xff1a; 對稱性——大于平均值與小于平均值的概率相等&#xff1b…

python 執行shell_python執行shell命令的方法

python執行shell命令的方法 os模塊 os.system方式&#xff1a; import os os.system(top) os.system(cat /proc/cpuinfo) 說明 這個調用相當直接&#xff0c;且是同步進行的&#xff0c;程序需要阻塞并等待返回。 返回值是依賴于系統的&#xff0c;直接返回系統的調用返回值&am…

linux下c語言讀取roed文件,如何在Linux系統上安裝Android4.4.docx

Android (x86)項目致力于移植 Android系統到X86處理器上&#xff0c;使用戶可以更容易的在任何電腦上安裝Android。他們通過使用android源碼&#xff0c;增加補丁來使 Android能夠在X86處理器&#xff0c;筆記本電腦和平板 電腦下工作。前一段時間&#xff0c;項目組發布了最新…

微信小程序setinterval_簡單談談setTimeout與setInterval

感謝踩過的坑sf社區的第一篇文章。最近在做一個拍賣的微信小程序&#xff0c;用到了定時器setTimout和setInterval,簡單談談這兩個api。setTimeout最常見的用法就是第二種(第三種mdn文檔不推薦)&#xff0c;如:var timeoutId setTimeout(function() {console.log(hello world!…

python 注釋一段話_Python快速入門(一)

引言Python作為一個&#xff0c;目前最火的編程語言之一&#xff0c;已經滲透到了各行各業。它易學好懂&#xff0c;擁有著豐富的庫&#xff0c;功能齊全。人生苦短&#xff0c;就用Python。這個快速入門系列分為六篇&#xff0c;包含了Python大部分基礎知識&#xff0c;每篇閱…

linux ibus獲取窗體位置,Ubuntu 12.04 顯示ibus 的輸入框

在虛擬機中安裝了Ubuntu 12.04&#xff0c;系統是英文版本的&#xff0c;我能接受&#xff0c;但是苦于沒有中文輸入法。起先&#xff0c;我是安裝SCIM&#xff0c;結果我折騰了半天&#xff0c;發現其只能在lib-office下使用。firefox,文字編輯器中都不能調出SCIM。無奈將其卸…

transporter上傳卡正在交付_【iOS】Xcode11使用Transporter將APP上傳到App Store,卡在正在驗證APP...

問題&#xff1a;在使用Transporter時&#xff0c;會卡主&#xff0c;一直顯示正在驗證APP在這里插入圖片描述解決方案一&#xff1a;利用V-P-N在這里插入圖片描述使用安全上網(V-P-N)&#xff0c;雙擊打開iTMSTransporter&#xff0c;等待幾分鐘lichuangMacBook-Pro-3 ~ % /Ap…

python練手經典100例微盤_20個Python練手經典案例,能全做對的人確實很少!

100個Python練手小程序&#xff0c;學習python的很好的資料&#xff0c;覆蓋了python中的每一部分&#xff0c;可以邊學習邊練習&#xff0c;更容易掌握python。 如果你感覺學不會&#xff1f;莫慌&#xff0c;小編推薦大家加入群&#xff0c; 前面548中間377后面875&#xff0…

小紅帽linux各功能中英,英文短劇《小紅帽》劇本臺詞完整版---中英對照文本版...

大灰狼和小紅帽的故事紅帽第一場&#xff1a;小紅帽家 媽媽&#xff1a; (媽媽拿著一個籃子&#xff0c;把桌子上的水果放在籃子里) 小紅帽唱著歌&#xff0c;歡快地跑進來)Hi,mummy, what are you doing? 嘿&#xff0c;媽媽 你在什么&#xff1f; 媽媽&#xff1a; (一邊把水…

uipath循環datatable_UiPath之DataTable轉換為List和Array

今天給大家分享一下&#xff0c;如何將DataTable轉為List和Array&#xff0c;為此小U也花了不少時間研究&#xff0c;最后發現沒有那么復雜。先來說說List和Array的區別&#xff1a;List&#xff1a;就像一個鏈條&#xff0c;存儲數據的空間可以不連續。Array&#xff1a;就像一…

python批量下載文件教程_Python抓包菜鳥教程:批量下載圖片的方法,電腦和手機都能用...

筆者看上了一組圖集&#xff0c;然后準備一張一張下載時&#xff0c;瞄了一眼&#xff0c;這組圖集還有100&#xff0c;好吧&#xff0c;我酸了。 筆者就是試試工具&#xff0c;你們別像我這樣用&#xff0c;這么好的工具&#xff0c;做自媒體&#xff0c;那絕對了那如何批量下…

esxi掛載Linux的nfs盤,ESXi安裝centos7掛載群暉NFS

前段時間折騰了ESXi&#xff0c;然后無盡的折騰接踵而來&#xff0c;今天要說的是如何安裝centos7并掛載群暉虛擬機的NFS共享文件夾直接步入正題&#xff01;先是下載centos7鏡像&#xff0c;因為我是用來當服務器的&#xff0c;所以只需要minimal版即可【centos下載鏈接】自己…

python使用的編輯器_我用過的最好的python編輯器PyScripter

用了IDLE, PythonWin等幾個python編輯器&#xff0c;在代碼補全、參數提示等功能上都非常不滿意。 終于找到PyScripter并且試用了一下&#xff0c;代碼補全、參數提示等功能非常強大。這個功能其實非常重要&#xff0c;可以大大提高開發效率&#xff0c;減少出錯。很滿意.PyScr…

linux is not unix由來,一些奇怪的 unix 指令名字的由來(轉)

一些奇怪的 unix 指令名字的由來(轉)[more]一些奇怪的 unix 指令名字的由來awk "Aho Weinberger and Kernighan"這個語言以作者 Al Aho, Peter Weinberger 和 Brian Kernighan 的姓來命名。grep "Global Regular Expression Print"grep 來自 ed 的列印所…