Apache Kyuubi 1.8 特性解读
- 1.Apache Kyuubi 简介
- 2.场景扩展 —— 在线分析,离线跑批
- 3.流式增强 —— 流批一体,面向未来
- 4.企业特性 —— 行业沉淀,持续打磨
- 5.开源社区 —— 开放包容,合作共赢
本文来自于 Apache Kyuubi PMC Member 潘成 的分享。内容围绕 Apache Kyuubi 最新版本 1.8 的特性与改进,主要分为以下部分:
- 场景扩展 —— 在线分析,离线跑批
- 流式增强 —— 流批一体,面向未来
- 企业特性 —— 行业沉淀,持续打磨
- 开源社区 —— 开放包容,合作共赢
1.Apache Kyuubi 简介
Apache Kyuubi 是一个构建在 Spark、Flink、Trino 等计算引擎之上的,分布式、多租户的企业级大数据网关,致力于在 Lakehouse 之上提供 Serverless SQL 服务。
Kyuubi 支持多种类型的工作负载。典型的使用场景包括:用户可以使用 JDBC / BeeLine 以及各种 BI 工具,连接 Kyuubi 进行交互式的数据分析;使用 RESRful API 向 Kyuubi 提交 SQL / Python / Scala / Jar 批作业。
Kyuubi 是一个分布式、多租户的企业级大数据网关,Kerberos 作为 Hadoop 生态组件的事实认证标准,Kyuubi 对其做了深度适配,同时 Kyuubi 也支持企业常用的 LDAP 安全认证协议。特别的,Kyuubi 支持同时启用 Kerberos 和 LDAP 认证,客户端可以选择任一种认证方式接入 Kyuubi。
除了作为网关的主体功能外,Kyuubi 还提供一系列可以独立使用 Spark 插件,可提供如小文件治理、Z-Order、SQL 血缘提取、限制查询数据扫描量等企业级功能。
2.场景扩展 —— 在线分析,离线跑批
使用 Kyuubi Thrift API 搭配 Spark 计算引擎,取代 HiveServer2 或者 Spark Thrift Server 是 Kyuubi 最早专注的场景,也是目前最成熟、生产案例最多的使用方式。
Kyuubi Server 是一个轻量级的常驻服务,不参与计算,负责按需拉起计算引擎,并通过内部 RPC 协议与其通信,以 Spark 引擎为例,Kyuubi Spark Engine 即一个 Spark Application。
在交互式会话中,Kyuubi 最重要的两个概念是 Session 和 Operation,分别与 JDBC 中的 Connection 和 Statement,以及 Spark 中 SparkSession 和 QueryExecution 概念对应。
如上是一段使用 JDBC 驱动连接 Kyuubi 执行 SQL 查询的代码,可以清晰地看到客户端 JDBC 调用与 Spark 引擎侧之间的对应关系;特别的,客户端通过 JDBC ResultSet 拉取结果集时,会以小批次的方式从 Spark Driver 经过 Kyuubi Server 回传,确保 Kyuubi Server 不会有较大的内存压力;在 1.7 版本中,Kyuubi 支持了基本 Apache Arrow 的结果集序列化方式,大幅提升了大结果集场景的传输效率,该特性在 1.8 中得到了进一步改进,优化了与结果集增量拉取组合使用时的性能。
在企业级的 Spark 应用中,Jar / PySpark 任务是不可回避的场景。自 1.6 版本起,在 eBay 的主导下,Kyuubi 引入了批会话(Batch Session)的概念,支持了 Jar 任务的提交,同时在实现上复用了交互式会话中的 Session、Operation 概念;在 1.8 版本中,通过引入了基于数据库的多级队列,批任务并发调度能力得到显著增强。
在批会话中,一个 Spark Application 即对一个一个 Batch Session,当用户发起提交任务请求时,Kyuubi Server 创建一个 Batch Session 并将其放置到 Backend 线程池队列中,此处即将线程池作为一个简易的内存队列,控制提交并发;当 Backend 线程池接收该任务后,调用 spark-submit
提交,并通过 YARN / K8s API 轮询 Spark Application 状态直至作业结束。
批任务会话目前仅提供 RESTful API(以及基于此 API 的 kyuubi-ctl
命令行工具),与交互式会话中常用的基于 TCP 长链接的 Thrift-Binary 协议不同,RESTful API 是基于 HTTP 短链接的协议,在典型的高可用部署中,多台 Kyuubi 服务实例部署在 Load Balancer 之后,客户端发起的请求则可能会被转发到不同的 Kyuubi 服务实例,因此直接类比交互式会话,将 Session、Operation 状态保存在内存里是不可行的行为。
Kyuubi 通过引入 Server 间的请求转发和数据库持久化存储状态解决了上述 HA 场景下的问题。数据库的引入同时支持了 Kyuubi Server 停机重启后的 Batch Session 状态恢复,是滚动升级的必要条件。
在初版的批会话(后续简称 Batch V1)实现中,我们发现一些可以改进的空间:
-
spark-submit
会瞬时(持续约 30s)消耗大量 CPU 和 IO 资源,突发的高并发任务提交将对 Kyuubi Server 服务所在机器或容器有极高的资源要求。 - 高并发提交场景下,当单台 Kyuubi Server 出现资源瓶颈时,水平扩容无法快速转移负载到新增节点上。
-
spark-submit
与后续 Application 状态轮询共享线程,spark-submit
仅在初始提交的数十秒内有较大的资源消耗,后续 Application 状态轮询资源消耗极低;使用同一个 Backend 线程池控制线程数从而控制 Batch Session 的并发,无法做到精细化的资源控制:较小的线程数造成单台 Kyuubi 节点承接的 Batch 作业并发度较低;较大的线程数在面临瞬间多个spark-submit
同时执行时可能发生资源耗尽。 - 无法做到全局 FIFO 调度和全局优先级调度。
在 1.8 中,我们在 Batch V1 的基础上,针对上述问题做了改进,提出 Batch V2 设计,其核心变化是,在原有 Backend 线程池队列的基础上,新增两个队列:
- 基于数据库的队列:用户向 Kyuubi Server 发起 Batch 任务提交后,入队数据库队列即返回。
-
Submitter 线程池队列:每个 Kyuubi Server 有一个 Submitter 线程池,每个线程专门负责从数据库队列中拾取任务,交由 Backend 线程池做
spark-submit
提交,该线程在 Spark Application 进入 RUNNING 或者退出状态后释放以继续处理数据库队列中的其他任务,从而实现对spark-submit
进程并发控制。 -
原有的 Backend 线程池队列:得益于前置 Submitter 线程池对
spark-submit
进程并发度的控制,此线程池可以设置较大的线程数,用于获取对 Spark Application 状态的拉取。
在 Batch V2 模式下,Kyuubi Server 的稳定性大幅提升,尤其在批量调度 ETL 作业场景下,可以从容地应对瞬间大量批任务的提交;当 Kyuubi 提交 Spark 作业的速度跟不上造成数据库队列堆积时,扩容 Kyuubi 集群后,新加入的 Kyuubi 节点启动后立即承接负载;同时,得益于数据库队列的引入,Batch V2 支持全局作业 FIFO 和优先级调度。
在落地 Spark on K8s 场景中,我们还发现频繁地通过查询 Spark Driver Pod 状态来获取 Spark Application 状态会对 API Server 造成巨大压力,随后我们改进方案,通过使用 Informer 在 Kyuubi Server 侧维护一份 Spark Driver Pod 状态列表而避免频繁的向 API Server 发起查询请求,显著地降低 API Server 的压力。
Kyuubi Batch RESTful API 提供了一个 REST SDK 供用户以编程的方式集成使用;同时也提供了一个 kyuubi-ctl
命令行工具,可以配合 yaml
文件提交和管理 Batch 作业。如上是一个使用 kyuubi-ctl
向 Kyuubi 提交 SparkPi 批作业的案例。
3.流式增强 —— 流批一体,面向未来
架构上,Kyuubi 由 Server 和 Engine 两个组件构成。其中 Server 是一个轻量级常驻服务,而 Engine 是按需启停的计算引擎。客户端发起连接后,Kyuubi Server 会根据路由规则寻找合适的 Engine,若没有命中,则会主动拉起一个新的计算引擎,当计算引擎闲置一段时段后,会主动退出释放资源。
对于交互会话,Kyuubi 创造性地提出 引擎共享级别,内置的四个共享级别:CONNECTION
、USER
、GROUP
、SERVER
,隔离性依次增强,共享程度依次降低,搭配使用可以满足多种负载场景。
Kyuubi 的设计上是天然适配多计算引擎的,我们可以相对容易的扩展接入其他引擎。Flink 是当前最成熟的流式计算引擎,Kyuubi 早在 1.4 就实现了第一版的 Flink Engine,并持续改进,在最新的 1.8 版本中,来自网易互娱的贡献者对 Flink Engine 做了重大重构,功能得到了显著增强。
在 1.8 中,Kyuubi 新增支持了 Flink YARN Application Mode,该模式与 Spark Cluster 模式类似,将 SQL 解析、执行计划生成等工作从 Kyuubi Server 节点的 Flink Client 进程转移到了 Application Master 中,从而将所有计算资源纳入 YARN 管控,大幅降低了 Kyuubi Server 节点的负载;搭配 Kyuubi 的引擎共享级别使用,可以获得极致的弹性。
Kyuubi 始终遵循 Upstream First 的原则,紧跟 Flink 社区最新动向,Kyuubi 1.8 适配了 Flink 1.16~1.18 最近三个版本。在具体实现上,Kyuubi 最大程度复用了 Flink SQL Gateway 模块的代码。
此外我们还对 Flink 时间类型做了更完整的覆盖,利好 Flink CDC 场景的用户;通过改进 Kyuubi 的结果集传输框架,支持了拉取 Flink 无边界流结果集。
4.企业特性 —— 行业沉淀,持续打磨
基于历史原因,Spark 内置的 Hive 连接器没有被实现为一个标准的 Data Source 组件,高度耦合的实现也使得 Spark 无法轻易连接多个 Hive 数仓做联邦查询和跨集群写入。
来自百度的开发者向 Kyuubi 社区贡献了基于 Spark DataSource V2 API 的 Hive 连接器,该连接器可以实现 Spark 对多个 Hive、HDFS 集群的联邦查询、写入。在 Kyuubi 1.8 中得到了一系列的改进和错误修复,包括对 Hadoop Delegation Token 的支持、对 Hive Serde 分区表的写入错误修复等。
安全是企业级应用中一个十分重要的话题,同时 Kerberos 是 Hadoop 生态认证机制的事实标准;Kyuubi 作为一个企业级大数据网关,Kyuubi 在 Kerberos 支持上做了深度适配,支持 Kerberos / LDAP 同时启用,客户端可以选择任何一种方式认证;支持 Hadoop 用户代理机制,在保证安全的同时,省去海量用户 keytab 的管理;支持 Hadoop Delegation Token 续期,满足 Spark 常驻任务的认证需求等。
Kyuubi 不乏一些来自一些金融券商和欧美企业的社区用户和贡献者,他们对安全有着更为极致的要求,比如服务组件间的内部通信也需要加密,支持权限控制和 SQL 审计等,Kyuubi 对此类场景亦可胜任。
Kyuubi 同时也简化了客户端侧的 Kerberos 认证过程;对于非技术开发人员,接入启用 Kerberos 认证的服务流程繁琐,学习 Kerberos 和 Hadoop 认证机制有陡峭的门槛;例如,用户若期望使用 Hive JDBC 驱动,在 Windows 系统上使用 DBeaver 连接启用 Kerberos 认证的 Kyuubi 服务,需要如上图左侧所示的 5 个步骤;而使用 Kyuubi JDBC 驱动,则简化为 2 个步骤,只需配置 krb5.ini
,并且在 JDBC URL 中指定客户端 principal
与 keytab
,以及服务端 principal
即可,大幅降低了用户学习和接入成本。
在 Kyuubi 1.8 中,来自 Cisco 的开发者向 Kyuubi 贡献了全新的 Web UI,可以满足对 Engine、Session、Operation 资源的查看和管理。
5.开源社区 —— 开放包容,合作共赢
Kyuubi 项目自诞生以来已经走过了 5 年,经历了网易自主开源、Apache 孵化阶段,社区不断壮大,最终在 2023 年正式毕业,成为了 Apache *项目。
社区始终秉持 Upstream First 的原则,紧跟开源社区上游生态,及时跟进上游组件新版本。在 Kyuubi 1.8 中新增了对 Java 17、Scala 2.13 的适配,并对 Java 21 做了初步的验证;主体功能以及所有插件完整兼容 Spark 3.1~3.4,初步兼容 Spark 3.5;基于 Flink 1.16~1.18 做了充分验证;支持 Hive 最新版本 3.1。
Kyuubi 已被多个公有云、海内外多个行业的头部企业所采纳作为 SQL 网关,我们也看到越来越多的用户在 AWS、GCP、Azure 上独立部署 Kyuubi 使用。
如果你也在使用Kyuubi,或者正在调研 Kyuubi,欢迎前往 GitHub 页面分享你的用户场景和案例~
???? https://github.com/apache/kyuubi/discussions/925
Apache Kyuubi 是一个社区驱动的开源项目。Kyuubi 核心开发者团队是多元化的,他们来自海内外的各个行业的企业,在 Apache Way 的指引下,彼此友好协作,致力于将 Kyuubi 打造成可持续的优秀开源项目。
如果你也对参与 Kyuubi 开发感兴趣,欢迎参加2023 Kyuubi 开发者活动,与优秀的开发者一起成长!
???? https://github.com/apache/kyuubi/issues/5357
现场问答
Q:我们使用共享的 Kyuubi Engine 为用户提供查询服务,在使用过程中,我们发现一些用户的大查询会影响 Engine 的稳定性,对其他查询造成影响甚至导致 Engine OOM,针对这种场景,有什么解决方案吗?
A:在用户分享的实践案例中,有两种常用的解决方案:
- HBO,即 History-based Optimization。构建独立的服务,收集并分析任务的特征,对于周期性的调度任务,在任务执行前,基于历史执行信息做出判断,将大查询的会话切换到 CONNECTION 隔离级别,使用独立的计算资源,降低对其他作业的影响。
- 将选择暴露给用户。例如在 Bilibili 的分享中提到,在面向用户的 SQL 查询工作台中,给出一个 “大查询” 的选项,对于有一定经验的数据分析师,可以提前预料到自己的查询可能会对 Engine 稳定性造成影响,则主动使用独立的计算资源以规避。