共计 7609 个字符,预计需要花费 20 分钟才能阅读完成。
本文来自 eBay 软件工程师、Apache Kyuubi PPMC Member 王斐在 Apache SeaTunnel & Kyuubi 联结 Meetup 的分享,介绍了 Apache Kyuubi(Incubating)的根本架构和应用场景,eBay 基于本身的需要对 Kyuubi 所做的加强,以及如何基于 Kyuubi 构建 Unified & Serverless Spark Gateway。
Kyuubi 是什么
首先介绍一下 Kyuubi。Kyuubi 是一个分布式的 Thrift JDBC/ODBC server,反对多租户和分布式等个性,能够满足企业内诸如 ETL、BI 报表等大数据场景的利用。我的项目由网易数帆发动,曾经进入 Apache 基金会孵化,目前的次要方向是依靠自身的架构设计,围绕各类支流计算引擎,打造一个 Serverless SQL on Lakehouse 服务,目前反对的引擎有 Spark、Flink、Trino(也就是 Presto)。我明天的主题是围绕 Kyuubi 和 Spark, 对于其它计算引擎这里不再开展。
对于 Spark,Kyuubi 有 HiveServer2 的 API,反对 Spark 多租户,而后以 Serverless 的形式运行。HiveServer2 是一个经典的 JDBC 服务,Spark 社区也有一个相似的服务叫做 Spark Thrift Server。这里介绍一下 Spark Thrift Server 和 Kyuubi 的比照。
Spark Thrift Server 能够了解为一个独立运行的 Spark app,负责接管用户的 SQL 申请, SQL 的编译以及执行都会在这个 app 外面去运行,当用户的规模达到肯定的级别,可能会有一个单点瓶颈。
对于 Kyuubi,咱们能够看左边这张图,有一个红色的用户和一个蓝色的用户,他们别离有一个红色的 Spark app 和一个蓝色的 Spark app,他们的 SQL 申请进来之后,SQL 的编译和执行都是在对应的 app 之上进行的,就是说 Kyuubi Server 只进行一次 SQL 申请的直达,把 SQL 间接发送给背地的 Spark app。
对于 Spark Thrift Server 来讲,它须要保留后果以及状态信息,是有状态的,所以不能反对 HA 和 LB。而 Kyuubi 不保留后果,简直是一个无状态的服务,所以 Kyuubi 反对 HA 和 LB,咱们能够减少 Kyuubi Server 的个数来满足企业的需要。所以说 Kyuubi 是一个更好的 Spark SQL Gateway。
Kyuubi 的架构分为两层,一层是 Server 层,一层是 Engine 层。Server 层和 Engine 层都有一个服务发现层,Kyuubi Server 层的服务发现层用于随机抉择一个 Kyuubi Server,Kyuubi Server 对于所有用户来共享的。Kyuubi Engine 层的服务发现层对用户来说是不可见的,它是用于 Kyuubi Server 去抉择对应的用户的 Spark Engine,当一条用户的申请进来之后,它会随机抉择一个 Kyuubi Server,Kyuubi Server 会去 Engine 的服务发现层抉择一个 Engine,如果 Engine 不存在,它就会创立一个 Spark Engine,这个 Engine 启动之后会向 Engine 的服务发现层去注册,而后 Kyuubi Server 和 Engine 之间的再进行一个 Internal 的连贯,所以说 Kyuubi Server 是所有用户共享,Kyuubi Engine 是用户之间资源隔离。
Kyuubi 反对一些 Engine 的共享级别,它是基于隔离和资源之间的均衡。在 eBay 咱们次要应用到了 USER 和 CONNECTION 级别。首先对于 CONNECTION 级别,对于用户的每次连贯都会发明一个新的 app,也就是一个 Kyuubi Engine,实用于 ETL 场景,ETL 的 workload 比拟高,须要一个独立的 app 去执行;对于 USER 级别,咱们能够看到这里有两个 user,一个叫 Tom,一个叫 Jerry,Tom 的两个 client 连贯 Kyuubi Server,会连贯到同一个属于 Tom 的 Kyuubi Engine,USER 级别实用于 ad-hoc 场景,就是对于同一个用户所有的连贯都会到同一个 Kyuubi Engine 去执行,而对 Jerry 的所有申请都会到 Jerry 的 Kyuubi Engine 去执行。
对 USER 共享级别 Kyuubi 做了一些增强,引入了一个 Engine POOL 的概念,就像编程外面的线程池一样,咱们能够创立一个 Engine 的 pool,pool 外面有编号,比如说这里 Tom 创立了两个 pool,叫做 pool- a 和 pool-b,编号为 pool-a-0,pool-a-1,如果说在客户端申请的时候间接指定这个 pool 的名字,Kyuubi server 会从这个 pool 外面去随机抉择一台 Engine 执行;如果 Tom 在申请的时候不仅指定 pool 的名字,还指定了这个 Engine 在 pool 外面的索引,比如说这里指定 pool-b-0,Kyuubi Server 会从这个 pool- b 外面抉择编号为 0 的 Engine 去做计算。对应的参数为kyuubi.engine.share.level.subdomain
.
这在 eBay 外面为 BI 工具集成提供了很大的便当,因为 eBay,每个分析师团队可能用同一个账号去执行数据分析,BI 工具会依据用户的 IP 去创立一个 Kyuubi Engine,因为每个分析师须要的参数配置可能是不一样的,比如说他们的内存的配置是不一样的,BI 工具就能够创立一个这样的 engine pool,而后保留用户的 IP 和所创立 Engine 索引的一个 mapping,而后在这个用户的申请过去的时候,依据 BI 工具保留的 IP 映射关系,去找到该用户所创立的 Engine,或者是说一个团队外面很多人应用一个 pool,能够预创立许多 Spark app,让这一个组外面的人能够随机抉择一个 Engine 去做执行,这样能够加大并发度。同时也能够作为 USER 共享级别上面的一个标签用于标注该引擎的用处,比如说咱们能够给 beeline 场景和 java JDBC 利用应用场景创立 USER 共享级别下的不同 engine pool, 在不同应用场景下应用不同的 engine pool, 相互隔离。
后面提到了不同的 Engine 共享级别,有的是为每个连贯创立一个 Spark App,有的是为一个用户创立一个或者多个 Kyuubi Engine,你可能会放心资源节约,这里讲一下 Kyuubi Engine 对资源的动静治理。首先,一个 Kyuubi Engine,也就是一个 Spark app,分为 Spark driver 和 Spark executor,对于 executor,Spark 自身就有一个 executor dynamic allocation 机制,它会依据以后 Spark job 的负载来决定是否向集群申请更多的资源,或者是说将目前已申请的资源返还给集群。所说咱们在 Kyuubi Server 层加一些限度,比方强制关上这个 executor dynamic allocation,并且把在闲暇时候最小的 executor 数量设为 0,也就是说当一个 app 十分闲暇的时候只有一个 driver 带运行,避免浪费资源。除了 executor 层的动静回收机制,Kyuubi 为 driver 层也加了资源回收机制。对于 CONNECTION 分享级别,Kyuubi Engine 只有在以后连贯才应用,当连贯敞开的时候 Spark driver 会间接被回收掉。对 USER 级别的共享,Kyuubi 有一个参数kyuubi.session.engine.idle.timeout
来管制 engine 的最长闲暇工夫,比如说咱们将闲暇工夫设置为 12 小时,如果 12 个小时之内都没有申请连贯到这个 Spark app 上,这个 Spark app 就会主动完结,防止资源节约。
Kyuubi 的应用场景
上面讲一下 Use Case。目前 Kyuubi 反对了 SQL 语言和 Scala 语言的执行,也能够把 SQL 和 Scala 写在一起去跑。因为 SQL 是一种十分用户敌对的语言,它能够让你不必理解 Spark 外部的原理,就能够应用简略的 SQL 语句去查问数据,然而它也有肯定的局限性;而 Scala 语言须要肯定的门槛,但它十分的灵便,咱们能够去写代码或者去操纵一些 Spark DataFrame API。
举一个例子,就是能够在一个 SQL 文件或者一个 notebook 外面去混合编程。首先用 SQL 语句创立了一张训练的数据表,在创立表之后通过 SET 语句把语言模式设为 Scala,而后开始用 Scala 去写代码,这里是用一个 kMeans 把训练数据进行解决,解决完之后把输入保留在一张表外面,再把语言模式切换到 SQL,持续用 SQL 去解决。这样十分不便,咱们能够联合 SQL、Scala 的长处,基本上能够解决数据分析外面的大部分的 case。咱们也在 Kyuubi JDBC 外面提供了一个十分敌对的接口,能够间接调用 KyuubiStatement::ExecuteScala
去执行 Scala 语句。
Kyuubi 在 eBay 的实际
eBay 需要背景
咱们 Hadoop team 治理了很多个 Hadoop 集群,这些集群散布在不同的数据中心,有不同的用处,有一套对立的基于 KDC 和 LDAP 的权限校验。
刚开始引入 Kyuubi 的时候,咱们就在想要为每个集群都部署一个 Kyuubi 服务吗?如果这样咱们可能要部署三四个 Kyuubi 服务,在降级的时候须要进行反复操作,治理起来很不不便,所以咱们就想是否可能用一套 Kyuubi 来服务多个 Hadoop 集群。
eBay 对 Kyuubi 的加强
下图就是咱们为这个需要所做的一些加强。首先,因为咱们是反对 KDC 和 LDAP 认证的,咱们就让 Kyuubi 同时反对 Kerberos 和 Plain 类型的权限认证,并对 Kyuubi Engine 的启动、Kyuubi 的 Beeline 做了些优化,而后咱们扩大了一些 Kyuubi 的 thrift API 反对上传下载数据。针对后面说的要用一个 Kyuubi 去拜访多个 Hadoop 集群,咱们加了一个 cluster selector 的概念,能够在连贯的时候指定参数,让申请路由到对应的集群。还有就是咱们也在欠缺 RESTfull API,曾经为 Kyuubi 反对了 SPNEGO 和 BASIC 的 RESTfull API 权限认证。此外咱们也在做 RESTfull API 去跑 SQL Query 和 Batch job 的一些工作。图中打编号的是曾经回馈社区的一些 PR。
这里讲一下 2、3、4,对 Kyuubi 的 Thrift RPC 的一些优化。首先因为 Thrift RPC 自身是针对 HiveServer2 来设计的,HiveServer2/Spark Thriftserver2 外面建设一个连贯是十分快的。而在 Kyuubi 外面建设一个连贯的话,首先要连贯到 Kyuubi Server,Kyuubi Server 要等到和远端的 Kyuubi Engine 建设连贯实现之后,能力把后果返回给客户端。
如果 Kyuubi Engine 一开始不存在,而且在启动 Kyuubi Engine 的时候因为资源问题,或者是有一些参数设置不对,比如说他设置了有效的spark.yarn.queu
,导致呈现谬误的话,两头可能会有一分钟或者说几十秒的提早,客户端要始终等,在等的过程中也没有任何的 log 返回给客户端。咱们就针对这个做了一些异步的 OpenSession,将 OpenSession 分为两局部,第一步是连贯到 Kyuubi Server,Kyuubi Server 再异步启动一个 LaunchEngine Operation,之后立刻把 Kyuubi Server 连贯给客户端,这样客户端能够做到一秒钟就能够连贯到 Kyuubi Server。然而他的下条语句以及进来之后,会始终等到这个 Engine 初始化好之后才开始运行。其实这也是咱们的 PM 的一个需要,即便第一条语句运行工夫长一点也没关系,然而连贯是肯定要很快,所以咱们就做了这样一个工作。
因为 Hive Thrift RPC 是一个广泛应用而且十分用户敌对的 RPC,所以咱们在不毁坏它的兼容性的状况下基于 Thrift RPC 做了一些扩大。首先对于 ExecuteStatement 这种申请及返回后果,它会在 API 外面返回一个 OperationHandle,再依据 OperationHandle 获取以后 Operation 的状态和日志。因为咱们后面曾经把 OpenSession 拆成了 OpenSession 加上一个 LaunchEngine Operation,所以咱们想把 LaunchEngine Operation 的一些信息,通过 OpenSession request 这个 configuration map 把它返回去,咱们是把一个 OperationHandler 分为两局部,一部分是 guid,另一部分是 secret,放到 OpenSessionResp 的 configuration Map 外面。
而后在拿到 OpenSessionResp 之后就能够依据这个 configuration 拼出 Launch Engine Operation 对应的 OperationHandler,而后再依据它去拿这个 LaunchEngine 的日志和状态。
上面是一个成果,咱们在建设 Kyuubi 连贯的时候能够实时晓得 spark-submit 的过程中到底产生了什么。比如说用户将 spark.yarn.queue
设置错了,或者说因为资源问题始终在期待,都能够分明的晓得这两头产生了什么,不须要找平台保护人员去看日志,这样既让用户感到极为敌对,也缩小了平台保护人员的 efforts。
构建 Unified & Serverless Spark Gateway
后面说到要用一个 Kyuubi 服务来服务多个集群,咱们就基于 Kyuubi 构建了一个 Unified & Serverless Spark Gateway。Unified 是说咱们只有一个 endpoint,咱们是部署在 Kubernetes 之上的,应用 Kubernetes 的 LB 作为 Kyuubi Server 的服务发现,endpoint 的模式就是一个 Kubernetes 的 LB 加上一个端口,比如说kyuubi.k8s-lb.ebay.com:10009
,要服务多个集群,咱们只须要在 JDBC URL 外面加上一个参数kyuubi.session.cluster
,指定 cluster name,就能够让他的申请到指定的集群去执行。对于权限校验咱们也是用 Unified 的,同时反对 Kerberos 和 LDAP 权限校验。对于 functions(性能)也是 Unified 的,同时反对 Spark-SQL、Spark-Scala 以及 ETL Spark Job 的提交。
对于 Serverless, Kyuubi Server 部署在 Kubernetes 之上,是 Cloud-native 的,而且 Kyuubi Server 反对 HA 和 LB,Kyuubi Engine 反对多租户,所以对于平台保护人员来说老本非常低。
这是咱们大略的一个部署,对于多集群咱们引入了 Cluster Selector 的概念,为每个集群都配了一个 Kubernetes ConfigMap 文件,在这个文件外面有这个集群所独有的一些配置,比方这个集群的 ZooKeeper 的配置,集群的环境变量,会在启动 Kyuubi Engine 的时候注入到启动的过程外面。
每个集群的 super user 的配置也是不一样的,所以咱们也反对了对各个集群进行 super user 的校验。目前 Kyuubi 反对 HadoopFSDelegation token 和 HiveDelegation token 的刷新,能够让 Spark Engine 在没有 keytab 的状况上来长运行,而不必放心 token 过期的问题。咱们也让这个性能反对了多集群。
用户一个申请进来的过程是这样的:首先他要指定一个 Cluster Selector,Kyuubi Server(on Kubernetes)依据这个 Selector 去找到对应的集群,连贯集群的 ZooKeeper,而后查找在 ZooKeeper 外面有没有对应的 Spark app, 如果没有就提交一个 app 到 YARN 下面(Spark on YARN),Engine 在启动之后会向 ZooKeeper 注册,Kyuubi Server 和 Kyuubi Engine 通过 ZooKeeper 找到 Host 和 Port 并创立连贯。
Kyuubi 从一开始就反对 Thrift/JDBC/ODBC API, 目前社区也在欠缺 RESTFul API. eBay 也在做一些欠缺 RESTFul API 的工作,咱们给 RESTful API 加了权限校验的反对,同时反对 SPNEGO(Kerberos)和 BASIC(基于明码)的权限校验。咱们打算给 Kyuubi 减少更多的 RESTful API。目前已有的是对于 sessions 的 API,比方能够关掉 session,次要用于来治理 Kyuubi 的 sessions。咱们筹备加一些针对 SQL 以及 Batch Job 的 API。对于 SQL 就是能够间接通 RESTful API 提交一条 SQL Query,而后能够拿到它的后果以及 log。对于 Batch Job 就是能够通过 RESTful API 提交一个一般的应用 JAR 来运行的 Spark app,而后能够拿到 Spark app 的 ApplicationId,还有 spark-submit 的 log,这样能够让用户更加不便地应用 Kyuubi 实现各种罕用的 Spark 操作。
eBay 的收益
对用户来说,他们可能十分不便地应用 Spark 服务,能够应用 Thrift、JDBC、ODBC、RESTful 的接口,它也是十分轻量的,不须要去装置 Hadoop/Spark binary,也不须要治理 Hadoop 和 Spark 的 Conf,只须要用 RESTful 或者 Beeline/JDBC 的模式去连贯就好。
对咱们平台开发团队来说,咱们有了一个中心化的 Spark 服务,能够提供 SQL、Scala 的服务,也能够提供 spark-submit 的服务,咱们能够不便地治理 Spark 版本,不须要将 Spark 安装包分发给用户去应用,能够更好地实现灰度降级,让 Spark 版本对于用户透明化,让整个集群应用最新的 Spark,也节俭集群的资源,节俭公司的老本。此外,平台的保护也是比拟不便的,老本很低,因为咱们只须要保护一个 Kyuubi 服务来服务多个 Hadoop 集群。
作者:王斐,eBay 软件工程师,Apache Kyuubi PPMC Member
附视频回放及 PPT 下载:
Apache Kyuubi 在 eBay 的实际 - 王斐
延长浏览:
Apache Kyuubi 在 T3 出行的深度实际
Who is using Apache Kyuubi (Incubating)?
Kyuubi 我的项目主页
Kyuubi 代码仓库