资讯动态

【Spark与Kyuubi(2)】从一条 JDBC 查询开始,看懂 STS 为什么撑不住,以及 Kyuubi 为什么能解

发布时间:2026/8/16 5:08:45 来源:尧图企业网站定制
很多人对 Spark Thrift ServerSTS的印象是“能跑但一多用户就出问题。”但很少有人从一条 SQL 的完整生命周期把问题说清楚。这篇文章只做两件事把JDBC → Driver → Executor → YARN的完整调用链按时间顺序拆开用同一条链路解释Kyuubi 是怎么把 STS 的 7 个结构性问题逐个拆掉的一、一条 SQL 在 STS 里到底走了什么路假设你从 BI 工具点了一下刷新SELECTdept,sum(amount)FROMt_orderGROUPBYdept;1️⃣ JDBC 层入口很简单但“太集中”BI 工具通过 JDBC 连接jdbc:hive2://sts-host:10000背后发生的是一个 Thrift 连接被 STS 的HiveServer2接收STS 内部维护一个 JDBC Session用户身份、临时视图但所有 Session 都落在同一个 JVM 里 到这里第一个隐患已经埋下连接可以很多但大脑只有一个。2️⃣ Driver大脑开始干活这条 SQL 进入 Driver顺序非常固定SQL 字符串 ↓ ParserANTLR→ Unresolved Logical Plan ↓ Analyzer查 Catalog绑定表/列 ↓ Catalyst OptimizerRBO / CBO ↓ SparkPlanner → Physical PlanDAG然后进入调度层DAGScheduler └── 按 Shuffle 切 Stage TaskScheduler └── 把 Task 封装成对象等待 Executor注意一个关键事实这些步骤100% 发生在一个 Driver JVM 里而且是所有用户共享这一个 JVM。3️⃣ Executor劳工但不认识“用户”Driver 向 YARN 申请到 Container 后Executor 启动。Executor 内部接收 Task读 Parquet / HDFS做 AggregateShuffle Write / Shuffle ReadExecutor 只知道一件事“Driver 让我算这个 Task。”它不知道这是谁发的 SQL属于哪个部门该不该限制资源4️⃣ YARN只认识 Application不认识 SQL在 YARN 眼里整个 STS 是一个 Application ├── 一个用户spark / hive ├── 一个 Queue ├── 一组 ContainerDriver Executors无论你背后有 1 个用户还是 100 个用户YARN 看到的信息完全不变。5️⃣ 结果回流Driver 再当一次中转站SQL 执行完小结果collect()回 DriverDriver 通过 Thrift 一行行发给 JDBC 客户端大结果写 HDFS再让客户端读Driver 同时是调度器编译器结果缓冲区把这条链画成一句话JDBC 连接很多 ↓ 同一个 Driver 编译 调度 ↓ 同一组 Executor 计算 ↓ YARN 只看到一个 App所有问题都长在这条链上。二、STS 的 7 个问题本质都是“链上断点”断点位置问题表现所有 Session → 一个 Driver共享 Driver用户互相影响Driver串行调度高并发压垮 DriverExecutor 共享一个烂 SQL 拖死所有人YARN 只看 App队列、用户无法精细控制Driver 单 JVM一挂全挂Executor 生命周期 AppSQL 结束资源不释放无用户维度无法按租户治理STS 不是“没调好”而是这条链路从设计上就不是一个多租户服务。三、Kyuubi 进来后链路被改成了什么Kyuubi 的核心思想可以用一句话概括不在一个 Driver 里服务所有用户而是让每个用户或租户拥有自己的 Driver。它把原来的“单点大脑”拆成两层。四、Kyuubi 的新链路先看架构分层JDBC Client ↓ Kyuubi Server无状态网关 ↓ ──────── 按用户 / 租户路由 ─────── ┌───────────────┐ │ Spark Engine │ ← 一个 Spark App │ (Driver A) │ └───────────────┘ ┌───────────────┐ │ Spark Engine │ │ (Driver B) │ └───────────────┘Kyuubi Server只干接入、认证、路由Spark Engine就是一个 Spark Application等价于一个 STS但只服务一部分人五、同一条 SQL在 Kyuubi 里怎么走还是那条 SQL。1️⃣ JDBC → Kyuubi ServerBI 连接的是 Kyuubijdbc:hive2://kyuubi-host:10009Kyuubi Server 收到后解析用户名 / 组LDAP / Kerberos / Ranger决定这个用户属于哪个 Engine Pool找已有 Engine或拉起一个新的这一步STS 没有。2️⃣ Engine 专属 Driver如果这是用户第一次连接Kyuubi 用spark-submit启动一个 Spark Application这个 App 里运行KyuubiSparkEngineEngine 内部有自己的 Driver有自己的 Executor向 YARN 注册成一个独立 Application现在链路变成用户 A 的 SQL → Engine ADriver A 用户 B 的 SQL → Engine BDriver B3️⃣ Driver 内和 STS 一模一样但范围变小了Engine 内部的 Driver做的事和 STS 一样解析 SQL优化切 Stage调度 Task区别是这个 Driver 只服务一个用户 / 一个组。4️⃣ Executor终于可以“认人”了 (资源隔离不同用户会调度到不同的运行资源)因为 Engine 是独立的 Spark App每个 Engine 有自己专属的 Executor这些 Executor 只跑这个 Engine 的 TaskYARN 看到的是App1 → 用户 A → Queue A App2 → 用户 B → Queue B队列、资源、权限第一次对齐到“人”。5️⃣ 结果回流网关只做转发Engine 把结果返回给 Kyuubi ServerKyuubi Server 不计算不编译 SQL不维护物理计划只负责 Thrift RPC 转发Driver 不再是“接入 调度 结果中转”三合一。六、逐条对照Kyuubi 怎么解决 STS 的问题1️⃣ STS所有用户共享 DriverKyuubi一人一个 Engine用户 A 的烂 SQL 只打爆自己的 Driver用户 B 完全无感2️⃣ STSDriver 高并发瓶颈Kyuubi压力被 Engine 水平拆分原来100 个连接 → 1 个 Driver现在100 个连接 → 10 个 Engine每个 10 个连接Driver 不再是全局瓶颈。3️⃣ STS用户资源不隔离KyuubiExecutor 天然隔离一个 Engine OOM → 只杀这个 Engine其他 Engine 的 Executor 不受影响4️⃣ STS一挂全挂KyuubiEngine 是独立 Application某个 Engine Driver 挂了Kyuubi Server 还在其他用户继续用这个用户下次连自动拉新 Engine5️⃣ STSYARN 队列控制不精细Kyuubi每个 Engine 是独立 App可以配置user A → queue.finance user B → queue.biKyuubi 在spark-submitEngine 时直接带--queue queue.financeYARN 第一次“看见用户”。6️⃣ STS生命周期耦合KyuubiEngine 可自动销毁Kyuubi 支持空闲 Engine 自动退出SQL 结束 → Executor 回收Dynamic AllocationApp 生命周期 ≈ 用户活跃周期而不是“永远活着”。7️⃣ STS无法按租户治理Kyuubi天然多租户模型可以统计每个 Engine 的 CPU / 内存可以限制单用户最大 Engine 数可以限制单个 Engine 的 core / memory治理从“猜”变成“可观测”。七、一句话对比两条链路STS 的链路JDBC ↓ 一个 Driver所有用户 ↓ 一组 Executor所有人 ↓ YARN一个 AppKyuubi 的链路JDBC ↓ 无状态网关 ↓ 按用户路由 ↓ 专属 Driver ↓ 专属 Executor ↓ YARN多个 App八、本质差异不是“功能”而是“抽象”STS 的假设是Spark 是一个计算引擎我给它加个 JDBC 壳。Kyuubi 的假设是数据服务应该是多租户系统Spark 只是计算内核。所以STS 把 Spark 当成“服务进程”Kyuubi 把 Spark 当成“可被编排的计算单元”九、最后给架构师的一句话如果你今天还在用 STS而且用户数 10有部门隔离诉求有 SLA 要求那么问题从来不是“STS 参数怎么调”而是“你是否需要一个真正的多租户 SQL Gateway。”Kyuubi 的答案不在功能列表里而在那条被拆开的 Driver 链路上。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价