python 微服务 etcd_架构之微服务(etcd)
1. ETCD是什么
ETCD是用于共享配置和服務(wù)發(fā)現(xiàn)的分布式,一致性的KV存儲系統(tǒng)。該項目目前最新穩(wěn)定版本為2.3.0. 具體信息請參考[項目首頁]和[Github]。ETCD是CoreOS公司發(fā)起的一個開源項目,授權(quán)協(xié)議為Apache。
提供配置共享和服務(wù)發(fā)現(xiàn)的系統(tǒng)比較多,其中最為大家熟知的是[Zookeeper](后文簡稱ZK),而ETCD可以算得上是后起之秀了。在項目實現(xiàn),一致性協(xié)議易理解性,運維,安全等多個維度上,ETCD相比Zookeeper都占據(jù)優(yōu)勢。
2. ETCD vs ZK
本文選取ZK作為典型代表與ETCD進行比較,而不考慮[Consul]項目作為比較對象,原因為Consul的可靠性和穩(wěn)定性還需要時間來驗證(項目發(fā)起方自身服務(wù)并未使用Consul, 自己都不用)。
一致性協(xié)議: ETCD使用[Raft]協(xié)議, ZK使用ZAB(類PAXOS協(xié)議),前者容易理解,方便工程實現(xiàn);
運維方面:ETCD方便運維,ZK難以運維;
項目活躍度:ETCD社區(qū)與開發(fā)活躍,ZK已經(jīng)快死了;
API:ETCD提供HTTP+JSON, gRPC接口,跨平臺跨語言,ZK需要使用其客戶端;
訪問安全方面:ETCD支持HTTPS訪問,ZK在這方面缺失;
3. ETCD的使用場景
和ZK類似,ETCD有很多使用場景,包括:
配置管理
服務(wù)注冊于發(fā)現(xiàn)
選主
應(yīng)用調(diào)度
分布式隊列
分布式鎖
4. ETCD讀寫性能
按照官網(wǎng)給出的[Benchmark], 在2CPU,1.8G內(nèi)存,SSD磁盤這樣的配置下,單節(jié)點的寫性能可以達到16K QPS, 而先寫后讀也能達到12K QPS。這個性能還是相當可觀的。
5. ETCD工作原理
ETCD使用Raft協(xié)議來維護集群內(nèi)各個節(jié)點狀態(tài)的一致性。簡單說,ETCD集群是一個分布式系統(tǒng),由多個節(jié)點相互通信構(gòu)成整體對外服務(wù),每個節(jié)點都存儲了完整的數(shù)據(jù),并且通過Raft協(xié)議保證每個節(jié)點維護的數(shù)據(jù)是一致的。
如圖所示,每個ETCD節(jié)點都維護了一個狀態(tài)機,并且,任意時刻至多存在一個有效的主節(jié)點。主節(jié)點處理所有來自客戶端寫操作,通過Raft協(xié)議保證寫操作對狀態(tài)機的改動會可靠的同步到其他節(jié)點。
ETCD工作原理核心部分在于Raft協(xié)議。本節(jié)接下來將簡要介紹Raft協(xié)議,具體細節(jié)請參考其[論文]。
Raft協(xié)議正如論文所述,確實方便理解。主要分為三個部分:選主,日志復制,安全性。
5.1 選主
Raft協(xié)議是用于維護一組服務(wù)節(jié)點數(shù)據(jù)一致性的協(xié)議。這一組服務(wù)節(jié)點構(gòu)成一個集群,并且有一個主節(jié)點來對外提供服務(wù)。當集群初始化,或者主節(jié)點掛掉后,面臨一個選主問題。集群中每個節(jié)點,任意時刻處于Leader, Follower, Candidate這三個角色之一。選舉特點如下:
當集群初始化時候,每個節(jié)點都是Follower角色;
集群中存在至多1個有效的主節(jié)點,通過心跳與其他節(jié)點同步數(shù)據(jù);
當Follower在一定時間內(nèi)沒有收到來自主節(jié)點的心跳,會將自己角色改變?yōu)镃andidate,并發(fā)起一次選主投票;當收到包括自己在內(nèi)超過半數(shù)節(jié)點贊成后,選舉成功;當收到票數(shù)不足半數(shù)選舉失敗,或者選舉超時。若本輪未選出主節(jié)點,將進行下一輪選舉(出現(xiàn)這種情況,是由于多個節(jié)點同時選舉,所有節(jié)點均為獲得過半選票)。
Candidate節(jié)點收到來自主節(jié)點的信息后,會立即終止選舉過程,進入Follower角色。
為了避免陷入選主失敗循環(huán),每個節(jié)點未收到心跳發(fā)起選舉的時間是一定范圍內(nèi)的隨機值,這樣能夠避免2個節(jié)點同時發(fā)起選主。
5.2 日志復制
所謂日志復制,是指主節(jié)點將每次操作形成日志條目,并持久化到本地磁盤,然后通過網(wǎng)絡(luò)IO發(fā)送給其他節(jié)點。其他節(jié)點根據(jù)日志的邏輯時鐘(TERM)和日志編號(INDEX)來判斷是否將該日志記錄持久化到本地。當主節(jié)點收到包括自己在內(nèi)超過半數(shù)節(jié)點成功返回,那么認為該日志是可提交的(committed),并將日志輸入到狀態(tài)機,將結(jié)果返回給客戶端。
這里需要注意的是,每次選主都會形成一個唯一的TERM編號,相當于邏輯時鐘。每一條日志都有全局唯一的編號。
主節(jié)點通過網(wǎng)絡(luò)IO向其他節(jié)點追加日志。若某節(jié)點收到日志追加的消息,首先判斷該日志的TERM是否過期,以及該日志條目的INDEX是否比當前以及提交的日志的INDEX跟早。若已過期,或者比提交的日志更早,那么就拒絕追加,并返回該節(jié)點當前的已提交的日志的編號。否則,將日志追加,并返回成功。
當主節(jié)點收到其他節(jié)點關(guān)于日志追加的回復后,若發(fā)現(xiàn)有拒絕,則根據(jù)該節(jié)點返回的已提交日志編號,發(fā)生其編號下一條日志。
主節(jié)點像其他節(jié)點同步日志,還作了擁塞控制。具體地說,主節(jié)點發(fā)現(xiàn)日志復制的目標節(jié)點拒絕了某次日志追加消息,將進入日志探測階段,一條一條發(fā)送日志,直到目標節(jié)點接受日志,然后進入快速復制階段,可進行批量日志追加。
按照日志復制的邏輯,我們可以看到,集群中慢節(jié)點不影響整個集群的性能。另外一個特點是,數(shù)據(jù)只從主節(jié)點復制到Follower節(jié)點,這樣大大簡化了邏輯流程。
5.3 安全性
截止此刻,選主以及日志復制并不能保證節(jié)點間數(shù)據(jù)一致。試想,當一個某個節(jié)點掛掉了,一段時間后再次重啟,并當選為主節(jié)點。而在其掛掉這段時間內(nèi),集群若有超過半數(shù)節(jié)點存活,集群會正常工作,那么會有日志提交。這些提交的日志無法傳遞給掛掉的節(jié)點。當掛掉的節(jié)點再次當選主節(jié)點,它將缺失部分已提交的日志。在這樣場景下,按Raft協(xié)議,它將自己日志復制給其他節(jié)點,會將集群已經(jīng)提交的日志給覆蓋掉。
這顯然是不可接受的。
其他協(xié)議解決這個問題的辦法是,新當選的主節(jié)點會詢問其他節(jié)點,和自己數(shù)據(jù)對比,確定出集群已提交數(shù)據(jù),然后將缺失的數(shù)據(jù)同步過來。這個方案有明顯缺陷,增加了集群恢復服務(wù)的時間(集群在選舉階段不可服務(wù)),并且增加了協(xié)議的復雜度。
Raft解決的辦法是,在選主邏輯中,對能夠成為主的節(jié)點加以限制,確保選出的節(jié)點已定包含了集群已經(jīng)提交的所有日志。如果新選出的主節(jié)點已經(jīng)包含了集群所有提交的日志,那就不需要從和其他節(jié)點比對數(shù)據(jù)了。簡化了流程,縮短了集群恢復服務(wù)的時間。
這里存在一個問題,加以這樣限制之后,還能否選出主呢?答案是:只要仍然有超過半數(shù)節(jié)點存活,這樣的主一定能夠選出。因為已經(jīng)提交的日志必然被集群中超過半數(shù)節(jié)點持久化,顯然前一個主節(jié)點提交的最后一條日志也被集群中大部分節(jié)點持久化。當主節(jié)點掛掉后,集群中仍有大部分節(jié)點存活,那這存活的節(jié)點中一定存在一個節(jié)點包含了已經(jīng)提交的日志了。
至此,關(guān)于Raft協(xié)議的簡介就全部結(jié)束了。
6. ETCD使用案例
據(jù)公開資料顯示,至少有CoreOS, Google Kubernetes, Cloud Foundry, 以及在Github上超過500個項目在使用ETCD。
7. ETCD接口
ETCD提供HTTP協(xié)議,在最新版本中支持Google gRPC方式訪問。具體支持接口情況如下:
ETCD是一個高可靠的KV存儲系統(tǒng),支持PUT/GET/DELETE接口;
為了支持服務(wù)注冊與發(fā)現(xiàn),支持WATCH接口(通過http long poll實現(xiàn));
支持KEY持有TTL屬性;
CAS(compare and swap)操作;
支持多key的事務(wù)操作;
支持目錄操作
總結(jié)
以上是生活随笔為你收集整理的python 微服务 etcd_架构之微服务(etcd)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pymongo查询列表元素_散列表:如何
- 下一篇: msdn集合不存在 请重新安装msdn_