文章目录
一、Spark Thrift Server 介绍
Spark Thrift Server 是 Spark 社区基于 HiveServer2 实现的一个 Thrift 服务。旨在无缝兼容 HiveServer2。
因为 Spark Thrift Server 的接口和协议都和 HiveServer2 完全一致,因此我们部署好 Spark Thrift Server 后,可以直接使用 hive 的 beeline 访问 Spark Thrift Server 执行相关语句。
Spark Thrift Server 的目的也只是取代 HiveServer2,因此它依旧可以和 Hive Metastore 进行交互,获取到 hive 的元数据。
二、部署 Spark Thrift Server
先将 hive-site.xml、hdfs-site.xml、core-site.xml 拷贝到 spark/conf 目录下。
如果运行的 Hive MetaStore 版本不是 1.2,需要将 hive-site.xml 中的 hive.metastore.schema.verification 参数设置为 false。否则会因为版本不一致报错
之后还需要拷贝相关 jar 包到 spark/jars 目录,否则会报 Could not load shims in class org.apache.hadoop.hive.schshim.FairSchedulerShim 错误。
cp hive/lib/hive-shims* spark/jars
cp hadoop/share/hadoop/yarn/hadoop-yarn-server-resourcemanager-2.7.4.jar spark/jars
之后启动 Thrift Server
# ThriftServer的本质是将Server服务以spark job的形式提交到集群运行,所以需要指定队列
sbin/start-thriftserver.sh --hiveconf spark.yarn.queue=root.bigdata.date
三、Spark Thrift Server 的架构

Spark Thrift Server 大量复用了 HiveServer2 的代码。
HiveServer2 的架构主要是通过 ThriftCLIService 监听端口,然后获取请求后委托给 CLIService 处理。CLIService 又一层层的委托,最终交给 OperationManager 处理。OperationManager 会根据请求的类型创建一个 Operation 的具体实现处理。比如 Hive 中执行 sql 的 Operation 实现是 SQLOperation。
Spark Thrift Server 做的事情就是实现自己的 CLIService——SparkSQLCLIService,接着也实现了 SparkSQLSessionManager 以及 SparkSQLOperationManager。另外还实现了一个处理 sql 的 Operation——SparkExecuteStatementOperation。这样,当 Spark Thrift Server 启动后,对于 sql 的执行就会最终交给 SparkExecuteStatementOperation 了。
Spark Thrift Server 其实就重写了处理 sql 的逻辑,其他的请求处理就完全复用 HiveServer2 的代码了。比如建表、删除表、建 view 等操作,全部使用的是 Hive 的代码。
四、Spark Thrift Server 如何执行 SQL
Spark Thrift Server 的启动其实是通过 spark-submit 将 HiveThriftServer2 提交给集群执行的。因此执行 start-thriftserver.sh 时可以传入 spark-submit 的参数表示提交 HiveThriftServer2 时的参数。另外,因为 HiveThriftServer2 必须要在本地运行,所以提交时的 deployMode 必须是 client,如果设置成 cluster 会报错。HiveThriftServer2 运行起来后,就等于是一个 Driver 了,这个 Driver 会监听某个端口,等待请求。
** 所以 HiveThriftServer2 程序运行起来后就等于是一个长期在集群上运行的 spark application。** 通过 yarn 或者 spark history server 页面我们都可以看到对应的任务。
既然 HiveThriftServer2 就是 Driver,那么运行 SQL 就很简单了。Spark Thrift Server 收到请求后最终是交给 SparkExecuteStatementOperation 处理,SparkExecuteStatementOperation 拿到 SQLContext,然后调用 SQLContext.sql() 方法直接执行用户传过来的 sql 即可。后面的过程就和我们直接写了一个 Main 函数然后通过 spark-submit 提交到集群运行是一样的。
五、和 HiveServer2 的区别
| Hive on Spark | Spark Thrift Server | |
|---|---|---|
| 任务提交模式 | 每个 session 都会创建一个 RemoteDriver,也就是对于一个 Application。之后将 sql 解析成执行的物理计划序列化后发到 RemoteDriver 执行 | 本身的 Server 服务就是一个 Driver,直接接收 sql 执行。也就是所有的 session 都共享一个 Application |
| 性能 | 性能一般 | 如果存储格式是 orc 或者 parquet,性能会比 hive 高几倍,某些语句甚至会高几十倍。其他格式的话,性能相差不是很大,有时 hive 性能会更好 |
| 并发 | 如果任务执行不是异步的,就是在 thrift 的 worker 线程中执行,受 worker 线程数量的限制。异步的话则放到线程池执行,并发度受异步线程池大小限制。 | 处理任务的模式和 Hive 一样。 |
| sql 兼容 | 主要支持 ANSI SQL 2003,但并不完全遵守,只是大部分支持。并扩展了很多自己的语法 | Spark SQL 也有自己的实现标准,因此和 hive 不会完全兼容。具体哪些语句会不兼容需要测试才能知道 |
| HA | 可以通过 zk 实现 HA | 没有内置的 HA 实现,不过 spark 社区提了一个 issue 并带上了 patch,可以拿来用:https://issues.apache.org/jira/browse/SPARK-11100 |
Spark Thrift Server 的优点
1、在大部分场景下,性能要比 Hive on spark 好,而且好很多
2、SparkSQL 的社区活跃度也很高,基本每月都会发布一个版本,因此性能还会不断提高
Spark Thrift Server 的缺点
1、因为 HiveThriftServer2 是以 Driver 的形式运行在集群的。因此它能使用的集群资源就和单个 Application 直接挂钩。如果 spark 集群没开启动态资源,那么 Spark Thrift Server 能得到的资源就始终都是固定的,这时候设置太大也不好,设置太小也不好。即使开启了动态资源,一般集群都会设置 maxExecutor,这时还是无法很好的利用集群的所有资源。如果将集群所有的资源都分配给了这个 Application,这样像 yarn、mesos 这些资源调度器就完全没有存在的意义了… 因此,单就这一点,Spark Thrift Server 就不是一个合格的企业级解决方案。
2、从 https://issues.apache.org/jira/browse/SPARK-11100 官方的回答来看,spark 官方对于 Spark Thrift Server 这套解决方案也不是很满意。这也可以理解,毕竟 Spark Thrift Server 只是对 HiveServer2 进行的一些小改造。
3、Spark Thrift Server 目前还是基于 Hive 的 1.2 版本做的改造,因此如果 MetaStore 的版本不是 1.2,那么也可能会有一些兼容性的潜在问题。
六、结论
Spark Thrift Server 说白了就是小小的改动了下 HiveServer2,代码量也不多。虽然接口和 HiveServer2 完全一致,但是它以单个 Application 在集群运行的方式还是比较奇葩的。可能官方也是为了实现简单而没有再去做更多的优化。
所以 Spark Thrift Server 最多搭建起来玩玩,或者自己内部做一些快速查询,并不适合真正放在企业级的使用上。