3.3 触发增量构建
3.3.1 Web GUI触发
在Web GUI上触发Cube的增量构建与触发全量构建的方式基本相同。在Web GUI的Model页面中,选中想要增量构建的Cube,单击Action→Build,如图3-3所示。
不同于全量构建,增量构建的Cube会在此时弹出对话框让用户选择“End Date”(如
图3-4所示),目前Kylin要求增量Segment的起始时间等于Cube中最后一个Segment的结束时间,因此当我们为一个已经有Segment的Cube触发增量构建的时候,“Start Date”的值已经被确定,且不能修改。如果在触发增量构建的时候Cube中不存在任何的Segment,那么“Start Date”的值会被系统设置为“Partition Start Date”的值(参见3.2.2节)。
图3-3 触发增量构建
图3-4 选择增量构建End Date
仅当Cube中不存在任何Segment,或者不存在任何未完成的构建任务时,Kylin才接受该Cube上新的构建任务。未完成的构建任务不仅包含正在运行中的构建任务,还包括已经出错并处于ERROR状态的构任务。如果存在一个ERROR状态的构建任务,那么用户需要先处理好该构建任务,然后才能成功地向Kylin提交新的构建任务。处理ERROR状态的构建任务的方式有两种:比较正常的做法是首先在Web GUI或后台的日志中查找构建失败的原因,解决问题后回到Monitor页面,选中失败的构建任务,单击Action→Resume,恢复该构建任务的执行。我们知道构建任务分为多个子步骤,Resume操作会跳过之前所有已经成功了的子步骤,直接从第一个失败的子步骤重新开始执行。举例来说,如果某次构建任务失败,我们在后台Hadoop的日志中发现失败的原因是由于Mapper和Reducer分配的内存过小导致了内存溢出,那么我们可以在更新了Hadoop相关的配置之后再恢复失败的构建任务。
3.3.2 构建相关的Rest API
Kylin提供了Rest API以帮助自动化地触发增量构建。该API同样也适用于非增量构建的Cube。关于Kylin API的更详细的介绍可以参见Kylin官网:http://kylin.apache.org/docs15/howto/howto_build_cube_with_restapi.html和http://kylin.apache.org?/docs15/howto/howto_use_restapi.html。
本节将着重介绍增量构建相关的API。事实上我们在Web GUI上进行的所有操作,其背后调用的都是同一套Rest API,所以在使用Rest API触发构建的时候,应当谨记之前进行Web GUI构建时所遇到的限制和经验。
1.?获取Segment列表
首先可以通过以下的Rest API来获取某个Cube所包含的所有的Segment列表信息。返回的列表信息可以帮助客户端分析Cube的状态,并且决定下一步增量构建的参数:
GET http://hostname:port/kylin/api/Cubes?CubeName={CubeName}
Path Variable
CubeName – 必须的,Cube名字
举例而言,假设在本地的7070端口启动了Kylin Server,那么可以通过如下的Rest请求获取名为test_kylin_cube_without_slr_empty的Cube的Segment列表:
curl -X GET -H "Authorization: Basic QURNSU46S1lMSU4=" -H "Content-Type: application/json" http://localhost:7070/kylin/api/Cubes?CubeName=test_kylin_cube_ ? without_slr_empty
格式化之后,该请求的返回结果如下所示:
[
{
"uuid": "daa53e80-41be-49a5-90ca-9fb7294db186",
"version": "1.5.3",
"name": "test_kylin_cube_without_slr_empty",
"owner": null,
"cost": 50,
"status": "READY",
"segments": [
{
"uuid": "f492158b-0910-4ced-bc51-26e78b9b8b81",
"name": "19700101000000_20220101000000",
"status": "READY",
"dictionaries": {
"DEFAULT.TEST_KYLIN_FACT/LSTG_SITE_ID": "/dict/EDW.TEST_SITES/SITE_ID/a9f93c23-9eca-4e2e-a814-17b81344a816.dict",
"DEFAULT.TEST_CATEGORY_GROUPINGS/CATEG_LVL2_NAME": "/dict/DEFAULT.
TEST_CATEGORY_GROUPINGS/CATEG_LVL2_NAME/58372aa5-6d42-4045-a32f-e6ae41c219a8.dict",
"DEFAULT.TEST_KYLIN_FACT/LSTG_FORMAT_NAME": "/dict/DEFAULT.TEST_KYLIN_FACT/LSTG_FORMAT_NAME/2e2e8137-5600-4c63-ba3f-3f382f452227.dict",
"DEFAULT.TEST_KYLIN_FACT/LEAF_CATEG_ID": "/dict/DEFAULT.TEST_
CATEGORY_GROUPINGS/LEAF_CATEG_ID/ee675200-8c5c-4112-99fa-763bb0aa689a.dict",
"DEFAULT.TEST_CATEGORY_GROUPINGS/META_CATEG_NAME": "/dict/DEFAULT.
TEST_CATEGORY_GROUPINGS/META_CATEG_NAME/8bc37a42-5577-4c18-b6a5-bd1c7eb55c73.dict",
"DEFAULT.TEST_KYLIN_FACT/SLR_SEGMENT_CD": "/dict/EDW.TEST_SELLER_
TYPE_DIM/SELLER_TYPE_CD/0c356b8c-74fa-4e58-b8b8-bbbd5095a6be.dict",
"DEFAULT.TEST_KYLIN_FACT/CAL_DT": "/dict/EDW.TEST_CAL_DT/CAL_
DT/5e4b4f35-0fc8-4940-b123-b18c9f77da19.dict",
"DEFAULT.TEST_KYLIN_FACT/PRICE": "/dict/DEFAULT.TEST_KYLIN_FACT/
PRICE/94d429fc-60ef-4635-af1e-2b47679bb494.dict",
"DEFAULT.TEST_CATEGORY_GROUPINGS/CATEG_LVL3_NAME": "/dict/DEFAULT.
TEST_CATEGORY_GROUPINGS/CATEG_LVL3_NAME/759e5fd6-9c7e-47ed-9293-e7c8695b6bb4.dict"
},
"snapshots": {
"EDW.TEST_SITES": "/table_snapshot/test_sites/1c3d3b91-8afa-
4d12-8743-5376133185eb.snapshot",
"EDW.TEST_CAL_DT": "/table_snapshot/test_cal_dt/96a2ad25-4279-
4c7f-9c0a-7e1f0132ae77.snapshot",
"DEFAULT.TEST_CATEGORY_GROUPINGS": "/table_snapshot/test_category
_groupings/3ed9f146-2a8b-4bdb-8899-45f2d765c25a.snapshot",
"EDW.TEST_SELLER_TYPE_DIM": "/table_snapshot/test_seller_type_
dim/f7f7b3c8-cfe8-49ea-8230-8c296d0e03ef.snapshot"
},
"storage_location_identifier": "KYLIN_KZO9NPAWGC",
"date_range_start": 0,
"date_range_end": 1640995200000,
"source_offset_start": 0,
"source_offset_end": 0,
"size_kb": 1589,
"input_records": 6000,
"input_records_size": 154637,
"last_build_time": 1467995504950,
"last_build_job_id": "f3f49487-e5bc-4fd0-a571-58c13c9311e9",
"create_time_utc": 1467995076271,
"cuboid_shard_nums": {},
"total_shards": 1,
"blackout_cuboids": [],
"binary_signature": null,
"index_path": "/kylin/kylin_metadata/kylin-f3f49487-e5bc-4fd0-a571-
58c13c9311e9/test_kylin_cube_without_slr_empty/secondary_index/",
"rowkey_stats": [
[
"LEAF_CATEG_ID",
134,
1
],
[
"META_CATEG_NAME",
44,
1
],
[
"CATEG_LVL2_NAME",
94,
1
],
[
"CATEG_LVL3_NAME",
127,
1
],
[
"LSTG_SITE_ID",
262,
2
],
[
"SLR_SEGMENT_CD",
8,
1
],
[
"CAL_DT",
3652427,
3
],
[
"LSTG_FORMAT_NAME",
5,
1
],
[
"PRICE",
5999,
2
]
]
}
],
"last_modified": 1467995504950,
"descriptor": "test_kylin_cube_without_slr_desc",
"create_time_utc": 0,
"size_kb": 1589,
"input_records_count": 6000,
"input_records_size": 154637
}
]
尽管输出比较复杂,但是我们仍然能够迅速地观察到当前的test_kylin_cube_without_slr_empty包含一个Segment,该Segment的分割时间为1970-01-01到2022-01-01。我们还能看到该Segment的状态(“status”)均为READY,表示这个Segment背后的构建任务均已正常完成,并且这个Segment已经可以正常使用。
2.?获取构建任务详情
如果Segment的状态显示为“NEW”,则说明该Segment背后的构建任务尚未完成,需要提取该构建任务的标识符(job id),即Segment中的last_build_job_id字段的值,然后以此为参数向Kylin提交如下的Rest请求以获取该构建任务的详情:
GET http://hostname:port/kylin/api/jobs/{job_uuid}
Path Variable
Job_uuid – 必需的,构建任务标识符
该请求的返回会带上相应的任务步骤清单,步骤中可能包含MapReduce作业或其他作业。每一个步骤都有相应的状态信息“step_status”。
PENDING:表示该步骤处于等待被执行的状态。
RUNNING:表示该步骤处于执行状态。
ERROR:表示该步骤的执行已经结束,并且该步骤执行失败。
DISCARDED:表示该步骤由于这个构建任务被取消而处于取消状态。
FINISHED:表示该步骤的执行已经结束,并且该步骤执行成功。
test_kylin_cube_without_slr_empty的第一个Segment的last_build_job_id为f3f49487-e5bc-4fd0-a571-58c13c9311e9,通过以上的Rest接口可以得到如下的结果:
{
"uuid": "f3f49487-e5bc-4fd0-a571-58c13c9311e9",
"version": "1.5.3",
"name": "test_kylin_cube_without_slr_empty - 19700101000000_20220101000000 - BUILD - GMT-08:00 2016-07-08 08:24:36",
"type": "BUILD",
"duration": 393,
"steps": [
{
"id": "f3f49487-e5bc-4fd0-a571-58c13c9311e9-00",
"name": "Count Source Table",
"info": {
"endTime": "1467995164094",
"source_records_size": "571743",
"mr_job_id": "job_1466095360365_0611",
"hdfs_bytes_written": "6",
"yarn_application_tracking_url": "http://sandbox.hortonworks.com:
8088/proxy/application_1466095360365_0611/",
"startTime": "1467995122900"
},
"interruptCmd": null,
"sequence_id": 0,
"exec_cmd": "hive -e \"SET dfs.replication=2;\nSET hive.exec.compress.
output=true;\nSET hive.auto.convert.join.noconditionaltask=true;\nSET hive.auto.convert.join.noconditionaltask.size=300000000;\nSET hive.merge.size.per.task=32000000;\n\nset hive.exec.compress.output=false;\n\ndfs -mkdir -p /kylin/kylin_metadata/kylin-f3f49487-e5bc-4fd0-a571-58c13c9311e9/row_count;INSERT OVERWRITE DIRECTORY '/kylin/kylin_metadata/kylin-f3f49487-e5bc-4fd0-a571-58c13c9311e9/row_count' SELECT count(*) from DEFAULT.TEST_KYLIN_FACT TEST_KYLIN_FACT\nWHERE (TEST_KYLIN_FACT.CAL_DT < '2022-01-01')\n\n\"",
"interrupt_cmd": null,
"exec_start_time": 1467995122900,
"exec_end_time": 1467995164094,
"exec_wait_time": 0,
"step_status": "FINISHED",
"cmd_type": "SHELL_CMD_HADOOP",
"run_async": false
},
{
"id": "f3f49487-e5bc-4fd0-a571-58c13c9311e9-01",
"name": "Create Intermediate Flat Hive Table",
"info": {
"endTime": "1467995223284",
"startTime": "1467995164168"
},
"interruptCmd": null,
"sequence_id": 1,
"exec_cmd": null,
"interrupt_cmd": null,
"exec_start_time": 1467995164168,
"exec_end_time": 1467995223284,
"exec_wait_time": 0,
"step_status": "FINISHED",
"cmd_type": "SHELL_CMD_HADOOP",
"run_async": false
},
…
{
"id": "f3f49487-e5bc-4fd0-a571-58c13c9311e9-16",
"name": "Garbage Collection",
"info": {
"endTime": "1467995516662",
"startTime": "1467995505050"
},
"interruptCmd": null,
"sequence_id": 16,
"exec_cmd": null,
"interrupt_cmd": null,
"exec_start_time": 1467995505050,
"exec_end_time": 1467995516662,
"exec_wait_time": 0,
"step_status": "FINISHED",
"cmd_type": "SHELL_CMD_HADOOP",
"run_async": false
}
],
"submitter": "TEST",
"progress": 100,
"last_modified": 1467995516721,
"related_cube": "test_kylin_cube_without_slr_empty",
"related_segment": "f492158b-0910-4ced-bc51-26e78b9b8b81",
"exec_start_time": 0,
"exec_end_time": 0,
"mr_waiting": 94,
"job_status": "FINISHED"
}
由于篇幅的限制,此处省略了中间14个子步骤的信息,但是仍然可以观察到每个子步骤的信息都描述了步骤的参数等元信息,另外每个子步骤还有一个唯一的字符串标识符“id”。这些信息可以帮助快速定位问题的所在。
3.?获取构建步骤的输出
一般情况下,构建触发的客户端会首先获取Cube的Segment列表,如果所有Segment的状态都是READY,那么客户端就可以开始构建新的Segment。反之,如果存在状态不是READY的Segment,那么客户端需要获取构建任务详情来观察各个子步骤的状态:如果某个子步骤的状态为ERROR,或者长时间PENDING,或者运行了非常长的时间,那么客户端有必要检查一下该步骤中究竟正在发生什么。Kylin提供了另外一个Rest接口允许用户获取构建任务中某个特定子步骤的输出,接口的请求如下:
GET http://hostname:port/kylin/api/jobs/{job_uuid}/steps/{step_id}/output
Path Variable
Job_uuid – 必需的,构建任务标识符
Step_id – 必需的,构建任务子步骤标识符
该接口的输出为该步骤的日志,根据输出的结果,用户可以在触发构建的客户端中找到问题并修复问题,并且可调用以下的RESUME Rest接口重新执行该次构建任务。RESUME接口会跳过之前所有已经成功了的子步骤,直接从第一个失败的子步骤开始重新执行:
PUT http://hostname:port/kylin/api/jobs/{job_uuid}/resume
Path Variable
Job_uuid – 必需的,构建任务标识符
由于自动修复的复杂性,触发构建的客户端也可以选择只向管理员发送邮件通知该次失败。Kylin服务器中自带的Web GUI客户端中暂时没有自动修复的逻辑,在遇到构建失败的情况时,Web GUI会根据Cube层面的配置向不同的人员发送构建失败的消息,并且将整个构建任务置于ERROR状态,并等待管理人员重新登录Web GUI查看详情。关于出错时通知方式的配置可以参考第10章。
4.?触发构建
首先介绍一下具体的API规范,代码如下:
PUT http://hostname:port/kylin/api/Cubes/{CubeName}/rebuild
Path Variable
CubeName – 必需的,Cube名字
Request Body
startTime – 必需的,长整数类型的起始时间,例如使用1388563200000代表起始时间为2014-01-01
endTime – 必需的,长整数类型的结束时间
buildType – 必需的,构建类型,可能的值为‘BUILD’‘MERGE’和‘REFRESH’,分别对应于新建Segment、合并多个Segment,以及刷新某个Segment
举例而言,假设在本地的7070端口启动了Kylin Server,那么可以通过如下的Rest请求申请名为test_kylin_cube_without_slr_empty的Cube,用于增量地构建[2022-01-01, 2023-01-01)这个时间段的新Segment:
curl -X PUT -H "Authorization: Basic QURNSU46S1lMSU4=" -H "Content-Type: application/json" -d '{"startTime": 1640995200000, "endTime": 1672560000000, "buildType": "BUILD"}' http://localhost:7070/kylin/api/Cubes/test_kylin_cube_without_slr_empty/rebuild
如果当前Cube不存在任何Segment,那么可以将startTime设置为0,这样kylin就会自动选择Cube的Partition Start Date(见3.2.2节)作为startTime。如果当前Cube不为空,那么对于BUILD类型的构建任务,请求中的startTime必须等于最后一个Segment的endTime,否则请求会返回500错误。