商丘做网站,商丘网站优化,商丘网络推广,商丘网络公司
当前位置:首页 > 新闻资讯 > 建站经验 >

【睢县SEO】揭密首个面向IaaS的查询语言:ZStack Query Language(ZQL)

发表日期:2018-08-26 13:45聚圣源浏览次数: 本文关键词:seo,睢县,SEO,优化,揭密,首个,面向,IaaS,se

  为了简化UI工作并为运维人员提供一种更加灵活的资源查询方式,ZStack在2.6版本中推出了首个面向IaaS的查询语言 —— ZStack Query Language,简称ZQL。

  背景

  IaaS管理着海量的数据中心资源,如何对这些资源进行灵活快速的查询是运维人员面临的一个难题。在以往的IaaS软件中,往往只对单个资源的某些字段提供有限的API查询支持,例如可以通过虚拟机的IP字段查询,这不足够也不灵活。运维人员在做复杂查询时往往得绕开IaaS软件直接查询其后端数据库,这既要求运维人员要了解IaaS资源的内部关系,又带来了数据库误操作的风险。

  从ZStack正式发布的第一个版本ZStack0.6开始,我们就致力在API层面提供跟数据库级别的查询功能,ZStack的每个资源都包含一个Query API,能够通过资源的自身字段以及资源的关联资源字段进行查询。例如

  QueryVmInstance name~=web-vm state=Running

  这里查询所有名字包含web-vm字符串,正在运行中的VM。又例如

  QueryVmInstance vmNics.eip.vip.ip='22.22.22.22'

  EIP是虚拟机的关联资源,这里查询网卡绑定了EIP为22.22.22.22的虚拟机。

  Query API功能强大:

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

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

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

  通过start、limit参数实现分页查询,类似SQL的limit和offset。

  Query API除了使用方便外,定义也很简单。程序员在ZStack中增加了一种新资源后,只需要在代码中定义如下class:

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

  public class APIQueryVmInstanceMsg extends APIQueryMessage {

  }

  不需要写任何实现,对应资源就具有了Query API。

  ZStack内部包含一个Query Service负责处理所有资源的Query API,将他们翻译成相应的SQL语句,在查询条件中包含关联资源条件时会生成对应的Join子句。

  基于Query API, ZStack0.6版本就包含了超过400万个单项查询条件,组合查询条件数为400万的阶乘。极大的方便了运维和复杂UI的设计。但Query API仍然包含一些缺陷:

  查询条件之间只能是AND逻辑,无法执行OR逻辑,条件之间也无法加括号实现复杂逻辑组合

  不支持类似SQL中的sub query子句

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

  不支持跟监控系统的查询语言整合

  随着ZStack UI的场景越来越丰富,Query API的限制使得UI端的工作越来越多,很多场景需要多次调用Query API进行数据组合。例如在监控Top 5页面(用于检测系统中CPU、内存、磁盘、网络等资源使用率最高5个资源的页面),需要先采用Query API将虚拟机、物理机等资源信息查询回来,再调用监控系统ZWatch的API查询对应的监控数据。

  Query API在未来的ZStack版本中会一直保留并维护,其后端实现已经从原来的Query Service替换成ZQL。

  ZStack Query Language

  使用过著名issue管理系统JIRA的开发者都知道JIRA在进行高级搜索的时大理候提供一种查询语言JQL (JIRA Query Language),能够使用一种类似SQL的DSL(Domain Specific Language)对JIRA中ticket的各个字段进行高效的查询。ZQL跟JQL类似,也是一种类似SQL的DSL,先来看一个例子:

  query vminstance where name='webvm' or vmnics.ip='192.168.0.10' or (vmnics.eip = '172.20.100.100' (cpuNum >= 8 or clusterUuid in ('fe13b725c80e45709f0414c266a80239','73ca1ca7603d454f8fa7f3bb57097f80')))

  在这个简单例子中,可以看到很多熟悉的SQL元素,例如and/or条件、括号、>=/in操作符等。ZQL可以看作SQL的一个子集外加ZStack根据自身需求进行的增强的查询语言。它的基本结构如下:

  QUERY queryTarget (WHERE condition+)? restrictBy? returnWith? groupBy? orderBy? limit? offset? filterBy? namedAs?

  query关键词

  一条ZQL语句通常以query关键字开头,queryTarget表示要查询的资源或资源字段的集合。前面的例子中vminstance代表虚拟机,例如host代表物理机、zone代表区域,所有可被查询的资源都有自己的名称。如果不希望返回资源的所有字段,只希望获得资源的一个或多个字段,实现类似SQL的uuid,name from ...的功能,可以在资源名后指定字段名,多个字段名用逗号隔离,例如:

  query vminstance.uuid,name,cpuNum

  该查询返回所有虚拟机的UUID、名称以及CPU数量。

  除了query关键字,查询也能以count和sum关键字开头,前者返回满足查询条件资源的总数,后者可以对资源的某个字段进行求和。例如:

  vminstance where cpuNum > 8

  返回系统中CPU数量超过8核的虚拟机的总数。

  sum vminstance.memorySize by name where cpuNum > 8 

  用虚拟机名字对CPU核数超过8个的虚拟机进行分组,对它们的memorySize字段进行求和。如果系统中有两个10CPU8G的虚拟机都名为webvm,则求和后返回webvm虚拟机总内存使用数为16G。翻译成SQL则为:

  sum(memorySize) from vminstance where cpuNum > 8 group by name

  WHERE从句

  ZQL的WHERE从句跟SQL的WHERE从句类似,支持and/or逻辑操作符、括号组合,条件的比较符支持=,!=,>,>=,<, <=, like, not like, is null, is not null, in, not in,查询条件名为资源的字段名。跟SQL不一样的地方在于,ZQL的查询条件可以是关联资源的字段,例如:

  query vminstance where 

  vmNics.eip.vip.ip='22.22.22.22'

  注意where从句前无需写类似SQL的from xx从句,因为query vminstance已经限定了被查询的资源

  这里vip跟eip关联,eip跟vmnic关联,vmnic又跟vminstance关联,则我们可以指定vip的IP作为查询条件。这正是ZQL的强大之处,对于多个关联资源的查询,无需调用多次API在应用端组合数据,也无需像SQL一样写复杂的join从句,只需要像编程一样通过点号(.)引用另一个资源即可, ZQL的翻译器会自动将跨资源引用翻译成对应的SQL join从句。

  WHERE从句可以包含子查询,类似于SQL的sub query功能,例如:

  query vminstance where vmNics.l3NetworkUuid in (query l3network.uuid 

  where ipRanges.networkCidr='10.1.0.0/24')

  这里找出所有CIRD为10.1.0.0/24的三层网络上运行的虚拟机。

  上面这个例子也可以用更简单的方法实现:query vminstance where 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分组,统计各区域中各集群中虚拟机的数量。

  vminstance group by zoneUuid,clusterUuid

  ORDER BY:

  查询所有虚拟机,使用cpuNum字段降序排序。

  1.query vminstance order by cpuNum desc

  LIMIT、OFFSET:

  使用limit和offset实现分页:

  query vminstance limit 100 offset 10

  多资源查询

  对于多个资源的查询,可以通过多条query查询语句实现,语句之间使用分号分隔,例如:

  query vminstance where name = 'my-vm';

  query host where cpuNum > 10;

  query zone;

  则一次调用即可返回三种资源的查询结果。由于返回的结果是一个map的JSON结构,为了方便获得对应语句的查询结果,可以使用named as关键字对查询语句命名,例如:

  query vminstance where name = 'my-vm' named as 'vm';

  query host where cpuNum > 10 named as 'host';

  query zone named as 'zone';

  则在返回的JSON map中,可以通过vm、host、zone作为key获得对应语句的查询结果。

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

  在ZStack中使用了两种数据库:关系数据库存放元数据,时序数据库存放监控数据。由于不同数据库查询方式不一样,在ZQL之前,用户要查询一个资源的监控数据,需要先通过Query 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子句解决这个问题。return with是一种插件机制,它允许子系统 通过插件将自身的查询条件注入ZQL中,ZQL会先执行关系数据库查询,将满足条件资源的原数据查询出来后,再将资源的主键(primary key)作为输入条件调用实现return with子句的插件,最后将插件的查询结果一并返回给ZQL的调用者。

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

  query vminstance.hostUuid,uuid where name = 'webvm' return with (zwatch{resultName='webvm-cpu',metricName='CPUAllUsedUtilization',offsetAheadOfCurrentTime=60})

  返回:

  {

  "results": [

  {

  "inventories": [

  {

  "hostUuid": "f8271f58468b4281a212a43e530b5535",

  "uuid": "05781209d24341ac84fc055ae71820ac"

  }

  ],

  "returnWith": {

  "webvm-cpu": [

  {

  "labels": {

  "VMUuid": "05781209d24341ac84fc055ae71820ac"

  },

  "time": 1533280402,

  "value": 0.8

  },

  {

  "labels": {

  "VMUuid": "05781209d24341ac84fc055ae71820ac"

  },

  "time": 1533280462,

  "value": 0.8

  }

  ]

  }

  }

  ],

  "success": true

  }

  这里我们用一条ZQL语句中即返回了我们感兴趣的元数据字段:uuid和hostUuid,也返回了该虚拟机的监控数据。细心的读者已经注意到我们在ZWatch查询字段中指定了参数resultName='webvm-cpu',并且在返回的JSON map中监控数据的key也是webvm-cpu。跟named as关键字一样,这是为了执行多条ZWatch查询子句时方便检索返回结果准备的。 ZStack UI使用非常复杂的ZQL查询语句,例如在TOP 5页面,一条ZQL查询包含多达13个ZWatch查询:

  ZQLQuery zql="query vmInstance.uuid,name where zoneUuid='89e148fb667c404dbc5309a2e956fa28' hypervisorType='KVM' type='UserVm' state='Running' return with (zwatch{resultName='CPUAllUsedUtilization',metricName='CPUAllUsedUtilization',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid\")',functions='top(num=5)'},zwatch{resultName='MemoryUsedInPercent',metricName='MemoryUsedInPercent',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid\")',functions='top(num=5)'},zwatch{resultName='MemoryFreeInPercent',metricName='MemoryFreeInPercent',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid\")',functions='top(num=5)'},zwatch{resultName='DiskAllReadOps',metricName='DiskAllReadOps',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid\")',functions='top(num=5)'},zwatch{resultName='DiskAllWriteOps',metricName='DiskAllWriteOps',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid\")',functions='top(num=5)'},zwatch{resultName='DiskAllReadBytes',metricName='DiskAllReadBytes',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid\")',functions='top(num=5)'},zwatch{resultName='DiskAllWriteBytes',metricName='DiskAllWriteBytes',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid\")',functions='top(num=5)'},zwatch{resultName='NetworkOutBytes',metricName='NetworkOutBytes',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid,NetworkDeviceLetter\")',functions='top(num=5)'},zwatch{resultName='NetworkInBytes',metricName='NetworkInBytes',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid,NetworkDeviceLetter\")',functions='top(num=5)'},zwatch{resultName='NetworkOutPackets',metricName='NetworkOutPackets',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid,NetworkDeviceLetter\")',functions='top(num=5)'},zwatch{resultName='NetworkInPackets',metricName='NetworkInPackets',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid,NetworkDeviceLetter\")',functions='top(num=5)'},zwatch{resultName='NetworkOutErrors',metricName='NetworkOutErrors',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid,NetworkDeviceLetter\")',functions='top(num=5)'},zwatch{resultName='NetworkInErrors',metricName='NetworkInErrors',offsetAheadOfCurrentTime=60,period=6,functions='average(groupBy=\"VMUuid,NetworkDeviceLetter\")',functions='top(num=5)'})"

  上例是在ZStack CLI中执行时的例子,使用\对引号转义

  当资源特别多时,时序数据库查询性能可能成为多条ZWatch查询的性能瓶颈,故return with会通过并发的方式执行插件,默认并发度为10。例如上述例子中的13条ZWatch查询会在10个线程中并发执行。用户可以通过全局配置zql.returnWith.concurrency更改并发度,例如

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

  限制查询 (restrict by从句)

  ZStack的企业管理模块包含一个功能,可以对管理绑定某个区域,使得该管理员只能管理该区域内的资源,这就要求我们的ZQL对该管理员的查询请求只返回与其绑定区区中的资源。

  对于虚拟机这样的资源,其元数据本身就带zoneUuid字段用于标识所在区域。但对于eip这样的资源,其元数据并无任何字段表示区域属性,区域属性是由其所在的三层网络或绑定的虚拟机确定的。例如要查询某个区域内的eip,可以使用:

  # 通过与虚拟机的绑定关系查询

  query eip where vmNic.vmInstance.zoneUuid = '52fdad0a2c0d4131a6c0fc6c1b7141a6'

  或

  # 通过所在三层网络确定

  query eip where vip.l3Network.zoneUuid = '52fdad0a2c0d4131a6c0fc6c1b7141a6'

  无论那种方式,都需要调用者了解知道eip跟zone之间的关联关系,这对API的使用者提出了非常苛刻的要求。ZQL通过restrict by从句解决这个问题。跟return with从句类似,restrict by也是个插件框架,它允许其它服务通过插件解读restrict by从句中指定的条件,向生成的SQL中注入额外条件。例如上面的eip例子通过restrict by从句可以写成:

  query eip restrict by (zone.uuid='52fdad0a2c0d4131a6c0fc6c1b7141a6')

  这里调用者无需知道eip跟zone之间的逻辑关系,restrict by的路径插件会自动计算两者的逻辑关系,并生成对应的SQL join从句。这里eip既可以通过所在三层网络,也可以通过绑定的虚拟机确定和区域的关系,插件会自动计算路径权重,使用权重最高的路径生成SQL语句。

  对于eip这个例子,插件会选取通过三层网络的关系生成SQL语句。因为eip可能没有跟虚拟机绑定,但其一定处于某个三层网络,故三层网络这条路径的权重更高。

  restrict by支持多个条件,通过逗号分隔,多个条件之间是AND关系。

  除了给ZQL调用者使用外,restrict by插件在ZStack内部也被其它服务广泛使用。例如账号系统会通过插件在普通账户调用ZQL的时候注入跟账号关联的SQL语句,使得普通账号只能查询到属于该账号的资源;又例如SNS服务会通过插件注入语句让ZQL只能查询到非系统类型的接收端。

  未来

  ZQL为ZStack提供了一种类似SQL的IaaS查询语言,并且能够通过return with插件框架跟其它非关系数据库系统进行查询整合。在未来的版本中我们还会继续丰富其功能,目前有两个方向:

  filter by从句

  虽然return with的ZWatch插件能让我们在查询资源元数据的同时查询其监控数据,但还不能将监控数据作为元数据的查询条件,例如无法通过一条ZQL实现查询某个集群中所有CPU使用率超过90%的虚拟机。这在未来版本中会通过filter by从句实现,例如:

  query vminstance where clusterUuid = '33e26bd547d149fbb190436cc9aca824' filter by (zwatch{metricName='CPUAllUsedUtilization', offsetAheadOfCurrentTime=60, threshold>90})

  同样,filter by从句会实现成类似return with的插件框架,用于整合非关系数据库的查询条件。

  智能CLI

  ZQL有大量的从句,每个ZStack又有大量的可查询字段,目前ZStack CLI可以对Query API的可查询字段进行补全,但ZQL还暂时无法补全。未来版本中,我们会对CLI进行在增强,使其对所有查询条件可以进行提示和补全。

  欢迎大家在ZStack官网下载页面

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

  进行免费的下载安装和试用。

如没特殊注明,文章均来自网络! 转载请注明来自:http://www.jushengyuan.com.cn/news/jzjy/10351.html

网站设计案例推荐

热门文章

站长工具综合查询里面SSL证书不...

SSL证书不安全是怎么回事?但是点进去这个提示后,显示的是别人的tdk是不是被劫持或者被黑了?...

日期:2018-03-27 浏览次数:1895

简洁而实用的版权信息可增色网...

打开网站,人们自然会从上往下浏览,首先映入眼帘的一定是BANNER主视觉,然后是网站主体内容部分。相比较而言,注意到网站底部版权信息的浏览者确实不多,但这并说明网站版权信...

日期:2018-09-20 浏览次数:1883

网站设计需要注意的3点问题...

对于网站设计来讲会受到很多因素的影响,而且不同类型的网站,在设计时需要体现的元素也不一样,比如说对于一个企业网站更想体现出品牌以及产品的特点,主要是对产品、企业信...

日期:2018-02-12 浏览次数:1808

企业网站为什么要改版 改版选择...

网站改版,是每个建站企业必须面临的工作。相信也有不少站长问,已经做好的企业网站,为何还要大费周章重新进行改版设计呢?下面小编就来给大家说说,企业究竟为什么要改变,并...

日期:2018-03-26 浏览次数:1338

永城网站制作:模板建站不可不...

随着互联网建站尤其是自助建站热潮不断高涨,建站行业涌现出越来越多的自助建站平台,这些平台普遍都提供网站模板可选。...

日期:2018-04-30 浏览次数:940

相关文章

【辽宁网站建设】常用网站建设...

大众创业,万众创新,早已成为当下热门词,无数的青年才俊,投入到创业浪潮中去。创业的第一步,大家都知道是进行工商注册,那第二步是什么呢? 创业的第二步,其实应该是搭建...

日期:2018-09-15 浏览次数:72

【睢县网站制作】模板建站真比...

小程序创业扶 汕尾 持计划 实现月入10万创业梦 经常看到有人在说,模板建站和定制建站相比,最好选定制建站,觉得模板建站没有特色,千篇一律,定制建站能根据自己的需求定做网...

日期:2018-09-15 浏览次数:70

【虞城网站制作】模板建站比定...

很多网络公司销售在向客户推销时会说,模板建站和定制建站相比,最好选定制建站,因为定制网站是纯手工制作,模板建站是套用框架。但是模板建站,真的比定制建站差吗?网站模板...

日期:2018-09-13 浏览次数:71

【吉林做网站】构筑企业微中心...

互联网时代,企业通过官网链接更多客户,可以说,官网则就是企业的门面,是品牌企业的标志,所以权威度是和企业一致的。 对于企业而言,官网究竟有多重要? 1.提高可信度 品牌官网能够...

日期:2018-09-12 浏览次数:60

【夏邑做网站】如何安装米拓建...

米拓建站系统是一款 高端、快速、开源 的建站系统,模板风格仅仅是网站的外表,模板背后所使用的系统后台才是网站真正的核心,了解米拓系统的功能。 一、获取米拓建站系统安装包 米拓...

日期:2018-09-12 浏览次数:70

随机推荐

初期草根站长适合做什么样的网...

对于企业网站建设来说 哪些内容...

企业建站:打造炫酷官网的几个...

网站建设如何突破同质化竞争的...

网站建设搜索框设计技巧和功能...

利用robots文件做seo优化,让蜘蛛...