【资源控制】自助查询的智能路由

智能路由的设计目标是让用户对底层集群无感知。

  • 用户只提交查询意图和 SLA,平台根据 SQL 指纹、历史执行画像、当前租户权限、数据源能力、集群健康状态和实时资源情况,自动选择最合适的执行环境。

  • 路由层负责生成可解释的 RouteDecision,Linkis 负责将决策落到 EngineConn 和具体计算引擎上。

  • 在执行失败时,我会把业务任务和具体执行尝试分开,通过状态机驱动重试和重新路由,而不是简单地重复提交。这样既能保证任务语义不变,又能根据最新资源状态选择新的集群或引擎。

  • 成功率验证:最终通过 SLA 命中率、路由后成功率、重试恢复率、排队时间和资源利用率验证这套智能路由是否真正有效。

总体来说

路由层解决的是多引擎、多集群环境下的执行决策问题。它基于标准化查询意图、SQL 指纹、历史执行画像和实时资源状态,先做权限、兼容性和配额过滤,再根据 SLA、耗时和资源成本选择最终执行环境,生成可解释的 RouteDecision。这个决策通过标准化请求、标签和运行配置转发给 Linkis,由 Linkis 完成 EngineConn 管理和实际执行。如果路由判断错误,则在 ExecutionAttempt 层进行切换和恢复,执行结果再反馈给画像系统,持续优化后续路由。

1、路由层要解决的问题和设计

路由层要解决的核心问题是:

在多个计算引擎、多个集群和多个资源队列并存的情况下,用户不需要指定 Spark、Trino 还是 JDBC,平台能够根据查询特征和运行状态,自动选择合适的执行环境,并对路由结果负责。

存在的意义

  1. 业务和引擎耦合:如果没有路由层,自助查询平台就需要直接绑定具体引擎,导致业务语义和基础设施耦合。
  2. 基于当前情况动态选择资源:平台统一考虑查询规模(元数据提供)、SLA(成功率)、租户配额(你有没有权限、权限的资源够不够)和集群负载。

因此,我会把路由层设计成一个独立的执行决策模块。它不负责真正提交任务,只负责将标准化的查询请求转换为可解释的 RouteDecision

路由层主要包含四个设计点。

第一,统一路由:统一提交协议、

自助查询平台先将用户的指标、维度、数据集、筛选条件和 SLA 转换成统一的 SubmitRequest,其中包含:

text 复制代码
1、查询内容:用户到底想执行什么。
QueryIntent
SQL 或 LogicalQueryPlan

2、数据源信息:查询涉及哪些数据,哪些引擎具备执行能力。
DataSource
QueryType

3、租户信息:谁在执行,以及他可以使用什么资源和数据。
Tenant
User

4、历史的SLA:能够给资源推荐
SLA
ResourceHint

路由层不直接依赖页面参数,也不通过 SQL 文本简单猜测引擎,而是基于结构化查询信息做决策。

第二,建立 SQL 指纹和执行画像

路由层对 SQL 做规范化和参数化,生成 SQLFingerprint,并记录该查询过去的执行画像:

  1. 过去在哪里执行:engine 和 cluster 描述过去在哪里执行
  2. 查询规模:scanBytes 和 shuffleBytes 描述查询规模
  3. 查询排队和执行时间:queueTime 和 executeTime 描述性能
  4. 执行成功率:successRate 和 slaHitRate 描述稳定性
  5. 使用的内存:peakMemory 和 runtimeConfig 用于资源调优
  6. 调度与重试:failureReason 用于决定失败后是重试、切换集群还是直接返回错误。

路由层基于这些历史画像,再结合当前租户权限和集群状态,生成最终的执行决策。

这样,路由决策就不只是静态规则,而是可以利用历史执行结果判断:

text 复制代码
这个 SQL 适合什么引擎
通常需要多少资源
在哪个集群执行更稳定
是否能够满足 SLA

第三,候选过滤和路由决策

  1. 生成候选集群之后进行约束过滤:硬约束(权限、对应队列是否有权限、集群健康、配额是否够),软约束(历史成功率、预计执行时间、排队时间、集群负载等),进行推荐集群执行。

路由层先生成候选执行环境:

text 复制代码
Trino / interactive-a
Trino / interactive-b
Spark / offline-a

然后分两步决策。

第一步是硬约束过滤:

text 复制代码
权限是否满足
数据源是否兼容
SQL 方言是否支持
租户是否有队列权限
集群是否健康
租户配额是否足够

第二步是软指标评分:

text 复制代码
历史成功率
SLA 命中率
预计执行时间
当前排队时间
资源成本
集群负载

最终形成:

text 复制代码
engine: Trino
cluster: interactive-a
queue: tenant_a
resource: small
reason:
  - scan_size_below_threshold
  - historical_sla_hit_rate_high
  - cluster_healthy

这里需要强调,路由结果必须可解释。平台不仅要告诉执行哪个引擎,还要保留为什么选择它,便于故障排查、审计和后续优化。

第四,执行失败后的恢复

路由是执行前的预估,可能出现统计信息不准确、实际数据量变大或集群状态变化。因此要把业务任务和具体执行尝试分开:

text 复制代码
Task:
用户原始查询意图

ExecutionAttempt:
一次具体的执行尝试

如果 Trino 执行超时,可以保留原始 Task,并创建新的 Attempt 切换到 Spark:

text 复制代码
Attempt 1:Trino / interactive-a,执行超时
Attempt 2:Spark / offline-a,重新执行

不同失败采用不同策略:

text 复制代码
SQL 语义错误:直接失败,不重试
EngineConn 创建失败:Attempt 级重试
外部提交超时:先查询 applicationId,避免重复提交
资源不足:调整资源或切换集群
集群不可用:重新选择候选环境

所以路由层的完整职责是:

text 复制代码
识别查询特征
-> 生成候选环境
-> 做权限和资源过滤
-> 选择引擎、集群、队列和资源
-> 输出可解释的 RouteDecision
-> 在 Attempt 层支持失败恢复

2、实际例子:订单查询如何与 Linkis 结合

假设用户在自助查询页面中选择:

text 复制代码
指标:订单金额
维度:销售渠道
时间范围:近 7 天
SLA:10 秒

自助查询平台先完成业务语义解析和权限校验,生成标准请求:

json 复制代码
{
  "dataset": "orders",
  "queryType": "aggregation",
  "sql": "SELECT channel, SUM(payment_amount) ...",
  "tenant": "tenant_a",
  "user": "user_1001",
  "slaSeconds": 10
}

路由层根据 SQL 指纹查询历史画像,发现:

text 复制代码
平均扫描量:5 GB
Trino 平均耗时:12 秒
Spark 平均耗时:90 秒
Trino SLA 命中率:98%

然后获取当前候选环境:

text 复制代码
Trino / interactive-a:健康,排队 2 秒
Trino / interactive-b:健康,排队 40 秒
Spark / offline-a:健康,但属于离线队列

经过权限、数据源兼容性、租户配额和集群健康度过滤后,路由层选择:

text 复制代码
engine: Trino
cluster: interactive-a
queue: tenant_a
resource: small

并生成:

text 复制代码
RouteDecision

路由层不会直接调用 Trino,也不会自己创建连接,而是把这个决策转换成 Linkis 的标准请求和标签:

text 复制代码
engineType = trino
cluster = interactive-a
queue = tenant_a
runtimeConfig = small

然后提交给 Linkis:

text 复制代码
RouteDecision
-> SubmitRequest / Labels
-> Linkis Orchestrator
-> EngineConnManager
-> Trino EngineConn
-> Trino Cluster

Linkis 负责完成:

text 复制代码
任务编排
EngineConn 复用或创建
资源和租户校验
查询提交
状态跟踪
日志获取
结果获取

自助查询平台只需要依赖统一的任务和结果接口,不需要感知底层是:

text 复制代码
Trino Session
Spark Application
JDBC Statement

如果执行过程中发现实际扫描量远大于预估,Trino 执行超过 SLA,路由层可以终止当前:

text 复制代码
ExecutionAttempt 1

然后重新生成一个执行决策:

text 复制代码
engine: Spark
cluster: offline-a
queue: tenant_a
resource: 4 cores / 8 GB

再通过 Linkis 创建:

text 复制代码
ExecutionAttempt 2

原始任务仍然是同一个:

text 复制代码
Task:查询近 7 天订单金额

执行结束后,Linkis 返回任务状态、执行指标和结果引用,路由层再将以下信息回写至 SQL 指纹画像,用于持续优化:

text 复制代码
实际引擎
实际集群
扫描量
排队时间
执行耗时
资源消耗
SLA 是否命中
失败原因

最终形成:

text 复制代码
自助查询:
用户想查什么

路由层:
选择什么引擎、集群和资源

Linkis:
如何管理和提交任务

Trino / Spark:
真正执行查询

其他

运行时间估算

预计排队时间不是一个精确值,而是基于实时队列状态和历史资源释放速度计算出的预测值。

  1. 对于 Trino,我会从 Resource Group 获取当前运行查询数、排队查询数、并发上限和查询优先级,再结合最近一段时间的查询完成速率估算。例如当前查询排在第 5 位,集群每秒平均完成 2.5 个查询,那么预计排队约 2 秒。
  2. 对于 Spark,我会从 YARN 获取目标队列的可用 CPU、内存、Pending Application、前方任务资源需求和当前任务最低启动资源,再结合历史资源释放速度计算。例如前方任务加当前任务共需要释放 32 个 vCore 和 128 GB 内存,队列每秒释放 0.8 个 vCore 和 3.2 GB 内存,那么预计资源等待约 40 秒,再加上调度和 ApplicationMaster 启动开销,预计排队约 45 秒。

路由层最终比较的不是单独的排队时间,而是预计端到端完成时间,也就是排队时间、EngineConn 获取时间、执行时间和结果交付时间之和。任务真正启动后,再用实际排队时间修正预测模型,形成持续反馈闭环。

SLA 计算

Trino SLA 命中率 98% 的意思是:

在统计范围内,路由到 Trino 的同类查询中,有 98% 在约定时间内完成了用户可用的结果交付。

例如,某类 SQL 的 SLA 是 10 秒,最近 7 天共执行了 1000 次:

text 复制代码
980 次在 10 秒内完成
20 次超过 10 秒或执行失败

SLA 命中率 = 980 / 1000 = 98%

这里的"完成时间"最好按用户端到端体验计算:

text 复制代码
SLA 耗时 = 排队时间 + EngineConn 获取时间 + 执行时间 + 结果交付时间

不能只计算 Trino 的 SQL 执行时间。比如 SQL 在 Trino 中执行了 6 秒,但排队 5 秒、结果封装 2 秒,总耗时 13 秒,对于 10 秒 SLA 来说仍然没有命中。

指标也不能只说"Trino 整体命中率 98%",必须带上统计维度:

text 复制代码
SQL 指纹:哪一类查询
集群:哪个 Trino 集群
SLA 档位:10 秒还是 30 秒
租户或资源组:使用什么配额
统计窗口:最近 7 天还是最近 30 天
样本量:总共执行了多少次

完整表达应该是:

最近 7 天,该 SQL 指纹在 trino-interactive-a 集群执行了 1000 次,其中980次在10秒内完成结果交付,因此该候选环境的10秒 SLA 命中率是98%。

路由时,98% 表示历史上 Trino 对这类查询具有较高的时效稳定性,但它不能单独决定路由。还要结合样本量、当前排队时间、集群资源、查询扫描量和租户权限。

例如:

text 复制代码
Trino 历史 SLA 命中率:98%
当前预计排队时间:2 秒
预计扫描量:5 GB
租户有权限,资源充足

可以优先路由到 Trino。但如果当前 Trino 集群已经严重拥堵,即使历史命中率是 98%,本次也可能选择备用 Trino 集群或 Spark。

Trino SLA 命中率 98%,表示在指定统计周期内,同类 SQL 路由到指定 Trino 集群后,有 98% 能在约定时间内完成端到端结果交付。这个指标反映的是历史时效稳定性,路由时还需要结合当前集群负载、预计扫描量、租户权限和样本量一起判断。

相关推荐
SelectDB1 小时前
无锡锡商银行 数据仓库演进:Apache Doris / SelectDB 的技术能力与实践
数据库
名不经传的养虾人1 小时前
从0到1:企业级AI项目迭代日记 Vol.87|记忆链路切换了,系统接管有了质量门
大数据·人工智能·ai编程·企业ai·多agent协作
GlobalInfo1 小时前
2026年显微外科手术机器人系统市场报告:市场规模、产业研究、十五五规划与发展趋势预测
大数据·人工智能·机器人
SelectDB1 小时前
雨润集团 统一实时数据仓库:Apache Doris / SelectDB 的技术能力与实践
数据库
Htr_1 小时前
Outcome 核心概念与实战应用指南
大数据·hadoop·apache
SelectDB1 小时前
天翼云 Iceberg 湖仓一体:Apache Doris / SelectDB 的技术能力与实践
数据库
步行cgn1 小时前
MyBatis Error evaluating expression ‘ids‘. Return value (3) was not iterable 错误详
java·后端
xiaohebang1 小时前
流失预测模型设计:行为特征分析算法选型
大数据·数据结构·经验分享
l1258652 小时前
# RAG重排序实战:硅基流动bge-reranker-v2-m3在线API vs 本地CrossEncoder,一篇讲透两种方案
数据库·人工智能·python·深度学习·算法·机器学习·langchain