news 2026/8/16 5:08:40

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Spark与Kyuubi(2)】从一条 JDBC 查询开始,看懂 STS 为什么撑不住,以及 Kyuubi 为什么能解

很多人对 Spark Thrift Server(STS)的印象是:

“能跑,但一多用户就出问题。”

但很少有人从一条 SQL 的完整生命周期,把问题说清楚。

这篇文章只做两件事:

  1. JDBC → Driver → Executor → YARN的完整调用链,按时间顺序拆开
  2. 用同一条链路,解释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 字符串 ↓ Parser(ANTLR)→ Unresolved Logical Plan ↓ Analyzer(查 Catalog,绑定表/列) ↓ Catalyst Optimizer(RBO / CBO) ↓ SparkPlanner → Physical Plan(DAG)

然后进入调度层:

DAGScheduler └── 按 Shuffle 切 Stage TaskScheduler └── 把 Task 封装成对象,等待 Executor

注意一个关键事实:

这些步骤,100% 发生在一个 Driver JVM 里,而且是所有用户共享这一个 JVM。


3️⃣ Executor:劳工,但不认识“用户”

Driver 向 YARN 申请到 Container 后,Executor 启动。

Executor 内部:

  • 接收 Task
  • 读 Parquet / HDFS
  • 做 Aggregate
  • Shuffle Write / Shuffle Read

Executor 只知道一件事:

“Driver 让我算这个 Task。”

它不知道:

  • 这是谁发的 SQL
  • 属于哪个部门
  • 该不该限制资源

4️⃣ YARN:只认识 Application,不认识 SQL

在 YARN 眼里,整个 STS 是:

一个 Application ├── 一个用户(spark / hive) ├── 一个 Queue ├── 一组 Container(Driver + Executors)

无论你背后有 1 个用户还是 100 个用户,YARN 看到的信息完全不变。


5️⃣ 结果回流:Driver 再当一次中转站

SQL 执行完:

  • 小结果:collect()回 Driver
  • Driver 通过 Thrift 一行行发给 JDBC 客户端
  • 大结果:写 HDFS,再让客户端读

Driver 同时是:

  • 调度器
  • 编译器
  • 结果缓冲区

把这条链画成一句话

JDBC 连接很多 ↓ 同一个 Driver 编译 + 调度 ↓ 同一组 Executor 计算 ↓ YARN 只看到一个 App

所有问题,都长在这条链上。

二、STS 的 7 个问题,本质都是“链上断点”

断点位置问题表现
所有 Session → 一个 Driver共享 Driver,用户互相影响
Driver串行调度高并发压垮 Driver
Executor 共享一个烂 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 Server

BI 连接的是 Kyuubi:

jdbc:hive2://kyuubi-host:10009

Kyuubi Server 收到后:

  • 解析用户名 / 组(LDAP / Kerberos / Ranger)
  • 决定这个用户属于哪个 Engine Pool
  • 找已有 Engine,或拉起一个新的

👉这一步,STS 没有。


2️⃣ Engine = 专属 Driver

如果这是用户第一次连接:

  • Kyuubi 用spark-submit启动一个 Spark Application
  • 这个 App 里运行KyuubiSparkEngine
  • Engine 内部:
    • 有自己的 Driver
    • 有自己的 Executor
    • 向 YARN 注册成一个独立 Application

现在链路变成:

用户 A 的 SQL → Engine A(Driver A) 用户 B 的 SQL → Engine B(Driver B)

3️⃣ Driver 内:和 STS 一模一样,但范围变小了

Engine 内部的 Driver,做的事和 STS 一样:

  • 解析 SQL
  • 优化
  • 切 Stage
  • 调度 Task

区别是:

这个 Driver 只服务一个用户 / 一个组。


4️⃣ Executor:终于可以“认人”了 (资源隔离,不同用户会调度到不同的运行资源)

因为 Engine 是独立的 Spark App:

  • 每个 Engine 有自己专属的 Executor
  • 这些 Executor 只跑这个 Engine 的 Task

YARN 看到的是:

App1 → 用户 A → Queue A App2 → 用户 B → Queue B

👉队列、资源、权限,第一次对齐到“人”。


5️⃣ 结果回流:网关只做转发

Engine 把结果返回给 Kyuubi Server:

  • Kyuubi Server 不计算
  • 不编译 SQL
  • 不维护物理计划
  • 只负责 Thrift RPC 转发

Driver 不再是“接入 + 调度 + 结果中转”三合一。


六、逐条对照:Kyuubi 怎么解决 STS 的问题

1️⃣ STS:所有用户共享 Driver

Kyuubi:一人一个 Engine

  • 用户 A 的烂 SQL 只打爆自己的 Driver
  • 用户 B 完全无感

2️⃣ STS:Driver 高并发瓶颈

Kyuubi:压力被 Engine 水平拆分

  • 原来:100 个连接 → 1 个 Driver
  • 现在:100 个连接 → 10 个 Engine,每个 10 个连接

Driver 不再是全局瓶颈。


3️⃣ STS:用户资源不隔离

Kyuubi:Executor 天然隔离

  • 一个 Engine OOM → 只杀这个 Engine
  • 其他 Engine 的 Executor 不受影响

4️⃣ STS:一挂全挂

Kyuubi:Engine 是独立 Application

  • 某个 Engine Driver 挂了
  • Kyuubi Server 还在
  • 其他用户继续用
  • 这个用户下次连,自动拉新 Engine

5️⃣ STS:YARN 队列控制不精细

Kyuubi:每个 Engine 是独立 App

可以配置:

user A → queue.finance user B → queue.bi

Kyuubi 在spark-submitEngine 时,直接带:

--queue queue.finance

YARN 第一次“看见用户”。


6️⃣ STS:生命周期耦合

Kyuubi:Engine 可自动销毁

Kyuubi 支持:

  • 空闲 Engine 自动退出
  • SQL 结束 → Executor 回收(Dynamic Allocation)

App 生命周期 ≈ 用户活跃周期,而不是“永远活着”。


7️⃣ STS:无法按租户治理

Kyuubi:天然多租户模型

  • 可以统计:每个 Engine 的 CPU / 内存
  • 可以限制:单用户最大 Engine 数
  • 可以限制:单个 Engine 的 core / memory

治理从“猜”变成“可观测”。


七、一句话对比两条链路

STS 的链路

JDBC ↓ 一个 Driver(所有用户) ↓ 一组 Executor(所有人) ↓ YARN:一个 App

Kyuubi 的链路

JDBC ↓ 无状态网关 ↓ 按用户路由 ↓ 专属 Driver ↓ 专属 Executor ↓ YARN:多个 App

八、本质差异不是“功能”,而是“抽象”

STS 的假设是:

Spark 是一个计算引擎,我给它加个 JDBC 壳。

Kyuubi 的假设是:

数据服务应该是多租户系统,Spark 只是计算内核。

所以:

  • STS 把 Spark 当成“服务进程”
  • Kyuubi 把 Spark 当成“可被编排的计算单元”

九、最后给架构师的一句话

如果你今天还在用 STS,而且:

  • 用户数 > 10
  • 有部门隔离诉求
  • 有 SLA 要求

那么问题从来不是:

“STS 参数怎么调?”

而是:

“你是否需要一个真正的多租户 SQL Gateway。”

Kyuubi 的答案,不在功能列表里,而在那条被拆开的 Driver 链路上。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/16 5:06:44

ESP32与舵机驱动:从零构建四足机器狗的硬件开源实践指南

最近在整理工作室的零件盒,翻出来一堆闲置的ESP32开发板、几个舵机和一块小小的OLED屏幕。看着这些散件,我突然意识到一个问题:我们玩硬件开源项目,很多时候热情都消耗在了“找齐零件”和“搭建环境”这两件事上。一个项目&#x…

作者头像 李华
网站建设 2026/8/16 5:05:39

OpenClaw数据同步框架:从架构设计到工程实践的深度解析

1. 从“黑盒”到“白盒”:为什么我们需要解读OpenClaw第一次接触OpenClaw这个名字,你可能会觉得它有点神秘,甚至有点“黑盒”的感觉。它不像Spring Boot、Vue.js那样,名字本身就暗示了它的功能。OpenClaw,直译是“开放…

作者头像 李华
网站建设 2026/8/16 5:04:44

Kali Linux国内镜像源配置:原理、实操与问题排查全指南

1. 项目概述:为什么Kali换源是每个安全从业者的必修课如果你刚接触Kali Linux,或者已经用它进行了一段时间的渗透测试和安全研究,那么“换源”这个词你肯定不陌生。它听起来像是一个简单的系统维护操作,但背后却直接关系到你的工作…

作者头像 李华
网站建设 2026/8/16 5:04:41

VSCode配置云端同步与便携化:告别重装系统后的重复配置

这次我们来看一个解决 VSCode 配置同步与迁移痛点的实用方案。对于开发者而言,重装系统、更换电脑后,最繁琐的莫过于重新配置开发环境,尤其是像 VSCode 这样高度依赖扩展、主题和用户设置的编辑器。传统的配置备份方法零散且容易遗漏&#xf…

作者头像 李华
网站建设 2026/8/16 4:56:09

IP5383至为芯支持2路C口45W双向快充的移动电源方案芯片

英集芯IP5383是一个应用于移动电源,充电宝等方案的移动电源管理SOC芯片。内置H桥功率MOS,单电感同步双向升降压。单口最大45W充放电,充电电流最高8A。支持2-5节串锂电池配置,集成PD、QC、UFCS等主流快充协议。提供USB-A1双向Type-…

作者头像 李华