推出IaaS的第一种查询语言:ZStack查询语言(ZQL)
浏览:280 时间:2022-5-12

为了简化UI工作并为运维人员提供更灵活的资源查询模式,ZStack推出了第一种面向IaaS的查询语言—— ZStack查询语言(ZQL)。

背景

IaaS管理大量数据中心资源。如何灵活快速地查询这些资源对于操作和维护人员来说是一个难题。在过去的IaaS软件中,仅为单个资源的某些字段提供有限的API查询支持,例如,可以通过虚拟机的IP字段查询,这是不够的或不灵活的。在进行复杂查询时,运维人员通常不得不绕过IaaS软件直接查询其后端数据库。这要求操作和维护人员了解IaaS资源的内部关系,并带来数据库误操作的风险。

从ZStack发布的第一个版本的ZStack开始,我们致力于在API级别提供数据库级查询功能。 ZStack的每个资源都包含一个查询API,它可以传递资源自己的字段和相关的资源资源。该字段被查询。例如

QueryVmInstance名称〜=web-vm state=正在运行

此查询包含web-vm字符串的所有名称,即正在运行的VM。另一个例子

QueryVmInstance vmNics.eip.vip.ip='22 .22.22.22'

EIP是虚拟机的关联资源。 NIC绑定到虚拟机,EIP为22.22.22.22。

Query API功能强大:

用户可以通过count参数返回满足查询条件的资源数,类似于SQL的count();

指定fields参数返回的字段,类似于SQL uuid,name from;

通过sortBy,sortDirection参数指定排序的字段和方向,类似于SQL order by;

通过启动,限制参数来实现分页查询,类似于SQL限制和偏移。

除了易于使用之外,查询API也很容易定义。在程序员向ZStack添加新资源之后,他只需要在代码中定义以下类:

@AutoQuery(replyClass=APIQueryVmInstanceReply.class,inventoryClass=VmInstanceInventory.class)

公共类APIQueryVmInstanceMsg扩展了APIQueryMessage {

}

无需编写任何实现,相应的资源具有Query API。

ZStack内部包含一个查询API,它处理所有资源,将它们转换为相应的SQL语句,并在查询条件中包含相关资源条件时生成相应的Join子句。

基于查询API,ZStack 0.6版本包含超过400万个单项查询条件,组合查询条件数为400万个阶乘。操作和维护方便,UI设计复杂。但是查询API仍然存在一些缺陷:

查询条件只能是AND逻辑,不能执行OR逻辑,也不能用于实现条件之间复杂的逻辑组合

不支持类似于SQL的子查询子句

单个API只能查询一个资源,查询多个资源时需要调用多个API。

不支持与监控系统集成查询语言

随着ZStack UI场景变得越来越丰富,Query API的局限性使得UI方面的工作越来越多。许多方案需要多次调用Query API才能进行数据组合。例如,在监控Top 5页面(用于检测最大资源资源率为5资源的CPU,内存,磁盘,网络和其他资源)中,需要使用Query API查询虚拟机,物理机和其他资源信息返回,然后调用监控系统ZWatch API查询相应的监控数据。

查询API将在未来的ZStack版本中保留并维护,其后端实现已被原始查询服务中的ZQL替换。

ZStack Query Language

使用着名问题管理系统JIRA的开发人员知道JIRA在执行高级搜索时提供查询语言JQL(JIRA查询语言),并且可以为每个JIRA票证使用类似SQL的DSL(域特定语言)。有效查询的字段。ZQL类似于JQL,也是类似SQL的DSL。我们来看一个例子:

查询vminstance,其中name='webvm'或vmnics.ip='192.168.0.10'或(vmnics.eip='172.20.100.100'(cpuNum>=8或clusterUuid in('fe13b725c80e45709f0414c266a80239','73ca1ca7603d454f8fa7f3bb57097f80')))/p>

在这个简单的示例中,您可以看到许多熟悉的SQL元素,例如和/或条件,括号,>=/in运算符等。ZQL可以看作是SQL的一个子集,加上ZStack根据自己的需要执行的增强查询语言。其基本结构如下:

QUERY queryTarget(WHERE条件+)? restrictBy? returnWith?通过...分组?排序依据?限制?偏移?过滤? namedAs?

query关键词

ZQL语句通常以query关键字开头,该关键字表示要查询的资源或资源字段的集合。在前面的示例中,vminstance表示虚拟机。例如,host表示物理机器,zone表示区域。可以查询的所有资源都有自己的名称。如果你不想返回资源的所有字段,你只想获得资源的一个或多个字段,实现uuid的功能,名称来自...类似于SQL,你可以在之后指定字段名称资源名称和多个字段名称用逗号分隔,例如:

查询vminstance.uuid,name,cpuNum

此查询返回所有虚拟机的UUID,名称和CPU数。

除了查询关键字之外,查询还可以从count和sum关键字开始。前者返回满足查询条件的资源总数,后者可以对资源的某个字段求和。例如:

Vminstance cpuNum> 8

返回系统中具有8个以上内核的虚拟机总数。

按名称汇总vminstance.memorySize,其中cpuNum> 8

虚拟机名称按虚拟机名称分组,CPU核心数超过8个,其memorySize字段相加。如果系统中有两个名为webvm的10CPU8G虚拟机,则求和后返回的webvm虚拟机的总内存使用量为16G。转换为SQL是:

来自vminstance的sum(memorySize),其中cpuNum>按名称分组8

WHERE从句

ZQL的WHERE子句类似于SQL的WHERE子句。它支持和/或逻辑运算符和括号。条件比较支持=,!=,>,>=,<,<=,like,not like,is null,not null,in,not in,查询名称是字段的名称资源。与SQL的区别在于ZQL的查询条件可以是关联资源的字段,例如:

查询vminstance在哪里

vmNics.eip.vip.ip='22 .22.22.22’

请注意,在where子句之前不需要从xx子句编写类似SQL的,因为查询vminstance已经定义了要查询的资源

这里vip与eip相关联,eip与vmnic相关联,vmnic与vminstance相关联,然后我们可以指定vip的IP作为查询条件。这是ZQL的强大功能。对于多个相关的资源查询,不需要调用多个API来组合应用程序端的数据,也不需要像SQL那样编写复杂的连接子句,只需要像编程一样传递点(。)。通过引用另一个资源,ZQL的转换器将自动将跨资源引用转换为相应的SQL连接子句。

WHERE子句可以包含类似于SQL的子查询函数的子查询,例如:

在vmNics.l3NetworkUuid中查询vminstance(查询l3network.uuid

其中ipRanges.networkCidr='10 .1.0.0/24')

找出运行在第3层网络上的所有虚拟机,CIRD为10.1.0.0/24。

上面的例子也可以用更简单的方式实现:query vminstance其中vmNics.l3network.ipRanges.networkCidr='10 .1.0.0/24',只是为了演示子查询函数

GROUP BY、ORDER BY、LIMIT、OFFSET 子句

与SQL一样,ZQL支持GROUP BY,ORDER BY,LIMIT和OFFSET关键字进行分组,排序和分页。

GROUP BY:

通过对虚拟机的区域UUID和群集UUID进行分组来计算每个区域中每个群集中的虚拟机数量。

VYNstance group by zoneUuid,clusterUuid

ORDER BY:

查询所有虚拟机,并使用cpuNum字段按降序对它们进行排序。

1. ceryNum desc的查询vminstance顺序

LIMIT、OFFSET:

使用limit和offset来实现分页:

查询vminstance限制100偏移10

多资源查询

对于多个资源查询,您可以使用以分号分隔的多个查询查询,例如:

查询vminstance,其中name='my-vm';

查询主机cpuNum> 10;

查询区域;

可以在一次调用中返回三个资源的查询结果。由于返回的结果是地图的JSON结构,为了获得相应语句的查询结果,可以使用命名为关键字来命名查询,例如:

查询vminstance,其中name='my-vm',命名为'vm';

查询主机cpuNum> 10名为“主持人”;

查询区域名为“zone”;

在返回的JSON映射中,可以使用vm,host和zone作为键来获取相应语句的查询结果。

合并监控查询 (return with从句)

ZStack使用两种数据库:关系数据库存储元数据,时间序列数据库存储监控数据。由于不同的数据库查询方法不同,在ZQL之前,用户需要查询资源的监控数据,首先需要通过查询API获取资源的元数据,然后通过ZWatch查询API获取监控数据。例如,要查询名为webvm虚拟机的CPU使用情况监视数据,需要执行以下API:

QueryVmInstance fields=uuid name=webvm

GetMetricData namespace=ZStack/VM metricName=CPUUsedUtilization labels=VMUuid=QueryVmInstance返回的UUID offsetAheadOfCurrentTime=60

ZQL通过返回子句解决了这个问题。Return with是一种插件机制,允许子系统通过插件将自己的查询条件注入ZQL。 ZQL将首先执行关系数据库查询,查询满足条件资源的原始数据,然后查询资源的主键(主键)作为输入条件,调用实现return with子句的插件,最后调用插件的查询结果返回给ZQL的调用者。

查询虚拟机监控数据的上述要求可以通过ZQL语句实现:

查询vminstance.hostUuid,其中name='webvm'返回的uuid(zwatch {resultName='webvm-cpu',metricName='CPUAllUsedUtilization',offsetAheadOfCurrentTime=60})

回:

{

'结果': [

{

'库存': [

{

'hostUuid':'f8271f58468b4281a212a43e530b5535',

'uuid':'05781209d24341ac84fc055ae71820ac'

}

],

'returnWith': {

'webvm-cpu': [

{

'labels': {

'VMUuid':'05781209d24341ac84fc055ae71820ac'

},

'时间': 1533280402,

'价值': 0.8

},

{

'labels': {

'VMUuid':'05781209d24341ac84fc055ae71820ac'

},

'时间': 1533280462,

'价值': 0.8

}

]

}

}

],

'成功':是真的

}

在这里,我们使用ZQL语句返回我们感兴趣的元数据字段:uuid和hostUuid,并返回虚拟机的监视数据。细心的读者注意到我们在ZWatch查询字段中指定了参数resultName='webvm-cpu',并且在返回的JSON映射中监视数据的键也是webvm-cpu。与命名为as关键字一样,这是为了便于在执行多个ZWatch查询子句时检索返回的结果。ZStack UI使用非常复杂的ZQL查询。例如,在TOP 5页面上,ZQL查询最多包含13个ZWatch查询:

上面的示例是在ZStack CLI中使用引号转义

的执行示例

当资源特别大时,时序数据库查询性能可能成为多个ZWatch查询的性能瓶颈,因此返回将以并发方式执行插件,默认并发性为10。例如,上面示例中的13个ZWatch查询将在10个线程中同时执行。用户可以通过全局配置zql.returnWith.concurrency来更改并发性,例如

UpdateGlobalConfig category=query name=zql.returnWith.concurrency value=15

限制查询 (restrict by从句)

ZStack的企业管理模块包括一个可以将区域绑定到管理的功能,以便管理员只能管理该区域中的资源。这要求我们的ZQL仅向管理员返回查询请求到绑定区域。资源。

对于诸如虚拟机之类的资源,其元数据本身具有标识该区域的zoneUuid字段。然而,对于诸如eip的资源,元数据不具有指示区域属性的任何字段,并且区域属性由第3层网络或绑定的虚拟机确定。例如,要查询区域中的eip,可以使用:

查询与虚拟机的绑定关系

查询eip,其中vmNic.vmInstance.zoneUuid='52fdad0a2c0d4131a6c0fc6c1b7141a6'

由三层网络决定

查询eip,其中vip.l3Network.zoneUuid='52fdad0a2c0d4131a6c0fc6c1b7141a6'

无论哪种方式,调用者都需要知道eip和区域之间的关系,这对API的用户提出了非常苛刻的要求。ZQL使用restrict by子句解决了这个问题。与return with子句类似,restrict by也是一个插件框架,允许其他服务通过插件解释restrict by子句中指定的条件,并在生成的SQL中注入其他条件。例如,上面的eip示例可以写成strict by子句:

查询eip限制(zone.uuid='52fdad0a2c0d4131a6c0fc6c1b7141a6')

这里调用者不需要知道eip和zone之间的逻辑关系。 limit by插件的路径将自动计算两者之间的逻辑关系并生成相应的SQL join子句。在这里,eip可以通过三层网络或通过绑定虚拟机确定与区域的关系。插件将自动计算路径权重并使用权重最高的路径生成SQL语句。

对于eip示例,插件将选择通过网络的三个层的关系生成SQL语句。由于eip可能不会绑定到虚拟机,但它必须位于三层网络中,因此三层网络的路径具有更高的权重。

限制支持多个条件,以逗号分隔,并且多个条件之间存在AND关系。

除了被ZQL调用者使用之外,限制依赖插件也被ZStack中的其他服务广泛使用。例如,当普通帐户通过插件调用ZQL时,帐户系统将注入与帐户关联的SQL语句,以便普通帐户只能查询属于该帐户的资源;例如,SNS服务只能通过插件注入语句查询ZQL。系统类型的接收端。

未来

ZQL为ZStack提供了类似SQL的IaaS查询语言,并且可以通过返回插件框架与其他非关系数据库系统集成。我们将在未来版本中继续丰富其功能,目前有两个方向:

filter by从句

虽然使用ZWatch插件返回允许我们在查询资源的元数据时查询监控数据,但我们不能将监控数据用作元数据的查询条件。例如,无法通过ZQL实现查询集群中的所有CPU使用情况。 90%的虚拟机。这将通过filter by子句在将来的版本中实现,例如:

查询vminstance,其中clusterUuid='33e26bd547d149fbb190436cc9aca824'过滤(zwatch {metricName''CPUAllUsedUtilization',offsetAheadOfCurrentTime=60,threshold> 90})

类似地,filter by子句将实现为类似于return with的插件框架,用于集成非关系数据库的查询条件。

智能CLI

ZQL有很多子句。每个ZStack都有大量可查询字段。目前,ZStack CLI可以完成查询API的可查询字段,但ZQL无法暂时完成。在将来的版本中,我们将增强CLI,以便它可以提示并完成所有查询条件。

欢迎大家下载ZStack官方网站上的页面

http://www.zstack.io/product_downloads/

免费下载安装和试用版。