search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

ONOS集群原理及流程分析

作者簡介:陳曉帆,畢業於中山大學,博士,目前是深信服的技術專家,主要負責SDN/NFV,雲計算相關的預研工作。這份文檔主要是依據我和另外兩位小夥伴(hgl,zll)最近對ONOS的原理和代碼流程的分析整理而成。本文所有觀點僅代表作者個人觀點,與作者目前所在的公司無關。

一、ONOS集群原理簡介

ONOS是一個分散式的控制器,為了提高數據的讀寫效率,採用自實現的基於In-Memory的Key-Value數據存儲系統。針對實際的需要,不同的數據模型採用不同的數據一致性方法,即強一致性(strong consistency)和最終一致性(eventually consistency)。ONOS使用raft協議實現強一致性,使用Gossip協議實現最終一致性。

ONOS在後面的版本中使用自研的基於raft協議的分散式存儲系統,ONOS使用的是基於Java實現的CopyCat版本,採用基於raft協議的分散式協同框架Atomix。

為了提高數據的訪問效率,ONOS數據採用了分片存儲,在ONOS形成集群后,會在$ONOS_ROOT/下生產一個config文件夾,文件夾裡面有個cluster.json文件,裡面就是該ONOS的分片信息。ONOS啟動后,PartitionManager會根據分片信息來創建相應的目錄和文件,如$KARAF_ROOT/data/partitions/目錄下的文件夾及文件。

二、Partition形成

ONOS開啟后,PartitionManager會作為服務而被載入,載入時就會調用它的activate方法,它會根據分片信息(也就是本機存儲的Metadata)來創建partitions目錄下的信息,該文件夾會作為參數傳入StoragePartition的構造函數。StoragePartition是ONOS自實現的Key-Value存儲系統中Value的一種類型。

PartitionManager接下來會調用第三方的框架去實現集群的管理。首先是創建相應的StoragePartitionClient,StoragePartitionServer來為集群的運行和管理做準備。程序會根據每個Partition的members的組成來決定相應的Server和Client的開啟。

開啟Server:

在開啟Server的過程中會在該Server的文件夾下創建幾個文件來輔助集群的運行,這幾個文件可以在$KARAF_ROOT/data/partitions/1(示例實驗是單個節點,所以只有一個partition)中看到,分別是該raft集群的:meta;log;snapshot。(ONOS的raft是實現是用了第三方的框架,該三個文件夾的具體作用,以及存儲了哪些東西,或是自己想要開發新的東西,都可以去Coptcat的官網查看具體說明)。

下圖是CopycatServer相關文件,管理等的創建,具體可以參考CopycatServer的builder方法(可以單步調試看看ServerContext的創建過程):

以上是進入ServerContext的創建過程,紅色框框即是Partition中存儲的文件,Copycat中都有對應的類對應。Raft的存儲和一致性就是通過日誌來實現的。Snapshot只要是輔助Log Compaction。

開啟Client:

DistributedClusterStore中沒有用到分散式原語,所以它只是保存單機的數據,不會被同步到其他機器上面。

三、集群形成

使用onos-form-cluter命令形成集群時,會調用ClusterManager的formCluster方法。

這個方法會調用buildDefaultPartitions來創建Partitions。

首先對node進行排序,設置框大小為partitionSize,每次在框裡面的node就是該Partition的member,框每次向右移動一個node,partition的命名從1開始依次遞增至n(n為集群中onos的總數)。

formCluster方法會創建形成集群后的Metadata,並設置該數據,該數據會寫到硬碟的$ONOS_ROOT/config/cluster.json文件裡面,然後onos會刪除partitions文件夾和它裡面的內容,重新啟動后,onos會按照cluster.json文件裡面的信息來啟動onos,PartitionManager會根據Metadata裡面的partitions信息來創建partition。

onos原始的形成集群流程如下:

四、copycat日誌分析

Java8提供了一種函數風格的非同步和事件驅動編程模型CompletableFuture。

日誌是raft一致性演算法的核心,當命令提交到群集時,表示狀態更改的條目被寫入磁碟上的有序日誌中。日誌提供了實現持久性和一致性的機制。

但是日誌在管理磁碟消費方面有特殊的挑戰。隨著命令逐漸寫入每個伺服器上的日誌中,日誌文件會消耗越來越多的磁碟空間。最終,每個伺服器上的磁碟空間會被日誌文件耗盡。

raft一致性演算法的典型實現使用基於快照的方法來壓縮伺服器日誌。但是為了尋找更一致的性能,並且由於Copycat會話事件演算法的獨特需求,Copycat選擇了一種增量日誌壓縮演算法。

Copycat的日誌被分成若干段,日誌的每個段都由磁碟上的一個文件(或內存塊)表示,每個段都包含一系列條目。一旦某個段變得完整,要麼取決於它的大小,要麼取決於條目的數量——日誌會滾到一個新的段中。每個段都有一個64位元組的標題,用來描述段的起始索引、時間戳、版本以及與日誌壓縮和恢復相關的其他信息。

日誌中的每個條目都是用16位無符號長度、32位無符號偏移量和可選的64位術語編寫的。因為raft保證日誌中的術語是單調遞增的,所以這個術語只寫在某個給定段中的第一個條目中,所有後面的條目都繼承這個術語。當附加一個新項的條目時,該條目用新術語編寫,後面的條目繼承這個術語。

五、強弱一致性分析

ONOS提供了一些分散式數據結構(distributed primitive)來實現數據的強一致性和最終一致性存儲。應用開發者可以運用它們來開發相應的應用。強一致性是通過raft來實現,而弱一致性是通過事件樂觀非同步複製和anti-entropy(gossip)協議實現最終一致性。

弱一致性如EventuallyConsistentMap用來存貯一個最終一致性map,當有節點的map值發生更新時,ONOS會廣播更新時間,其它的節點會通過比較時間戳來更新map的值。另外,當有新節點加入或有節點的數據突然丟失時,ONOS使用anti-entropy(gossip)協議來確保數據的最終一致性。這些狀態都是存儲在ONOS的內存裡面,所以當整個集群重新啟動時,數據會丟失。

5.1 強一致性分散式存儲實例分析

強一致性分散式存儲實例主要通過Network/config的API介面下發配置。配置信息保存在DistributedNetworkConfigStore中,該配置信息的保存使用了強一致性的分散式原語ConsistentMap。

上圖第一個紅框是存儲配置信息ConsistentMap的聲明,第二個紅框是ConsistentMap的創建初始化,這個過程是在DistributedNetworkConfigStore的acvivate方法中進行的。

這個過程調用storageService來創建我們的分散式數據結構。

onos調用storageService服務來創建ConsistentMap,DefaultConsistentMapBuilder會提供一些方法來設置ConsistentMap的屬性,設置完了屬性之後,調用build方法來創建符合要求的ConsistentMap。

數據如何映射到分片信息,Hasher是系統寫的對象映射PartitionId的介面,他的實現具體如下:

具體的調用過程如下:

Hasher是系統寫的對象映射PartitionId的介面,該介面決定了配置數據是如何映射到分片信息。

5.2 弱一致性分析

ONOS提供了一些分散式數據結構(distributed primitive)來實現數據的強一致性和最終一致性存儲。下面來討論一下ONOS的弱一致性。

EventuallyConsistentMap是ONOS提供的用來實現弱一致性的分散式原語,它的實現類中提供了一系列參數來設置它的屬性,其中就有一個是設置該Map的值是否存儲在硬碟上,下面就流程做一個簡單的說明。以下例子是以網路拓撲為例。

在DistributedTopologyStore的activate方法中,我們在創建存儲網路拓撲EventuallyConsistentMap的地方打上斷點。

上圖第一個紅框是DistributedTopologyStore中EventuallyConsistentMap的聲明,第二個紅框是它的創建初始化。初始化時,會調用StorageService去創建,上圖紅框是要傳遞的參數persistentService,弱一致性的數據想要存儲在硬碟上面,必須通過該服務來創建相應的persistentMap或者persistentSet,該項服務會把數據存儲在由PersistenceManager提供的localDB中。

上圖是EventuallyConsistentMap的創建過程。這個過程通過EventuallyConsistentMapbuilderImpl來控制,上面兩個紅框是我們今天重點關注的兩個屬性,一個就是我們的persistentService,還有一個就是設置是否將弱一致性數據保存在硬碟上面。

EventuallyConsistentMapbuilderImpl提供了一些方法來設置屬性。

屬性等設置完畢后,要調用build方法來創建EventuallyConsistentMap。

最後通過EventuallyConsistentMapImpl去創建EventuallyConsistentMap,過程中會根據persistent(boolean)的值來決定是否調用persistentService這個服務。

微信ID:S


熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦