【ZStack】2.ZStack的伸缩性秘密武器:无状态服务

每个ZStack服务都是无状态的,让服务高可用以及横向拓展(scale out)可以很简单,只需要启动剩余的服务实例,然后进行负载均衡即可。此外,ZStack将所有的服务打包到名为管理节点(management node)的单个进程,它让部署和管理变得超级简单。

动机

ZStack的伸缩性秘密武器——异步架构(ZStack's Scalability Secrets Part 1: Asynchronous Architecture) 一文中, 我们已经详细解释了异步架构,它让单个ZStack管理节点能胜任大多数的云端工作负载。然而,当用户希望建立高可用的生产环境,或者处理超级大的并发工作负载的时候,一个管理节点是不够的。解决方案是,构建一个分布式的系统,这样工作负载可以延展到每一个单一管理节点。这种增加新节点来拓展整个系统的容量的方式称为 横向拓展(scale out).

问题

设计一个分布式的系统并不容易。一个分布式的系统,特别是一个有状态的系统,必须处理一致性,可用性,以及分区容忍性(请查看 CAP理论(CAP theorem)),所有这些都很复杂。相反,一个无状态的分布式系统,在某种程度上摆脱了这种复杂性。首先,因为在节点之间无需状态共享,系统自然保持了一致性;其次,由于节点之间是类似的,当系统遇到一个分区问题通常也是OK的。鉴于此,一个分布式的系统,通常更倾向于保持无状态而不是有状态。但是,设计一个无状态的分布式系统也是很困难的,同时,常常比设计有状态的分布式系统更加困难。提升了消息总线(message bus)和数据库优势的ZStack,构建了一个包含了无状态服务的无状态分布式系统。

由于无状态服务是保证整个系统无状态的根基,在讨论它是什么之前,让我们先了解下什么是“状态”。在ZStack里面,资源,如主机,虚拟机,镜像,以及用户,都是由单个服务管理的;当系统中存在多余一个服务实例的时候,资源会被划分为不同的实例。例如,假如有10,000个虚拟机和两个虚拟机服务实例,理想的情况下,每个实例将会管理5000个虚拟机:

由于存在两个服务实例,在向虚拟机发送请求之前,请求者必须知道哪一个实例正在管理虚拟机;否则,它将无法知道将请求发往何处。像 ”哪个服务实例正在管理什么资源“ 的认知,正是我们正在谈论的状态。如果服务是有状态的,状态也就显现在服务之中。请求者需要在某个地方咨询这些状态。当服务实例的数目发生变化的时候,服务需要交换状态,例如,当一个新的服务实例加入,或者当前的服务实例脱离的时候。

状态交换是让人担忧的,它很容易导致错误,常常会限制系统的可拓展性。为了让系统更可靠,同时更易于横向拓展,理想的方式是,通过彼此分隔状态来让服务保持无状态(查看 服务无状态原则(Service Statelessness Principle)。 有了无状态的服务,请求者不再需要询问何处发送请求;当新的服务实例加入,或者旧的服务实例脱离的时候,服务也不再需要交换状态。

注意:在接下来的内容中,为了简单起见,术语“服务”和“服务实例”交换着使用。

服务和管理节点

服务,通过中央消息总线(central message bus)--RabbitMQ,来彼此通讯,它们是ZStack中的“第一等公民”。

不像通常的微服务架构,其每个服务都在单独的进程或单独的机器上运行,ZStack将所有的服务打包到一个名为管理节点的单一进程。对于这个号称 进程中的微服务(in-process microservices)架构,我们有充分的理由,你可以参看进程中的微服务架构(The In-Process Microservices Architecture)。

一个管理节点是一个完整功能的ZStack软件。由于包含了无状态服务,管理节点没有共享状态,但是有心跳记录,以及一致性哈希算法环(consistent hashing ring)--接下来我们将详细介绍。 心跳用来监控管理节点的“健康”(译者注:即此管理节点是否存活,是否正常运转),只要一个管理节点在给定的间隔内停止更新心跳,其它的管理节点将会驱除它,同时开始接管它所管理的资源。

无状态服务

实现无状态服务的核心技术,特别是对于ZStack的业务逻辑,就是一致性哈希算法(consistent hashing algorithm)。在启动的时候,每个管理节点都会被分配一个 版本4UUID(version 4 UUID)(管理节点UUID),它会和服务名一起,在消息总线上注册一个服务队列。例如,管理节点可能注册如下所示的服务队列:

zstack.message.ansible.3694776ab31a45709259254a018913ca
zstack.message.api.portal       
zstack.message.applianceVm.3694776ab31a45709259254a018913ca     
zstack.message.cloudbus.3694776ab31a45709259254a018913ca        
zstack.message.cluster.3694776ab31a45709259254a018913ca
zstack.message.configuration.3694776ab31a45709259254a018913ca   
zstack.message.console.3694776ab31a45709259254a018913ca
zstack.message.eip.3694776ab31a45709259254a018913ca     
zstack.message.globalConfig.3694776ab31a45709259254a018913ca    
zstack.message.host.3694776ab31a45709259254a018913ca    
zstack.message.host.allocator.3694776ab31a45709259254a018913ca  
zstack.message.identity.3694776ab31a45709259254a018913ca        
zstack.message.image.3694776ab31a45709259254a018913ca   
zstack.message.managementNode.3694776ab31a45709259254a018913ca  
zstack.message.network.l2.3694776ab31a45709259254a018913ca      
zstack.message.network.l2.vlan.3694776ab31a45709259254a018913ca
zstack.message.network.l3.3694776ab31a45709259254a018913ca      
zstack.message.network.service.3694776ab31a45709259254a018913ca
zstack.message.portForwarding.3694776ab31a45709259254a018913ca  
zstack.message.query.3694776ab31a45709259254a018913ca   
zstack.message.securityGroup.3694776ab31a45709259254a018913ca   
zstack.message.snapshot.volume.3694776ab31a45709259254a018913ca
zstack.message.storage.backup.3694776ab31a45709259254a018913ca

说明:你应该注意到,所有队列都以同样的UUID结尾,那是管理节点的UUID。

资源,如主机,容量,虚拟机,也是通过UUID来标识的。消息,常常和资源相关联,是在服务间传递的。在发送消息之前,发送者必须选择基于资源的UUID的接收者服务,这时,一致性哈希算法就开始登场了。

一致性哈希(Consistent hashing)是一种特别的哈希,当哈希表调整大小的时候,就会用到一致性哈希,其中只有一部分键(key)需要重新映射。关于一致性哈希的更多内容,更详细的请参阅 这里。在ZStack之中,管理节点由一致性哈希环组成,如下所示:

每个管理节点都维护一份一致性哈希环的拷贝,这个环包含了系统中所有管理节点的UUID。当管理节点加入或者脱离的时候,生命周期事件(lifecycle event)就会通过消息总线广播到其它节点,这样使得这些节点扩展或者收缩环,以呈现当前系统的状态。当发送消息的时候,发送者服务将使用资源的UUID,通过哈希的方式得出目标管理节点的UUID。例如,发送VM的UUID为932763162d054c04adaab6ab498c9139的StartVmInstanceMsg,伪代码如下:

msg = new StartVmInstanceMsg(); destinationManagementNodeUUID = consistent_hashing_algorithm("932763162d054c04adaab6ab498c9139"); msg.setServiceId("vmInstance." + destinationManagementNodeUUID); cloudBus.send(msg)

如果有一个稳定的环,那么包含同样资源UUID的消息就总是会路由到某个管理节点上同样的服务,这就是ZStack无锁架构的基础(参阅 ZStack的伸缩性秘密(第三部分):无锁架构(Stack's Scalability Secrets Part 3: Lock-free Architecture)。

6.png

当一致性哈希环收缩或释放的时候,由于一致性哈希的特性,只有少数节点受到轻微影响。

由于一致性哈希环,发送者无需知道哪一个服务实例即将处理消息;取而代之的是,这将会被处理掉。服务无需维护和交换,关于它们正在管理什么资源的信息;它们所需要做的就是,处理即将到来的消息,因为环能够保证消息找到正确的服务实例。这就是服务如何变得超级简单和保持无状态的。

除包含资源UUID的消息之外(如 StartVmInstanceMsg, DownloadImageMsg),也有一类无资源UUID的消息,通常是创建型的消息(如 CreateVolumeMsg)和非资源消息(如 AllocateHostMsg)--它们不会操控单独的资源。考虑到这些消息可以发送到任意管理节点的服务,它们可能被故意发送到本地的管理节点,由于发送者和接收者在同样的节点,当发送者发送消息的时候,接收者当然也是可达的。

对 API 消息(例如:APIStartVmInstanceMsg)来说,有一个特殊的处理,它们总是发送一个众所周知的服务 ID api.portal 。在消息总线上,一个全局的队列被叫做 zstack.message.api.portal ,它被所有的管理节点 API 服务所共享,消息服务 ID api.portal 将会自动对其中的一个API服务做负载均衡,这个服务还会路由转发消息到正确的目的地,并使用了一致性哈希环(consistent hashing ring)。通过这种做法,ZStack 隐藏了来自 API 客户端消息路由转发的细节,并简化了写一个ZStack API 客户端的工作。

msg = new APICreateVmInstanceMsg()
msg.setServiceId("api.portal")
cloudBus.send(msg)

摘要

在这篇文章中,我们证明了Zstack 构建伸缩性的分布式系统。因为管理节点共享的信息比较少,很容易建立一个大的集群,可能有几十个甚至几百个管理节点。然而实际上,在私有云方面,两个管理节点可以有很好的扩展性;在公共云方面,管理员能根据工作量创建一个管理节点。依靠异步架构和无状态的服务,Zstack能够处理大量的并发任务,现有的IaaS软件则不能处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容