91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

深入淺出etcd系列Part 1 – etcd架構和代碼框架

發布時間:2020-07-13 10:43:15 來源:網絡 閱讀:476 作者:CCE華為云 欄目:云計算

1、緒論
etcd作為華為云PaaS的核心部件,實現了PaaS大多數組件的數據持久化、集群選舉、狀態同步等功能。如此重要的一個部件,我們只有深入地理解其架構設計和內部工作機制,才能更好地學習華為云Kubernetes容器技術,笑傲云原生的“江湖”。本系列將從整體框架再細化到內部流程,對etcd的代碼和設計進行全方位解讀。本文是《深入淺出etcd》系列的第一篇,重點解析etcd的架構和代碼框架,下文所用到的代碼均基于etcd v3.2.X版本。

另,由華為云容器服務團隊傾情打造的《云原生分布式存儲基石:etcd深入解析》一書已正式出版,各大平臺均有發售,購書可了解更多關于分布式key—value存儲和etcd的相關內容!

2、etcd簡介
etcd是一個分布式的key-value存儲系統,底層通過Raft協議進行leader選舉和數據備份,對外提供高可用的數據存儲,能有效應對網絡問題和機器故障帶來的數據丟失問題。同時它還可以提供服務發現、分布式鎖、分布式數據隊列、分布式通知和協調、集群選舉等功能。為什么etcd如此重要?因為etcd是Kubernetes的后端唯一存儲實現,毫不夸張地說,etcd就是Kubernetes的“心臟”。

2.1 Raft協議
要理解etcd分布式協同的工作原理,必須提到Raft算法。Raft算法是斯坦福的Diego Ongaro、John Ousterhout兩人以易懂(Understandability)為目標設計的一致性共識算法。在此之前,提到共識算法(Consensus Algorithm)必然會提到Paxos,但是Paxos的實現和理解起來都非常復雜,以至于Raft算法提出者的博士論文中,作者提到,他們用了將近一年時間研究這個算法的各種解釋,但還是沒有完全理解這個算法。Paxos的算法原理和真正實現也有很大的距離,實現Paxos的系統,如Chubby,對Paxos進行了很多的改進有優化,但是細節卻是不為人所知的。 Raft協議采用分治的思想,把分布式協同的問題分為3個問題:

選舉: 一個新的集群啟動時,或者老的leader故障時,會選舉出一個新的leader;

日志同步: leader必須接受客戶端的日志條目并且將他們同步到集群的所有機器;

安全: 保證任何節點只要在它的狀態機中生效了一條日志條目,就不會在相同的key上生效另一條日志條目。

一個Raft集群一般包含數個節點,典型的是5個,這樣可以承受其中2個節點故障。每個節點實際上就是維護一個狀態機,節點在任何時候都處于以下三種狀態中的一個。

leader:負責日志的同步管理,處理來自客戶端的請求,與Follower保持這heartBeat的聯系;

follower:剛啟動時所有節點為Follower狀態,響應Leader的日志同步請求,響應Candidate的請求,把請求到Follower的事務轉發給Leader;

candidate:負責選舉投票,Raft剛啟動時由一個節點從Follower轉為Candidate發起選舉,選舉出Leader后從Candidate轉為Leader狀態。

節點啟動以后,首先都是follower狀態,在follower狀態下,會有一個選舉超時時間的計時器(這個時間是在配置的超時時間基礎上加一個隨機的時間得來的)。如果在這個時間內沒有收到leader發送的心跳包,則節點狀態會變成candidate狀態,也就是變成了候選人,候選人會循環廣播選舉請求,如果超過半數的節點同意選舉請求,則節點轉化為leader狀態。如果在選舉過程中,發現已經有了leader或者有更高的任期值的選舉信息,則自動變成follower狀態。處于leader狀態的節點如果發現有更高任期值的leader存在,則也是自動變成follower狀態。

Raft把時間劃分為任期(Term)(如下圖所示),任期是一個遞增的整數,一個任期是從開始選舉leader到leader失效的這段時間。有點類似于一屆總統任期,只是它的時間是不一定的,也就是說只要leader工作狀態良好,它可能成為一個獨裁者,一直不下臺。

2.2 etcd的代碼整體架構

從大體上可以將其劃分為以下4個模塊:

  • http:負責對外提供http訪問接口和http client

  • raft 狀態機:根據接受的raft消息進行狀態轉移,調用各狀態下的動作。

  • wal 日志存儲:持久化存儲日志條目。

  • kv數據存儲:kv數據的存儲引擎,v3支持不同的后端存儲,當前采用boltdb。通過boltdb支持事務操作。

相對于v2,v3的主要改動點為:

  1. 使用grpc進行peer之間和與客戶端之間通信;

  2. v2的store是在內存中的一棵樹,v3采用抽象了一個kvstore,支持不同的后端存儲數據庫。增強了事務能力。

去除單元測試代碼,etcd v2的代碼行數約40k,v3的代碼行數約70k。

2.3 典型內部處理流程

我們將上面架構圖的各個部分進行編號,以便下文的處理流程介紹中,對應找到每個流程處理的組件位置。

2.3.1 消息入口

一個etcd節點運行以后,有3個通道接收外界消息,以kv數據的增刪改查請求處理為例,介紹這3個通道的工作機制。 1. client的http調用:會通過注冊到http模塊的keysHandler的ServeHTTP方法處理。解析好的消息調用EtcdServer的Do()方法處理。(圖中2) 2. client的grpc調用:啟動時會向grpc server注冊quotaKVServer對象,quotaKVServer是以組合的方式增強了kvServer這個數據結構。grpc消息解析完以后會調用kvServer的Range、Put、DeleteRange、Txn、Compact等方法。kvServer中包含有一個RaftKV的接口,由EtcdServer這個結構實現。所以最后就是調用到EtcdServer的Range、Put、DeleteRange、Txn、Compact等方法。(圖中1) 3. 節點之間的grpc消息:每個EtcdServer中包含有Transport結構,Transport中會有一個peers的map,每個peer封裝了節點到其他某個節點的通信方式。包括streamReader、streamWriter等,用于消息的發送和接收。streamReader中有recvc和propc隊列,streamReader處理完接收到的消息會將消息推到這連個隊列中。由peer去處理,peer調用raftNode的Process方法處理消息。(圖中3、4)

2.3.2 EtcdServer消息處理

對于客戶端消息,調用到EtcdServer處理時,一般都是先注冊一個等待隊列,調用node的Propose方法,然后用等待隊列阻塞等待消息處理完成。Propose方法會往propc隊列中推送一條MsgProp消息。 對于節點間的消息,raftNode的Process是直接調用node的step方法,將消息推送到node的recvc或者propc隊列中。 可以看到,外界所有消息這時候都到了node結構中的recvc隊列或者propc隊列中。(圖中5)

2.3.3 node處理消息

node啟動時會啟動一個協程,處理node的各個隊列中的消息,當然也包括recvc和propc隊列。從propc和recvc隊列中拿到消息,會調用raft對象的Step方法,raft對象封裝了raft的協議數據和操作,其對外的Step方法是真正raft協議狀態機的步進方法。當接收到消息以后,根據協議類型、Term字段做相應的狀態改變處理,或者對選舉請求做相應處理。對于一般的kv增刪改查數據請求消息,會調用內部的step方法。內部的step方法是一個可動態改變的方法,將隨狀態機的狀態變化而變化。當狀態機處于leader狀態時,該方法就是stepLeader;當狀態機處于follower狀態時,該方法就是stepFollower;當狀態機處于Candidate狀態時,該方法就是stepCandidate。leader狀態會直接處理MsgProp消息。將消息中的日志條目存入本地緩存。follower則會直接將MsgProp消息轉發給leader,轉發的過程是將先將消息推送到raft的msgs數組中。 node處理完消息以后,要么生成了緩存中的日志條目,要么生成了將要發送出去的消息。緩存中的日志條目需要進一步處理(比如同步和持久化),而消息需要進一步處理發送出去。處理過程還是在node的這個協程中,在循環開始會調用newReady,將需要進一步處理的日志和需要發送出去的消息,以及狀態改變信息,都封裝在一個Ready消息中。Ready消息會推行到readyc隊列中。(圖中5)

2.3.4 raftNode的處理

raftNode的start()方法另外啟動了一個協程,處理readyc隊列(圖中6)。取出需要發送的message,調用transport的Send方法并將其發送出去(圖中4)。調用storage的Save方法持久化存儲日志條目或者快照(圖中9、10),更新kv緩存。 另外需要將已經同步好的日志應用到狀態機中,讓狀態機更新狀態和kv存儲,通知等待請求完成的客戶端。因此需要將已經確定同步好的日志、快照等信息封裝在一個apply消息中推送到applyc隊列。

2.3.5 EtcdServer的apply處理

EtcdServer會處理這個applyc隊列,會將snapshot和entries都apply到kv存儲中去(圖中8)。最后調用applyWait的Trigger,喚醒客戶端請求的等待線程,返回客戶端的請求。

3、重要的數據結構

3.1 EtcdServer

type EtcdServer struct {

// 當前正在發送的snapshot數量

inflightSnapshots int64 

//已經apply的日志index

appliedIndex      uint64 

//已經提交的日志index,也就是leader確認多數成員已經同步了的日志index

committedIndex    uint64 

//已經持久化到kvstore的index

consistIndex consistentIndex 

//配置項

Cfg          *ServerConfig

//啟動成功并注冊了自己到cluster,關閉這個通道。

readych chan struct{}

//重要的數據結果,存儲了raft的狀態機信息。

r       raftNode

//滿多少條日志需要進行snapshot

snapCount uint64

//為了同步調用情況下讓調用者阻塞等待調用結果的。

w wait.Wait

//下面3個結果都是為了實現linearizable 讀使用的

readMu sync.RWMutex

readwaitc chan struct{}

readNotifier *notifier

//停止通道

stop chan struct{}

//停止時關閉這個通道

stopping chan struct{}

//etcd的start函數中的循環退出,會關閉這個通道

done chan struct{}

//錯誤通道,用以傳入不可恢復的錯誤,關閉raft狀態機。

errorc     chan error

//etcd實例id

id         types.ID

//etcd實例屬性

attributes membership.Attributes

//集群信息

cluster *membership.RaftCluster

//v2的kv存儲

store       store.Store

//用以snapshot

snapshotter *snap.Snapshotter

//v2的applier,用于將commited index apply到raft狀態機

applyV2 ApplierV2

//v3的applier,用于將commited index apply到raft狀態機

applyV3 applierV3

//剝去了鑒權和配額功能的applyV3

applyV3Base applierV3

//apply的等待隊列,等待某個index的日志apply完成

applyWait   wait.WaitTime

//v3用的kv存儲

kv         mvcc.ConsistentWatchableKV

//v3用,作用是實現過期時間

lessor     lease.Lessor

//守護后端存儲的鎖,改變后端存儲和獲取后端存儲是使用

bemu       sync.Mutex

//后端存儲

be         backend.Backend

//存儲鑒權數據

authStore  auth.AuthStore

//存儲告警數據

alarmStore *alarm.AlarmStore

//當前節點狀態

stats  *stats.ServerStats

//leader狀態

lstats *stats.LeaderStats

//v2用,實現ttl數據過期的

SyncTicker *time.Ticker

//壓縮數據的周期任務

compactor *compactor.Periodic

//用于發送遠程請求

peerRt   http.RoundTripper

//用于生成請求id

reqIDGen *idutil.Generator

// forceVersionC is used to force the version monitor loop

// to detect the cluster version immediately.

forceVersionC chan struct{}

// wgMu blocks concurrent waitgroup mutation while server stopping

wgMu sync.RWMutex

// wg is used to wait for the go routines that depends on the server state

// to exit when stopping the server.

wg sync.WaitGroup

// ctx is used for etcd-initiated requests that may need to be canceled

// on etcd server shutdown.

ctx    context.Context

cancel context.CancelFunc

leadTimeMu      sync.RWMutex

leadElectedTime time.Time

}

3.2 raftNode

raftNode是Raft節點,維護Raft狀態機的步進和狀態遷移。

type raftNode struct {

// Cache of the latest raft index and raft term the server has seen.

// These three unit64 fields must be the first elements to keep 64-bit

// alignment for atomic access to the fields.

//狀態機當前狀態,index代表當前已經apply到狀態機的日志index,term是最新日志條目的term,lead是當前的leader id

index uint64

term  uint64

lead  uint64

//包含了node、storage等重要數據結構

raftNodeConfig

// a chan to send/receive snapshot

msgSnapC chan raftpb.Message

// a chan to send out apply

applyc chan apply

// a chan to send out readState

readStateC chan raft.ReadState

// utility

ticker *time.Ticker

// contention detectors for raft heartbeat message

td *contention.TimeoutDetector

stopped chan struct{}

done    chan struct{}

}

3.3 node

type node struct {

//Propose隊列,調用raftNode的Propose即把Propose消息塞到這個隊列里

propc      chan pb.Message

//Message隊列,除Propose消息以外其他消息塞到這個隊列里

recvc      chan pb.Message

//集群配置信息隊列,當集群節點改變時,需要將修改信息塞到這個隊列里

confc      chan pb.ConfChange

//外部通過這個隊列獲取修改后集群配置信息

confstatec chan pb.ConfState

//已經準備好apply的信息隊列

readyc     chan Ready

//每次apply好了以后往這個隊列里塞個空對象。通知可以繼續準備Ready消息。

advancec   chan struct{}

//tick信息隊列,用于調用心跳

tickc      chan struct{}

done       chan struct{}

stop       chan struct{}

status     chan chan Status

logger Logger

}

4、小結
本文簡要介紹了raft協議和etcd的框架,介紹了etcd內部的和消息流的處理。后續將分心跳和選舉、數據同步、數據持久化等不同專題詳細講述etcd的內部機制。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高要市| 达拉特旗| 运城市| 罗山县| 高淳县| 调兵山市| 耒阳市| 韶山市| 芜湖市| 新巴尔虎右旗| 汪清县| 庆阳市| 澄城县| 稻城县| 北票市| 从化市| 军事| 商城县| 喀什市| 镇赉县| 祁门县| 资阳市| 藁城市| 临清市| 南丰县| 三门县| 周宁县| 东乌珠穆沁旗| 普兰县| 家居| 泸溪县| 连江县| 通化市| 内丘县| 龙州县| 广德县| 古交市| 资中县| 张家口市| 台东县| 石渠县|