文档章节

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

ZStack社区版
 ZStack社区版
发布于 08/03 13:37
字数 2559
阅读 5
收藏 0

每个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软件则不能处理。

© 著作权归作者所有

共有 人打赏支持
ZStack社区版
粉丝 16
博文 16
码字总数 36412
作品 1
闵行
产品经理
高性能web服务器的秘密核武器

最近kangle web服务器已经发布了新版2.3.1,其性能比老版本提升8倍之多,静态文件处理能力达apache的8-10倍。如此高的性能怎么来的 呢?kangle有哪些秘密武器呢?其实作为现代化的其它web服务...

keengo
2011/08/20
0
1
“九”答不可 | 量子通信如何做到安全保密?

导读 打个电话,会不会被窃听?通过网络传送一份保密文件,途中被他人窃取咋办……现代社会,信息安全面临的问题越来越多。 有没有一种不可破译的保密方式,能让传送的信息绝对安全可靠?量子...

雪花又一年
05/03
0
0
OSChina 开源周刊第34期 —— 看好 Swift 的十个理由

每周技术抢先看,总有你想要的! 开源资讯 开源中国安卓客户端 2.X 系列版本正式开源 为什么你说“就差一个码农了”,我们是拒绝的 2015年5月 TIOBE 编程语言排行榜单 微软全新的 Edge 浏览器...

OSC编辑部
2015/05/17
3.2K
1
SpamAssasssin的网友评论

SpamAssassin 这款反垃圾工具是许多商业产品背后的"秘密武器(secret sauce)",同时,很多的电子邮件服务商和垃圾过滤(工具)提供商都在使用它.专家经常将SpamAssassin看作是最好的开源反垃圾工具...

红薯
2009/12/11
274
1
反垃圾邮件系统--SpamAssassin

SpamAssassin 这款反垃圾工具是许多商业产品背后的"秘密武器(secret sauce)",同时,很多的电子邮件服务商和垃圾过滤(工具)提供商都在使用它.专家经常将SpamAssassin看作是最好的开源反垃圾工具...

匿名
2008/09/11
6.8K
0

没有更多内容

加载失败,请刷新页面

加载更多

redis 系列一 -- 简介及安装

1.简介 redis -- remote dictionary server 远程字典服务 使用 C 语言编写; 高性能的 key-value数据库; 内存数据库,支持数据持久化。 Redis 是一个开源(BSD许可)的,内存中的数据结构存...

imbiao
31分钟前
1
0
nginx log记录请求响应时间

有时为了方便分析接口性能等,需要记录请求的时长,通过修改nginx的日志格式可以做到,如 添加一个新的log_format log_format timed_combined '$remote_addr - $remote_user [$time_local] "...

swingcoder
54分钟前
2
0
Spring MVC之RequestMappingHandlerMapping匹配

对于RequestMappingHandlerMapping,使用Spring的同学基本都不会陌生,该类的作用有两个: 通过request查找对应的HandlerMethod,即当前request具体是由Controller中的哪个方法进行处理; 查...

爱宝贝丶
58分钟前
2
0
Java Web--增删改查之二界面后台java代码(转载参考)

/** *  *//** * @author Administrator * */package dao; import java.sql.*;public class DBConn {/** * 链接数据库 * @return */  ...

小橙子的曼曼
今天
2
0
Redis源码阅读笔记-对象及其类型和编码

总结之《Redis设计与实现》 对象 Redis中是使用对象来便是数据库中的键和值。 结构 // server.h...#define LRU_BITS 24...typedef struct redisObject { unsigned type:4; ...

Jian_Ming
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部