1. 程式人生 > >elasticsearch原始碼分析之discovery(七)

elasticsearch原始碼分析之discovery(七)

Discovery模組概述

elasticsearch中的Discover模組,這個模組主要是發現模組負責發現叢集中的節點,以及選取主節點。用作處理elasticsearch中的叢集問題,是elasticsearch中比較複雜的一個模組。 
discovery有幾類:

  • Azure discovery(類似於多播),它可作為外掛使用。
  • EC2 discovery,作為外掛使用。
  • Google Compute Engine (GCE) discovery (類似於多播),它可作為外掛使用。
  • zenDiscovery是elasticsearch的內建並且預設的discovery模組。 它提供unicast發現,並且擴充套件到支援雲環境和其他形式的發現。

這裡我們只分析zenDiscovery。

Discovery子模組

ZenDiscover其實是由一些其他的模組配合而成的,比如node之間的通訊就是用的transport模組。ZenDiscover可以分為以下幾個子模組:

Ping

這是一個節點使用發現機制來查詢其他節點的過程。

Unicast

通過配置discovery.zen.ping.unicast對列表中的node單播。 
單播發現需要使用的主機列表作為傳播的路由器,它使用discovery.zen.ping.unicast字首提供以下設定:

可以是陣列設定或逗號分隔設定。 
每個值的格式應為host:port或host(其中,port預設為9300)。 請注意,IPv6主機必須加括號。 預設為127.0.0.1,[:: 1]

unicast discovery用transport模組來執行發現。

Master Election

用作Master的選舉;叢集的主節點被選舉或加入是ping過程的一部分。這是自動完成的。 
當主節點停止或遇到問題時,群集節點再次開始ping過程,並選擇一個新的主節點。這輪ping還用作對(部分)網路故障的保護,其中節點可能不正當地認為主節點已經故障。在這種情況下,節點將簡單地從其他節點聽到關於當前活動的主機的資訊。 
discovery.zen.minimum_master_nodes設定需要加入新選擇的主節點的主合格節點的最小數量,以便選擇完成,並且選擇的節點成為masternode。相同的設定控制應作為任何活動叢集的一部分的活動主機合格節點的最小數量。如果不滿足此要求,活動主節點將退出,並且將開始新的主節點選擇。

Fault Delection

用ping的方式來確定node是否在叢集裡面,有兩個fault detection程序執行。 第一個nodesFD是由master去ping所有其他叢集中的節點並驗證他們是活著的。 第二個masterFD是每個節點ping到master以驗證其是否仍然活著或者需要啟動選舉過程。 
有如下設定使用discovery.zen.fd字首控制fault detection過程:

ping_interval #節點被ping的頻率,預設為1s。 
ping_timeout #等待ping響應的時間長度,預設為30秒。 
ping_retries #ping失敗重試次數,預設為3。

Cluster state updates

這個只在master node上有效,用於向其他node釋出叢集的狀態資訊。 
master節點是叢集中可以更改叢集狀態的唯一節點。 master一次處理一個群集狀態更新,修改更新並將更新的群集狀態釋出到群集中的所有其他節點。 每個節點接收發布過來的訊息,更新其本地的叢集狀態,並且響應給主節點。主節點會等待所有節點的響應,直到一個超時時間,在這之前後面的更新請求都會排在一個佇列中。 discovery.zen.publish_timeout預設設定為30秒,可以通過叢集更新設定api動態更改。

No master block

要使叢集完全可操作,它必須具有活動的master節點,並且執行的主節點合格節點數必須滿足discovery.zen.minimum_master_nodes設定(如果設定)。 
discovery.zen.no_master_block設定控制當沒有活動主機時應拒絕哪些操作。

discovery.zen.no_master_block設定有兩個有效選項:

all 
節點上的所有操作讀和寫操作都將被拒絕。這也適用於api叢集狀態讀取或寫入操作,如get索引設定,put對映和叢集狀態api。

write(預設值) 
寫操作將被拒絕。根據最後一個已知的叢集配置,讀取操作將成功。這可能導致過時資料的部分讀取,因為此節點可能與群集的其餘部分隔離。 
discovery.zen.no_master_block設定不適用於基於節點的api(例如cluster stats、 node info and node stats)。對這些API的請求不會被阻止,並且可以在任何可用節點上執行。

ZenDiscovery程式碼分析

建構函式

在ZenDiscovery建構函式中,初始化一些基本的服務介面和關鍵引數:

  • pingTimeout: 取自discovery.zen.ping_timeout(預設為3s)允許調整選舉時間來處理網路慢或擁塞的情況(更高的值確保更少的失敗機會)。
  • joinTimeout:取自discovery.zen.join_timeout(預設值為ping超時的20倍)。當一個新的node加入叢集時,將會發個join的request到master,這個request的timeout即joinTimeout。
  • joinRetryAttempts:join重試的次數,預設為3次。
  • joinRetryDelay:重試的間隔,預設為100ms。
  • maxPingsFromAnotherMaster:容忍其他master發出的,在強制其他或是本地master rejoin之前的次數。
  • masterElectionWaitForJoinsTimeout: master選舉時等待join的timeout,預設是joinTimeout的一半。
  • masterElectionFilterClientNodes:取自discovery.zen.master_election.filter_client為true(預設值為true) 
    如果為true,則在主選舉期間忽略來自客戶機節點(節點node.client為true,或node.data和node.master都為false的節點)的ping。
  • masterElectionFilterDataNodes: 取自discovery.zen.master_election.filter_data(預設值為false),如果為true,則在主選舉期間將忽略來自非主節點資料節點(node.data=true,node.master=false)的ping。在主選舉期間總是觀察到來自master節點的ping。

joinRetryAttempts和maxPingsFromAnotherMaster必須大於等於1. 
構造方法

執行

ZenDiscovery的執行即幾個子模組的執行

joinThreadControl

首先要將自己加入叢集,使用joinThreadControl

1、首先是findMaster,findMaster通過pingService來實現,在這裡我們只探討unicast的ping的方式,主要的實現在sendPings這個方法裡面,讓我們來詳細看看這個方法是怎麼ping的。 
確定需要ping的目標:

  • 第一部分是其實是由clusterService.state().nodes()而得來,也就是擁有同一cluster.name的這些node
  • 第二部分是hostsProviders自動生成的hosts列表(此處怎麼來的還不清楚)
  • 第三部分是所以可能作為master的node
  • 第四部分是discovery.zen.ping.unicast.hosts配置的列表(主要在這裡)

這裡寫圖片描述

2、對nodesToPingSet排序,這個排序的依據是根據可能成為master的概率來的。將master node排在前面,data node排在後面;然後把第四部分的hosts加在最前面(人工配置的master,如果有的話肯定從中選擇),最後在加入剛才排序的集合,這樣組成新的集合nodesToPing。

3、分別對nodesToPing中的node傳送ping,如果transport連線在,將會發送一個ping request到目標node,傳送的邏輯是呼叫了TransportService,最終呼叫NettyTansport,tranport模組參照http://blog.csdn.net/thomas0yang/article/details/52355798。如果transport連線不在了,會先connectToNode建立連線,然後再發送ping request。

// if we find on the disco nodes a matching node by address, we are going to restore the connection 
// anyhow down the line if its not connected… 
// if we can’t resolve the node, we don’t know and we have to clean up after pinging. We do have 
// to make sure we don’t disconnect a true node which was temporarily removed from the DiscoveryNodes 
// but will be added again during the pinging. We therefore create a new temporary node

這一段解釋沒有看懂。。。

4、對ping之後有響應結果的集合進行過濾篩選,過濾邏輯參照上文中masterElectionFilterClientNodes和masterElectionFilterDataNodes解釋。 
pingMasters,即ping各個節點之後返回的各節點元資料中儲存的master節點,在pingMasters列表中不能包括本地節點,否則我們可能在ZenDiscovery中沒有檢查其他節點,直接選舉自己#innerJoinCluster(),造成腦裂。 
這裡寫圖片描述

5、然後建立兩個node列表,一個是activeNodes,表示所有active的node,joinedOnceActiveNodes,前者後者表示叢集中之前就存在的node。

6、 如果從之前的ping中沒有發現master,表示要重新選舉了;首先判斷active的master node是否大於配置中的minimumMasterNodes,不然是選舉不了master的。如果滿足minMaster,會優先從joinedOnceActiveNodes中選舉出master;若選不出才會從activeNodes中去選舉。選舉的邏輯比較簡單, 先排序,在排序時會remove掉不能作為master的node,排序完後將第一個作為master。

7、如果pingMasters不為空,表示已經有選舉出的master了,但是還在pingMasters列表中進行一次選舉,得到master。官方註解:lets tie break between discovered nodes。但是此時pingMasters中如果不一個master,則會出現了腦裂。

在加入集群后,node就根據自己的角色,做不同的事情。

master

如果當前node是master,會先等待來足夠的有資格成為master的節點join以完成主選舉(waitToBeElectedAsMaster方法), 如果是則會通過ClusterState更新任務變為主節點。 
更新任務參照這裡寫圖片描述
真正釋出狀態參照InternalClusterService.UpdateTask類的run方法, 
這裡寫圖片描述
然後會啟動nodesFD,nodesFD啟動一個schedulethreadPool.schedule(TimeValue.timeValueMillis(0), ThreadPool.Names.SAME, fd);去ping其他的node,相當於heartbeat,如果檢測失敗會被踢出叢集nodesFD.remove(node, NodeFD.this)。 
這裡寫圖片描述
(上面一些程式碼比較凌亂,有待深入研究)

如果當前node不是master,會向master發出一個join的request,注意這裡並不會開啟一個master fault detection;因為這一部分在processNextPendingClusterState中實現。

publishClusterState

這裡寫圖片描述

elasticsearch預設傳送state採用diff的方式,當然你也可以通過配置來設定discovery.zen.publish_diff.enable是否使用diff。 
ClusterState表示叢集的當前狀態。具體參照elasticsearch原始碼分析之Gateway(六)

叢集狀態物件是不可變的,除了{@link RoutingNodes}結構和和叢集狀態{@link #status},前者是根據{@link RoutingTable}的需求構建的,後者是在叢集狀態釋出和應用處理期間更新。叢集狀態只能在主節點上更新。所有更新都由單個執行緒執行,由{@link InternalClusterService}控制。每次更新後,{@link DiscoveryService#publish}方法會向群集中的所有其他節點發布群集狀態的新版本。實際的釋出機制委託給{@link Discovery#publish}方法,並取決於發現的型別。例如,對於本地發現,它由{@link LocalDiscovery#publish} 方法。在Zen發現中,它在{@link PublishClusterStateAction#publish}方法中處理。釋出機制可以被其他發現覆蓋。

叢集狀態實現{@link Diffable}介面,以支援釋出叢集狀態差異,而不是每次更改時的整個狀態。如果此節點存在於叢集狀態的先前版本中,則釋出機制應僅向節點發送差異。如果一個節點不存在於以前版本的叢集狀態,這樣的節點不太可能有以前的叢集狀態版本,應該傳送完整版本。為了確保差異應用於叢集狀態的正確版本,每個叢集狀態版本更新將生成{@link #stateUUID}唯一標識該版本的狀態。此uuid由{@link ClusterStateDiff#apply}方法驗證,以確保應用正確的差異。如果uuids不匹配,則{@link ClusterStateDiff#apply}方法會丟擲{@link IncompatibleClusterStateVersionException},這將導致向生成此異常的節點發送一個完整版本的叢集狀態。

傳送ClusterChangedEvent,這個類持有兩個clusterstate

private final ClusterState previousState;
private final ClusterState state;
  • 1
  • 2
  • 1
  • 2

這裡寫圖片描述

FaultDetection

MasterFaultDetection

MasterFaultDetection是每個節點ping到master,進行錯誤檢測。 
啟動時候連線masternode,並按照一定頻率ping master。 
這裡寫圖片描述
master接收到masterping,進行一系列校驗,返回空response 
這裡寫圖片描述
node端接收到response, 
這裡寫圖片描述
如檢測到master失效,則釋出master失效通知,啟動重新選舉 
這裡寫圖片描述

NodesFaultDetection

如果本node是master,而它又接收到來自其他node的再來看看NodesFaultDetection,則叢集裡有兩個master,一般稱之為“腦裂”。遇到這種情況時,node會比較自己的version和另外master的version;如果比別人的小,就會stop掉自己的nodesFD和masterFD,然後rejoin進叢集,開始joinThreadControl乾的那些事兒。如果version比別人的大,那麼當前node仍然是master,它會向另一個master發出rejoin指令。 
這裡寫圖片描述

終於完了,非同步跟蹤檢視程式碼比較累。 
Discover的內容比較多。這個模組主要的作用是維護這個叢集的狀態,並負責state的下發,master的選舉,配置的更新等等,是elasticsearch中較為核心的一個模組。

相關推薦

elasticsearch原始碼分析discovery()

Discovery模組概述 elasticsearch中的Discover模組,這個模組主要是發現模組負責發現叢集中的節點,以及選取主節點。用作處理elasticsearch中的叢集問題,是elasticsearch中比較複雜的一個模組。  discovery有幾類:

elasticsearch原始碼分析分片分配(十)

分片 什麼是分片 分片是把索引資料切分成多個小的索引塊,這些小的索引塊能夠分發到同一個叢集中的不同節點。在檢索時,檢索結果是該索引每個分片上檢索結果的合併。類似於資料庫的分庫分表。 為什麼分片 1、這樣可以提高讀寫效能,實現負載均衡。 2、副本容易

elasticsearch原始碼分析索引操作(九)

上節介紹了es的node啟動如何建立叢集服務的過程,這節在其基礎之上介紹es索引的基本操作功能(create、exist、delete),用來進一步細化es叢集是如果工作的。 客戶端部分的操作就不予介紹了,詳細可以參照elasticsearch原始碼分析之客戶

elasticsearch原始碼分析服務端(四)

上篇部落格說明了客戶端的情況,現在繼續分析服務端都幹了些啥,es是怎麼把資料插進去的,此處以transport的bulk為入口來探究,對於單個document的傳送就忽略了。 一、服務端接收 1.1接收訊息 在客戶端分析中已經提到,netty中通訊的處理類是Mes

elasticsearch原始碼分析啟動過程(二)

最近開始廣泛的使用elasticsearch,也開始寫一些java程式碼了,為了提高java程式碼能力,也為了更加深入一點了解elasticsearch的內部運作機制,所以開始看一些elasticsearch的原始碼了。對於這種廣受追捧的開源專案,細細品讀一定會受益匪淺,

elasticsearch原始碼分析叢集管理

一、背景 Elasticsearch是一個實時分散式搜尋和分析引擎。它讓你以前所未有的速度處理大資料成為可能。本文主要介紹實現分散式搜尋和分析的基礎–儲存,好的儲存設計在根本上決定了查詢的效能。 es的儲存本質上是採用了lucene全文索引,在其基礎上實現了分散式功

elasticsearch原始碼分析Transport(五)

一、基本介紹 1.1概念介紹 transport模組是es通訊的基礎模組,在elasticsearch中用的很廣泛,比如叢集node之間的通訊、資料的傳輸、transport client方式的資料傳送等等,只要數和通訊、資料傳輸相關的都離不開transport模組的

elasticsearch原始碼分析search查詢(十一)

分散式查詢 elasticsearch的搜尋主要分為結構化搜尋和全文檢索。 結構化搜尋(Structured search) 是指有關探詢那些具有內在結構資料的過程。比如日期、時間和數字都是結構化的:它們有精確的格式,我們可以對這些格式進行邏輯操作。比較常見

spark 原始碼分析 -- Spark磁碟儲存剖析

上篇文章 spark 原始碼分析之十六 -- Spark記憶體儲存剖析 主要剖析了Spark 的記憶體儲存。本篇文章主要剖析磁碟儲存。 總述 磁碟儲存相對比較簡單,相關的類關係圖如下:     我們先從依賴類 DiskBlockManager 剖析。 &

istio原始碼分析pilot-discovery模組分析(中)_Kubernetes中文社群

Istio是由Google/IBM/Lyft共同開發的新一代Service Mesh開源專案。 上次我們深入剖析了pilot-discovery的部分功能,這次讓我們一起來看看pilot-discovery的其他功能。 注:本文分析的istio程式碼版本為0.8.0,commit為0cd8d6

istio原始碼分析pilot-discovery模組分析(上)_Kubernetes中文社群

Istio是由Google/IBM/Lyft共同開發的新一代Service Mesh開源專案。 上次我們深入剖析了pilot-agent的各個功能,這次讓我們一起來看看pilot-discovery有何功能。 注:本文分析的istio程式碼版本為0.8.0,commit為0cd8d67,com

netty(十原始碼分析客戶端建立

相對於服務端,Netty客戶端的建立更加複雜,除了要考慮執行緒模型、非同步連線、客戶端連線超時等因素外,還需要對連線過程中的各種異常進行考慮。 下面我們直接分析客戶端連線操作: 首先要建立和初始化NioSocketChannel,程式碼如下: private Cha

Spring原始碼分析IOC(

前面分析了finishBeanFactoryInitialization();留一下了doGetBean()這個方法,由於這個方法是Spring IOC的例項化真正工作的方法,所以特地拿出來單獨來說。 doGetBean()方法太長,下面截圖按照順序剪下來的話

Alink漫談(十) :Word2Vec原始碼分析 迭代訓練

# Alink漫談(十七) :Word2Vec原始碼分析 之 迭代訓練 [ToC] ## 0x00 摘要 Alink 是阿里巴巴基於實時計算引擎 Flink 研發的新一代機器學習演算法平臺,是業界首個同時支援批式演算法、流式演算法的機器學習平臺。本文和上文將帶領大家來分析Alink中 Word2Vec

Spark原始碼分析Spark Shell(上)

https://www.cnblogs.com/xing901022/p/6412619.html 文中分析的spark版本為apache的spark-2.1.0-bin-hadoop2.7。 bin目錄結構: -rwxr-xr-x. 1 bigdata bigdata 1089 Dec

Netty 原始碼分析拆包器的奧祕

為什麼要粘包拆包 為什麼要粘包 首先你得了解一下TCP/IP協議,在使用者資料量非常小的情況下,極端情況下,一個位元組,該TCP資料包的有效載荷非常低,傳遞100位元組的資料,需要100次TCP傳送,100次ACK,在應用及時性要求不高的情況下,將這100個有效資料拼接成一個數據包,那會縮短到一個TCP資

Android原始碼分析為什麼在onCreate() 和 onResume() 獲取不到 View 的寬高

轉載自:https://www.jianshu.com/p/d7ab114ac1f7 先來看一段很熟悉的程式碼,可能在最開始接觸安卓的時候,大部分人都寫過的一段程式碼;即嘗試在 onCreate() 和 onResume() 方法中去獲取某個 View 的寬高資訊: 但是列印輸出後,我們會發

netty原始碼分析服務端啟動

ServerBootstrap與Bootstrap分別是netty中服務端與客戶端的引導類,主要負責服務端與客戶端初始化、配置及啟動引導等工作,接下來我們就通過netty原始碼中的示例對ServerBootstrap與Bootstrap的原始碼進行一個簡單的分析。首先我們知道這兩個類都繼承自AbstractB

SNMP原始碼分析(一)配置檔案部分

snmpd.conf想必不陌生。在程序啟動過程中會去讀取配置檔案中各個配置。其中幾個引數需要先知道是幹什麼的:   token:配置檔案的每行的開頭,例如 group MyROGroup v1 readSec 這行token的引數是group。  

【kubernetes/k8s原始碼分析】kubelet原始碼分析cdvisor原始碼分析

  資料流 UnsecuredDependencies -> run   1. cadvisor.New初始化 if kubeDeps.CAdvisorInterface == nil { imageFsInfoProvider := cadv