【RocketMQ】NameServer總結

NameServer是一個注冊中心,提供服務注冊和服務發現的功能。NameServer可以集群部署,集群中每個節點都是對等的關系(沒有像ZooKeeper那樣在集群中選舉出一個Master節點),節點之間互不通信。
服務注冊
Broker啟動的時候會向所有的NameServer節點進行注冊,注意這里是向集群中所有的NameServer節點注冊,而不是只向其中的某些節點注冊,因為NameServer每個節點都是對等的,所以Broker需要向每一個節點進行注冊,這樣每一個節點都會有一份Broker的注冊信息。

服務發現
Broker向NameServer注冊以后,生產者Producer和消費者Consumer就可以從NameServer中獲取所有注冊的Broker信息,并從中選取Broker進行消息的發送和消費。

以生產者為例,在NameServer集群部署模式下,生產者會從多個NameServer中隨機選取一個進行通信,從中拉取所有Broker的注冊信息,并將拉取到的信息進行緩存,生產者知道了Broker的信息后,就可以得知Topic的分布情況,然后選取一個消息隊列,與其所在的Broker通信進行消息的發送。如果通信的Nameservre宕機,消費者會輪詢選擇下一個NameServer。

為什么需要NameServer?

在使用RocketMQ的時候,為了提升性能以及應對高并發的情況,一般都會使用多個Broker進行集群部署,假設沒有注冊中心,對于Broker來說,如果想獲取到集群中所有的Broker信息(生產者和消費者需要通過某個Broker獲取整個集群的信息,從而得到Topic的分布情況),每個Broker都需要與其他Broker通信來交換信息,以此來得到集群內所有Broker的信息,在Broker數量比較大的情況下,會造成非常大的通信壓力。

為什么不使用zookeeper這樣的分布式協調組件?
首先zookeeper的實現復雜,引入zookeeper會增加系統的復雜度,并且zookeeper在CAP中選擇了CP,也就是一致性和分區容錯性,從而犧牲了可用性,為了保持數據的一致性會在一段時間內會不可用。

而NameServer在實現上簡單,RocketMQ的設計者也許認為對于一個消息隊列的注冊中心來說,一致性與可用性相比,可用性更重要一些,至于一致性可以通過其他方式來解決。

假如選擇了CP的ZooKeeper,先不考慮其他原因,在ZooKeeper不可用的時候,如果有消費者或生產者剛好需要從NameServer拉取信息,由于服務不可用,導致生產者和消費者無法進行消息的生產和發送,在高并發或者數據量比較大的情況下,大量的消息無法發送/無法消費影響是極大的,而如果選擇AP,即便數據暫時處于不一致的狀態,在心跳機制的作用下也可以保證數據的最終一致性,所以RocketMQ選擇了自己實現注冊中心,簡單并且輕量

舉個例子,假如集群中有三個Broker(分別為 A、B、C),向三臺NameServer進行了注冊(也分別為A、B、C),消費者從NameServer中獲取到了三個Broker的信息,如果此時BrokerA需要停止服務,分別通知三臺NameServer需要下線,從NameServer中剔除該Broker的信息,由于網絡或者其他原因,NameServer A和B收到了下線的請求,NameServer C并未收到,此時就處于數據不一致的狀態,如果某個消費者是與NameServer C進行通信,會認為Broker還處于可用的狀態:

對于這種情況,首先NameServer與Broker之間會有一個心跳機制,NameServer定時檢測在某個時間范圍內是否收到了Broker發送的心跳請求,如果未收到,會認為該Broker不可用,將其剔除(在下面會講到),所以對于NameServer來說,盡管數據會暫時處于不一致的狀態,但是可以保證過一段時間之后恢復數據的一致性,也就是最終一致性。

對于消費者來說,既然可以從NameServer C中獲取到Broker A的信息,那么消費者就認為Broker A可用,如果發送的消息所在的消息隊列在Broker A中,就會與Broker A通信進行發送,但實際上Broker A實際上是不可用的,消息會發送失敗,所以RocketMQ設計了消息重試機制以及故障延遲機制。

Broker注冊

Broker啟動后會開啟定時向NameServer進行注冊(發送心跳包)的任務,發送心跳包的時間間隔可以在配置文件中進行設置,但是最長不能超過10s,也就是說Broker最長10秒鐘會向Nameserver發送一次心跳包。

NameServer收到Broker的注冊請求(心跳包)后,會判斷Broker之前是否已經注冊過,如果未注冊過將其加入到注冊的Broker集合brokerAddrTable中,同時也會記錄收到注冊請求的時間,將其加入到brokerLiveTable中,里面記錄了NameServer收到每個Broker發送心跳包的時間,在進行心跳檢測的時候根據這個時間戳來判斷是否在規定時間內未收到該Broker發送的心跳包。

讀寫鎖
由于NameServer可能同時收到多個Broker的注冊以及生產者或者消費者的拉取請求,為了保證數據的一致性(因為有讀寫請求同時發生或者寫與寫請求同時發生),在處理相關請求的時候需要加鎖,為了提高性能,使用了ReadWriteLock讀寫鎖,處理注冊請求時會先添加寫鎖,處理拉取請求時添加讀鎖,這樣如果某一時刻都是讀的請求可以同時進行,互不影響,如果有寫請求,其他請求就需要等鎖釋放才可以進行往下進行。如果不使用讀寫鎖,直接對所有的請求加鎖,會影響性能,實際上讀與讀之間并不需要加鎖。

心跳檢測

Nameserver在啟動的時候會開啟一個用于心跳檢測的定時任務(每10s執行一次),定時掃描處于不活躍狀態的Broker,如果在規定時間內未收到某個Broker的心跳包,會認為此Broker不可用,需要將其進行剔除。

上面說到brokerLiveTable保存了當前NameServer收到的心跳數據,里面記錄了每一個Broker最近進行注冊/發送心跳的時間戳,所以只需遍歷brokerLiveTable,獲取每一個Broker最近一次發送心跳的時間進行判斷,如果上一次發送心跳的時間 + 過期時間(120s) 小于 當前時間,也就是超過120s沒有收到某個Broker的心跳包,則認為此Broker已下線,將Broker移除

Broker下線

正常下線
當Broker下線的時候會向NameServer發起取消注冊的請求,NameServer收到請求后會將Broker剔除。

異常下線

如果Broker異常宕機,或者發送給NameServer的取消注冊請求由于某些原因并未發送成功,NameServer可能并未感知到Broker的下線,由于心跳機制定時檢測的功能,會在一段時間后發現未收到Broker的心跳請求,主動將Broker剔除。

生產者和消費者

生產者和消費者都會定時從NameServer中更新Broker的注冊信息,默認是30s進行一次更新:

public class MQClientInstance {private void startScheduledTask() {this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {try {// 更新路由信息 MQClientInstance.this.updateTopicRouteInfoFromNameServer();} catch (Exception e) {log.error("ScheduledTask updateTopicRouteInfoFromNameServer exception", e);}}}, 10, this.clientConfig.getPollNameServerInterval(), TimeUnit.MILLISECONDS);}
}

對應的相關源碼可參考:

【RocketMQ】【源碼】NameServer的啟動
【RocketMQ】【源碼】Broker服務注冊

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

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

相關文章

【通俗易懂】如何使用GitHub上傳文件,如何用git在github上傳文件

目錄 創建 GitHub 倉庫 使用 Git 進行操作 步驟 1:初始化本地倉庫 步驟 2:切換默認分支 步驟 3:連接到遠程倉庫 步驟 4:獲取遠程更改 步驟 5:添加文件到暫存區 步驟 6:提交更改 步驟 7&#xff1a…

Chrome 手動代理設置 HTTP/Socks5

1、安裝代理插件:SwitchyOmega 在線安裝 從 Chrome 應用商店 安裝,如果您無法從該鏈接安裝,請使用下面的離線安裝。 離線安裝 ①、去 Github 下載 最新版安裝包 ,或者直接 本地下載 文件進行安裝。 ②、下載安裝文件后&#xf…

[Vue warn]: Error in render: “SyntaxError: “undefined“ is not valid JSON“

[Vue warn]: Error in render: “SyntaxError: “undefined” is not valid JSON” 這說明出現了undefined這個變量類型,比如JSON.parse()時候會出現,可以先嘗試打印JSON.parse()括號中的內容是否是undefined,如果是,那問題的根源…

RenderDoc 導出Cubemap到UE

找到使用了Cubemap的模型,再Output里會顯示該模型使用的所有貼圖 ,選中Cubemap導出 選擇導出格式為HDR 導出的Cubemap是豎著的,需要再PS里逆時針旋轉90度 還有,導出的的Cubemap方向是錯的,需要把3,4 跟1,2 對換,6旋轉180度 UE 文檔里的方向參…

Spring Boot @Validated 驗證注解的使用

1、引入依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId> </dependency> 2、使用 2.1、非對象參數 參數如果是非對象格式&#xff0c;需要在controller類上面添…

JVM——HotSpot的算法細節實現

一、根節點枚舉 固定可作為GC Roots的節點主要在全局性的引用&#xff08;如常量或類靜態屬性&#xff09;與執行上下文&#xff08;如棧幀中的本地變量表&#xff09;中&#xff0c;盡管目標明確&#xff0c;但查找要做到高效很難。現在java應用越來越龐大&#xff0c;光方法區…

Code interpreter生成無聊的APP:病理圖像切割和提取

一、寫在前面 機器學習100步不夠分配了&#xff0c;所以開個新專欄&#xff0c;就叫做《Code interpreter生成無聊的APP》&#xff0c;旨在探索GPT-4官方插件Code interpreter的使用心路歷程。 主要靈感來源&#xff1a;聽戶主說&#xff0c;她們在做病理組學圖像標注和分割的…

如何用Apipost實現sign簽名?

我們平常對外的接口都會用到sign簽名&#xff0c;對不同的用戶提供不同的apikey ,這樣可以提高接口請求的安全性&#xff0c;避免被人抓包后亂請求。 如何用Apipost實現sign簽名&#xff1f; 可以在Apipost中通過預執行腳本調用內置的JS庫去實現預執行腳本是在發送請求之前自…

Wordcloud | 風中有朵雨做的‘詞云‘哦!~

1寫在前面 今天可算把key搞好了&#xff0c;不得不說&#x1f3e5;里手握生殺大權的人&#xff0c;都在自己的能力范圍內盡可能的難為你。&#x1f602; 我等小大夫也是很無奈&#xff0c;畢竟奔波霸、霸波奔是要去抓唐僧的。 &#x1f910; 好吧&#xff0c;今天是詞云&#x…

【C++精華鋪】8.C++模板初階

目錄 1. 泛型編程 2. 函數模板 2.1 函數模板的概念及格式 2.2 函數模板的原理 2.3 模板的實例化 2.4 模板參數的匹配原則 3. 類模板 3.1 類模板格式 3.2 類模板的實例化 1. 泛型編程 什么是泛型編程&#xff1f;泛型編程是避免使用某種具體類型而去使用某種通用類型來進行…

mysql中INSERT INTO ... ON DUPLICATE KEY UPDATE的用法,以及與REPLACE INTO 語句用法的異同

INSERT INTO ... ON DUPLICATE KEY UPDATE 是 MySQL 中一種用于插入數據并處理重復鍵沖突的語法。與之相似的還有 REPLACE INTO 語句。以下是它們的用法和異同點的詳細說明&#xff1a; 一、INSERT INTO ... ON DUPLICATE KEY UPDATE INSERT INTO ... ON DUPLICATE KEY UPDAT…

NET域名的優勢

NET域名是互聯網上最常見的頂級域名之一&#xff0c;其開放使用日期遠比其他主要頂級域名早&#xff0c;始于1985年。其作為商業網絡服務提供者的域名&#xff0c;主要用于企業、組織和個人等在網絡上建立自己的網站。本文將從以下三個方面介紹NET域名。 一、NET域名的歷史 N…

帶你了解—使用內網穿透,公網遠程訪問本地硬盤文件

文章目錄 前言1. 下載cpolar和Everything軟件3. 設定http服務器端口4. 進入cpolar的設置5. 生成公網連到本地內網穿透數據隧道 總結 前言 隨著云概念的流行&#xff0c;不少企業采用云存儲技術來保存辦公文件&#xff0c;同時&#xff0c;很多個人用戶也感受到云存儲帶來的便利…

如何使用Java代碼收集網站所有功能

使用Java代碼收集網站所有功能的步驟可以這么實現: 1. 使用JSoup等工具解析網站首頁HTML,獲取超鏈接、表單等元素。 Document doc JSoup.connect("http://website.com").get(); Elements links doc.select("a[href]"); Elements forms doc.select(&qu…

學習ts(四)聯合類型、交叉類型、類型斷言

聯合類型 使用聯合類型定義屬性和方法&#xff0c;只要符合其中一種即可 let myPhone: string | number 010-7788 // let myPhone1: string | number true 因為沒有包含boolean值 會報錯const fn (something: number | boolean): boolean > {return !!something }con…

【CSS動畫01--登錄】

CSS動畫01--登錄 介紹代碼HTMLCSSJS 介紹 當鼠標不同方向的劃過時展示不同效果的登錄&#xff0c;以上是一個簡單的圖片展示 代碼 HTML <!DOCTYPE html> <html> <head><meta http-equiv"content-type" content"text/html; charsetutf-8&…

生物筆記——暑期學習筆記(四)

生物筆記——暑期學習筆記&#xff08;四&#xff09; 文章目錄 前言一、R篇1. unname()2. duplicated()3. 數據提取4. 分組 二、生信篇1. 文本處理常用命令2. 命令輸出1. 重定向2. 多命令執行 3. 文本工具4. 本地hmm鑒定1. hmmer軟件安裝2. 文件準備3. 基于hmm的鑒定 總結 前言…

【制作npm包5】npm包制作完整教程,我的第一個npm包

制作npm包目錄 本文是系列文章&#xff0c; 作者一個橙子pro&#xff0c;本系列文章大綱如下。轉載或者商業修改必須注明文章出處 一、申請npm賬號、個人包和組織包區別 二、了解 package.json 相關配置 三、 了解 tsconfig.json 相關配置 四、 api-extractor 學習 五、npm包…

MySQL的配置文件my.cnf與my.ini

一、my.cnf與my.ini win系統&#xff0c;MySQL配置文件為my.ini 其他系統&#xff08;Ubuntu、CentOS、macOS)MySQL配置文件為my.cnf 二、my.cnf與my.ini的路徑 2.1 默認路徑 MySQL 的配置文件 my.cnf 可能位于多個位置&#xff0c;具體取決于安裝方式和操作系統。以下是一…

Redis如何處理內存溢出的情況?

當Redis的內存使用達到上限時&#xff0c;會出現內存溢出的情況。Redis提供了幾種處理內存溢出的機制&#xff1a; 內存淘汰策略&#xff1a;Redis提供了多種內存淘汰策略&#xff0c;用于在內存不足時選擇要移除的鍵。常見的淘汰策略包括&#xff1a; LRU&#xff08;Least Re…