集群隔离
AIR 支持通过配置进行 Master 范围选举,可独立部署查询集群和构建任务集群,实现集群间的资源隔离。
节点角色
AIR Tardis 应用节点分为以下 3 个角色:
| 角色 | 说明 |
|---|---|
| Follower | 节点不参与选举,仅作为从节点运行 |
| Candidate | 参与选举 Leader,所有节点的默认角色 |
| Leader | 通过选举产生的集群唯一 Leader 节点,负责集群的管理和协调工作 |
配置方式
登录 Tardis 应用机器,编辑 config.properties 配置文件,新增以下配置项:
- 参数说明
| 配置项 | 可选值 | 默认值 | 说明 |
|---|---|---|---|
| node.role | FOLLOWER / CANDIDATE | CANDIDATE | 设置当前 Tardis 节点的角色 |
- 设置为
FOLLOWER:该节点不参与 Leader 选举,适用于仅需要处理查询或构建任务的节点 - 设置为
CANDIDATE:该节点参与 Leader 选举(默认行为),具备成为 Leader 的资格
引擎选择路由指南
1. 概述
AIR 通过 QueueRule 实现基于规则的引擎路由。分别为查询(Query)和构建(Build)两类场景提供规则匹配。
核心流程:
2. QueueRule 字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
String | 是 | 规则名称,用于标识 |
description |
String | 否 | 规则描述 |
expr |
String | 是* | Aviator 表达式,求值结果必须为 Boolean。 |
queueName |
String | 是 | 匹配成功后路由到的队列名,需与 ComputeUnit.queueName 对应 |
priority |
int | 是 | 优先级,数字越小优先级越高,优先匹配 |
3. 可用变量
3.1 查询规则(queryRules)可用变量
| 变量名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
userName |
String | "" |
执行查询的用户名 |
groupName |
String | "" |
用户所属分组 |
queryCost |
double | 0.0 |
查询预估代价 |
clientType |
String | "" |
客户端类型 |
clientIp |
String | "" |
客户端 IP 地址 |
catalogs |
String | "" |
逗号分隔的 catalog 名称列表 |
originalCatalogs |
String | "" |
原始 catalog 名称列表 |
schemas |
String | "" |
逗号分隔的 schema 名称列表 |
originalSchemas |
String | "" |
原始 schema 名称列表 |
tables |
String | "" |
逗号分隔的表名列表 |
originalTables |
String | "" |
原始表名列表 |
sourceTypes |
String | "" |
逗号分隔的数据源类型列表 |
3.2 构建规则(buildRules)可用变量
| 变量名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
owner |
String | "" |
数据集 / 投影 的 owner |
queryCost |
double | 0.0 |
构建预估代价 |
datasetPath |
String | "" |
数据集路径 |
taskType |
String | "" |
任务类型,如 "RP"、"EXPORT" |
sourceTypes |
String | null |
逗号分隔的数据源类型列表 |
rpName |
String | "" |
RP 名称(RP 构建时使用) |
exportName |
String | "" |
导出名称(Export 任务时使用) |
3.3 内置变量取值范围
clientType 取值
| 变量名 | 说明 |
|---|---|
PRESTO_JDBC |
Presto JDBC 连接 |
SERVICE |
数据服务调用 |
REPORT |
报表查询 |
ACCELERATION |
加速/投影构建查询 |
UI |
DWS UI 界面查询 |
INTERNAL |
内部系统查询 |
EXPORT |
导出任务查询 |
MYSQL_JDBC |
MySQL 协议连接 |
PyHive |
Python DB-API |
TRINO_JDBC |
Trino JDBC 连接 |
UNKNOWN |
无法识别的客户端,兜底值 |
taskType 取值
| 变量名 | 说明 |
|---|---|
RP |
投影构建 |
EXPORT |
数据导出任务 |
sourceTypes 取值
HIVE2,HIVE3,HIVE2_JDBC,HIVE3_JDBC,ICEBERG_HIVE,ICEBERG_HADOOP,MYSQL,MYSQL5,POSTGRESQL,ORACLE,MSSQL,MSSQL_2022,TIDB,
DAMENG,GAUSS,OPEN_GAUSS,HANA,DB2,VERTICA,INTER_SYSTEMS,OCEANBASE_MYSQL,OCEANBASE_ORACLE,STARROCKS,DORIS,CLICKHOUSE,
CMB_CLICKHOUSE,PRESTO,PRESTO_JDBC,SPARK,TRINO,IMPALA,CALCITE,DATABRICKS,ATHENA,SNOWFLAKE,HUAWEI_DWS,ELASTICSEARCH,
HBASE,MONGODB,NEBULA,ARGODB,HDFS,FILE,S3,AZURE_BLOB,API,AIR,LARKSUITE,UNKNOWN_SOURCE_TYPE
4. 表达式语法(Aviator 5.3.0)
expr 字段使用 AviatorScript 表达式语言,求值结果必须返回 true 或 false。
4.1 运算符
比较运算符
| 运算符 | 说明 | 示例 |
|---|---|---|
== |
等于 | userName == "admin" |
!= |
不等于 | clientType != "JDBC" |
> |
大于 | queryCost > 1000 |
>= |
大于等于 | queryCost >= 500 |
< |
小于 | queryCost < 100 |
<= |
小于等于 | queryCost <= 200 |
逻辑运算符
| 运算符 | 说明 | 示例 |
|---|---|---|
&& |
逻辑与 | userName == "admin" && queryCost > 100 |
\|\| |
逻辑或 | clientType == "JDBC" \|\| clientType == "REST" |
! |
逻辑非 | !string.contains(sourceTypes, "MYSQL") |
三元运算符
正则匹配运算符
| 运算符 | 说明 | 示例 |
|---|---|---|
=~ |
正则匹配 | userName =~ /admin.*/ |
4.2 内置字符串函数
以下是在规则表达式中最常用的函数:
| 函数 | 返回值 | 说明 | 示例 |
|---|---|---|---|
string.contains(s, sub) |
boolean | 字符串包含判断 | string.contains(sourceTypes, "DORIS") |
string.startsWith(s, prefix) |
boolean | 前缀判断 | string.startsWith(datasetPath, "/prod/") |
string.endsWith(s, suffix) |
boolean | 后缀判断 | string.endsWith(rpName, "_daily") |
string.length(s) |
long | 字符串长度 | string.length(userName) > 0 |
string.substring(s, begin, end) |
String | 子串截取 | string.substring(catalogs, 0, 4) == "prod" |
string.indexOf(s, sub) |
int | 查找子串位置,不存在返回 -1 | string.indexOf(sourceTypes, "HIVE") >= 0 |
string.replace_first(s, regex, replacement) |
String | 正则替换第一个 | - |
string.replace_all(s, regex, replacement) |
String | 正则替换全部 | - |
string.split(s, regex, limit) |
String[] | 字符串分割 | count(string.split(sourceTypes, ",", -1)) > 2 |
4.3 内置数学函数
| 函数 | 说明 | 示例 |
|---|---|---|
math.abs(n) |
绝对值 | math.abs(queryCost) > 100 |
math.ceil(n) |
向上取整 | math.ceil(queryCost) > 500 |
math.floor(n) |
向下取整 | - |
math.round(n) |
四舍五入 | - |
math.pow(a, b) |
幂运算 | - |
math.log(n) |
自然对数 | - |
math.log10(n) |
以10为底对数 | - |
math.sqrt(n) |
平方根 | - |
4.4 其他常用内置函数
| 函数 | 说明 | 示例 |
|---|---|---|
nil |
空值常量 | sourceTypes != nil |
count(collection) |
集合/数组元素个数 | count(string.split(catalogs, ",", -1)) > 1 |
include(collection, element) |
集合是否包含元素 | include(string.split(sourceTypes, ",", -1), "DORIS") |
seq.every(seq, predicate) |
所有元素满足条件 | - |
seq.some(seq, predicate) |
至少一个元素满足条件 | - |
seq.filter(seq, predicate) |
过滤元素 | - |
seq.map(seq, function) |
映射函数 | - |
5. 配置示例
在 queryComputeUnits / buildComputeUnits 中为需要路由的引擎配置 “queueName”,然后配置对应的逻辑规则 queryRules / buildRules
5.1 按数据源类型路由构建引擎
{
"buildRules": [
{
"name": "iceberg-hive-doris-build-rule",
"description": "Route ICEBERG_HIVE and DORIS RP builds to dedicated engine",
"expr": "string.contains(sourceTypes, \"ICEBERG_HIVE\") || string.contains(sourceTypes, \"DORIS\")",
"queueName": "doris_build_queue",
"priority": 1
}
]
}
5.2 按用户名路由查询引擎
{
"queryRules": [
{
"name": "admin-query-rule",
"description": "Admin users route to high-priority engine",
"expr": "userName == \"admin\" || userName == \"root\"",
"queueName": "high_priority_queue",
"priority": 1
}
]
}
5.3 按查询代价路由
{
"queryRules": [
{
"name": "heavy-query-rule",
"description": "Route heavy queries to dedicated engine",
"expr": "queryCost > 10000",
"queueName": "heavy_query_queue",
"priority": 1
},
{
"name": "light-query-rule",
"description": "Route light queries to fast engine",
"expr": "queryCost <= 100",
"queueName": "fast_query_queue",
"priority": 2
}
]
}
5.4 按客户端 IP 段路由
{
"queryRules": [
{
"name": "internal-ip-rule",
"description": "Internal network uses dedicated engine",
"expr": "string.startsWith(clientIp, \"10.5.\")",
"queueName": "internal_queue",
"priority": 1
}
]
}
5.5 组合条件
{
"queryRules": [
{
"name": "specific-catalog-user-rule",
"description": "Specific user querying specific catalog",
"expr": "userName == \"analyst\" && string.contains(catalogs, \"prod_catalog\")",
"queueName": "analyst_prod_queue",
"priority": 1
}
]
}
5.6 正则匹配
5.7 按任务类型路由构建引擎
{
"buildRules": [
{
"name": "export-task-rule",
"description": "Export tasks use dedicated engine",
"expr": "taskType == \"EXPORT\"",
"queueName": "export_queue",
"priority": 1
}
]
}
5.8 精确匹配数据源类型(使用 split + include)
{
"buildRules": [
{
"name": "exact-doris-rule",
"description": "Exact match DORIS in sourceTypes (avoid matching DORIS_XXX)",
"expr": "include(string.split(sourceTypes, \",\", -1), \"DORIS\")",
"queueName": "doris_queue",
"priority": 1
}
]
}
构建实例自动重启
AIR 支持对 Kyuubi Spark 引擎实例进行定时检测和自动重启,避免 Spark Driver 长时间运行导致内存泄漏或性能下降。
配置方式
编辑集群配置中对应的 ComputeUnit(buildComputeUnits)内添加 sparkManagerConfig 字段,或通过集群管理 API 更新配置。
配置项说明
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
kyuubiRestUrl |
String | 是 | - | Kyuubi REST API 地址,支持逗号分隔多个地址 |
yarnUrl |
String | 是 | - | YARN ResourceManager REST API 地址 |
maxRuntimeHours |
Integer | 否 | 24 | Spark 实例最大运行时长(小时),超过后触发重启 |
stopImmediately |
boolean | 否 | false | 立即停止模式:超时后直接停止并重启,不等待运行中的任务完成 |
stopGraceful |
boolean | 否 | false | 优雅停止模式:先从 ZooKeeper 下线(不再接受新任务),等待运行中的任务完成后再停止并重启 |
重启策略
根据 stopImmediately 和 stopGraceful 的配置,支持三种重启策略:
| 策略 | 配置 | 行为 | 适用场景 |
|---|---|---|---|
| 优雅停止 | stopGraceful = true |
先下线、等无任务后再停止重启 | 生产环境推荐 |
| 立即停止 | stopImmediately = true |
超时后直接停止重启,不等待任务 | 对中断容忍度高的场景 |
| 空闲停止 | 两者均为 false(默认) | 仅在无运行中任务时才停止重启 | 一般场景 |
注意:
stopImmediately优先级高于stopGraceful,两者同时为 true 时按立即停止处理。
配置示例
cluster.json 配置
{
"buildComputeUnits": [
{
"priority": 4,
"computeUnitName": "spark_kyuubi_build",
"computeUnitType": "BUILD",
"engineType": "KYUUBI_SPARK",
"connectionConfigs": {
"url": "jdbc:kyuubi://zk1:2181,zk2:2181,zk3:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi-tardis;",
"username": "devops"
},
"sparkManagerConfig": {
"kyuubiRestUrl": "http://kyuubi-host:10099",
"yarnUrl": "http://yarn-rm-host:8088/",
"maxRuntimeHours": 24,
"stopGraceful": true,
"stopImmediately": false
}
}
]
}
关闭自动重启
如果不需要自动重启功能,不配置 sparkManagerConfig 字段即可。已配置的情况下,移除 sparkManagerConfig 或将 kyuubiRestUrl / yarnUrl 置空即可关闭。