分散式系統通常都依賴一個仲裁系統協同工作,一般這樣的系統透過仲裁來保證訊息的準確傳達,以避免腦裂。這類系統透過犧牲通用性換來了充分的設計餘地,這種做法顯然已經被不斷擴散的各種具體實現所例證。這樣的系統有很多,例如:chubby,ZooKeeper,etcd和consul等。儘管這些系統的理念和協議不同,但提供的都是類似的基於key-value的分散式仲裁。作為將etcd打造成分散式系統最受矚目的基礎組件計劃的一部分,etcd團隊開發了一款全新的代理,zetcd,無需變動就可以讓etcd集群消費ZooKeeper的服務請求。
ZooKeeper是第一個開源實作的仲裁軟體,這促使它成為眾多分散式系統偏好的後端。理論上這些系統應該可以跟etcd相容,但由於歷史原因,事實並非如此;etcd叢集無法取代ZooKeeper,其資料模型和客戶端協定跟ZooKeeper應用不相容;反之亦然。倘若該系統已經投產,幾乎沒什麼動力可以推動它接入新的後端,引入新的複雜度。
幸運的是,etcd v3 API正準備透過一個標準代理zetcd實現對ZooKeeper資料模型的模擬支持,zetcd是一個由etcd團隊開發的全新開源項目,今天發布了zetcd第一個beta版本,v0. 0.1,目標是在生產系統中管理和部署zetcd系統。
zetcd 代理部署在etcd叢集前面,服務於一個模擬的ZooKeeper客戶端端口,使得ZooKeeper應用可以在上層原生調用etcd。整體來說,zetcd接受ZooKeeper的客戶請求,轉換成etcd的資料模型和API,將請求轉送到etcd,然後將回傳訊息以客戶端可以理解的方式轉回。 zetcd的性能跟ZooKeeper不相上下,並且簡化了ZooKeeper集群與etcd之間的管理和操作複雜性。本文將揭示如何使用zetcd,zetcd工作原理以及效能基準。
#zetcd運作所需的是一個go編譯器,從網路上取得的原始碼,以及一個可以執行etcd的系統。以下範例展示了從取得zetcd原始碼,一直到如何在zetcd上執行ZooKeeper指令。由於都是基於開發分支所建構的etcd和zetcd,所以不建議在生產環境這樣做,這只是一個講解如何使用的簡單例子。
首先,取得etcd和zetcd原始碼,並編譯成二進位程式碼:
go get github.com/coreos/etcd/cmd/etcd go get github.com/coreos/zetcd/cmd/zetcd
其次,執行etcd,將zetcd連接到etcd客戶服務端:
#etcd uses localhost:2379 by default etcd & zetcd -zkaddr localhost:2181 -endpoints localhost:2379 &
透過增加訂閱和建立一個key來試用zetd:
go install github.com/coreos/zetcd/cmd/zkctl zkctl watch / & zkctl create /abc "foo"
從概念上講,上述例子即完成在一個單一的etcd實例上增加一層zetcd。
深入來講,zetcd會將ZooKeeper的資料模型翻譯成適配etcd API。對於key查找,zetcd將ZooKeeper層級式目錄轉換成etcd扁平的二分鍵值空間(flat binary keyspace)。為了管理元數據,當寫入etcd後端時,zetcd利用記憶體層級的事務將資訊安全、原子地更新為ZooKeeper znode資訊。
ZooKeeper以目錄方式列出key(getChildren),而etcd則是透過間隔(Range)方式。下圖講解了zetcd如何對etcd下的key進行編碼從而有效地支援以目錄形式列出。所有在etcd中的zetcd key都有一個包含全目錄名的前綴(例如:”/”和“/abc”分別代表深度為0 和1)。要列出一個目錄時,zetcd發出一個帶有前綴的range請求(例如[“/zk/key/002/abc/”, “/zk/key/002/abc0”)來列出滿足目錄深度和路徑的所有/abc/下的key。深度限制只針對目錄本身;如果zetcd只使用路徑而不使用深度,那麼etcd將傳回這個目錄下的所有key,zetcd則會丟棄該結果,反之則只回傳本目錄下的key。
#每個ZooKeeper key在ZNode裡都帶有一些元數據,即key的調整,版本和權限等。儘管etcd也有每個key的元數據,卻比ZNode要簡單很多,例如因為沒有目錄也就沒有子版本,因為etcd使用的是基於角色認證的機制因此也就沒有ACL,因為實際的時鐘超出範疇所以沒有時間戳。這些額外的元資料會被映射為對應的key,用來描述一個完整的ZNode。修改元資料時,zetcd利用記憶體層級的軟事務來自動更新key的子集,確保ZNodes不需要昂貴的加鎖機制就可以保持一致。
此外,zetcd可以和一台授權的ZooKeeper伺服器做動態校驗。為了做比較,zetcd可以同時連到etcd和外部ZooKeeper伺服器。當客戶端發起請求給該模式下的zetcd時,請求會被同時轉送到zetcd和ZooKeeper服務端。如果兩個伺服器回應的資料不一致,zetcd會給此回應標識一個警告。
由于数据的转换以及额外的网络开销,也许很容易觉得这样的模拟不切实际。尽管对于ZooKeeper或者etcd集群来说,zetcd有额外的花销,但是它仍然有一个优势,即某些etcd应用安装完毕后仍然需要ZooKeeper来协调的场景。例如,早期用户报告称在zetcd里通过etcd的TLS加密流量比一个类似的经典ZooKeeper配置更简单。在这些场景中,支持同一种ZooKeeper协议所带来的简单可靠性比性能更重要一些。 跟etcd性能工具的接口及报告形式类似,zetcd命令行工具zkboom可以用来判断一个zetcd的性能基准是否满足要求。其它ZooKeeper性能工具应该也可以用在zetcd;zkboom为用户提供了便利,我们不妨试试用它来做下创建key的测试:
go get github.com/coreos/zetcd/cmd/zkboom zkboom --conns=50 --total=10000 --endpoints=localhost:2181 create
zetcd应当可以为小负载提供充分的性能保障。一个简单两节点配置的延迟基准表明zetcd是可以承受大量请求的。具体配置为两台Linux服务器通过一个千兆交换机互联,其中一台设备在RAID磁盘配置上运行代理和和服务端,另外一台设备用于产生客户请求。zkbook通过创建一个空的key存储,然后从中读取128Kbytes的键值对来进行测量。用户请求被限制在每秒2500个请求,然后逐渐增加并发客户端数量。ZooKeeper 3.4.10和etcd结果对比见下图。
下图揭示了zetcd客户端并发数与创建key的平均延迟之间的关系。由于etcd在延迟上比ZooKeeper要有5-35ms的优势,zetcd有足够余地处理由于额外负载和网络跳转造成的延迟。比起ZooKeeper,zetcd代理始终还是存在20ms左右的差距,但是从处理2500请求的吞吐量数据来看,并没有出现队列堵塞。一种对zetcd写比较慢的解释是,与读不一样,由于数据模型上存在差异,所以在每个ZooKeeper key写时需要写多个key。
下图揭示了zetcd客户端并发数与key取值的平均延迟之间的关系。由于ZooKeeper的取值延迟比etcd要快那么2ms左右,想要zetcd提供数据的速度快过ZooKeeper的话恐怕还得依赖于etcd本身性能的进一步提升。然而,尽管zetcd需要从etcd请求额外的key来模拟Zookeeper znode的元数据,zetcd的命中延迟在等待etcd key提取数据方面只增加了大概1.5ms。zetcd在key的数据提取操作方面仅需一次往返,因为读请求会被打包到一个etcd事务中。
zetcd承诺上述性能基准测试的结果是合理的,在可接受的延迟情况下,可以轻松支撑每秒上千个操作。以上模拟对于Mesos,Kafka和Drill替代ZooKeeper提供了一个替代选择。但是对于zetcd本身来说性能方面仍有不少的提升空间。与此同时测试更多的ZooKeeper应用也会进一步推动zetcd成为ZooKeeper服务器的替代品。
zetcd从去年十月开始在开源社区发行,最近刚发布第一个版本:zetcd v0.0.1。尽管是第一个beta发行版,但是已经为未来生产系统提供稳定管理和部署。如果跟etcd配合起来使用,运行zetcd的系统将会一套自驱动的“ZooKeeper”集群,它可以自动后台升级,备份和TLS管理。
etcd为分布式系统提供可靠、高效的配置管理服务,在Docker、Kubernetes、Mesos等平台中扮演了越来越重要的角色。作为2013年开始的项目,它还很年轻,官方文档中缺乏实现上全面、系统的介绍,本课程深入浅出地介绍了etcd的实现,并为运维和二次开发提供了系统的指导和建议。
以上是zetcd解決如何讓應用程式解除對ZooKeeper的依賴的詳細內容。更多資訊請關注PHP中文網其他相關文章!