Spark Thrift JDBCServer應用場景解析與實戰案例

[TOC]


Spark Thrift JDBCServer應用場景解析與實戰案例

1 前言

這裏說的Spark Thrift JDBCServer並不是網上大部分寫到的Spark數據結果落地到RDB數據庫中所使用的JDBC方式,而是指Spark啓動一個名爲thriftserver的進程以供客戶端提供JDBC連接,進而使用SQL語句進行查詢分析。

http://spark.apache.org/docs/2.3.3/sql-programming-guide.html#running-the-thrift-jdbcodbc-server

後面的文章分析中,我會先說明一個基本的演進過程,即爲什麼會使用到Spark Thrift JDBCServer,其在大數據生態棧中大致是處於一個什麼樣的位置?我想理解了這些之後,使用Spark Thrift JDBCServer會顯得更加“自然”。不過如果讀者本身已經經歷過MapReduce、Hive、Spark On Yarn、Spark On Yarn With Hive、Spark SQL等的一些使用歷程,相信只要看過官方文檔的介紹,應該就能知道其定位以及出現的原因。因此這部分實際上是介紹一些相關大數據組件的作用以及演進,通過這些介紹來理解Spark Thrift JDBCServer所處在的位置。

在實際工作場景中,可能這些環境都不是你自己搭建的,可能你只是需要去連接Spark Thrift JDBCServer以使用Spark SQL的分析能力,或者基於Spark Thrift JDBCServer開發一些服務中間件,但仍然可以確定的是,你還是需要掌握其原理,並且熱切希望能自己搭個簡單的環境體驗一下。我會在已經搭建的Hadoop僞分佈式環境下,大致說明如何應用Spark Thrift JDBCServer,以及有哪些注意事項。

文章多數是按照個人的理解進行說明,如有相關錯誤,還望批評指正。

2 SQL大數據分析的Hadoop生態和Spark生態演進以及整合

大數據產品或大數據平臺,不管底層的技術使用多麼複雜,其最終都是希望產品交到用戶手中,能夠快速簡單地使用起來進行大數據分析,儘快和儘可能地處理大量數據,以更好地挖掘數據的價值。而進行數據分析最好用的工具或語言之一顯然就是SQL了,因此大多數據大數據產品、框架或技術,一般都會提供SQL接口。放眼來看現在的比較主流的大數據框架,也是如此,比如有Hive、Spark SQL、Elasticsearch SQL、Druid SQL等。

這裏會簡要介紹

2.1 Hadoop MapReduce

MapReduce是Hadoop的分佈式計算框架,結合Hadoop的分佈式存儲HDFS,使得大規模的批量數據處理成爲可能。通過MapReduce提供的簡單接口,用戶可以在不瞭解其底層的情況下,快速構建分佈式應用程序,大大提高了開發分佈式數據處理程序的效率。

但由於MapReduce在數據處理過程中,中間生成結果都是存放在磁盤,因此其處理速度很慢,儘管如此,對於大規模的離線數據處理,MapReduce仍然會是一個不錯的選擇。

2.2 SQL On MapReduce: Hive

儘管基於MapReduce提供的接口開發分佈式程序已經比較簡單了,但由於仍然需要進行編碼,這對於一些從來沒有接觸過編程的數據分析人員或運維人員,其還是會有不少的學習成本。於是Hive便出現了。

Hive被稱爲SQL On Hadoop或者SQL On MapReduce,是一款建立在Hadoop之上的數據倉庫的基礎框架,簡單理解,在Hive上,你可以像在RDB中一樣,編寫SQL語句來對你的數據進行分析,Hive的解釋器會把SQL語句轉換爲MapRedcue作業,提交到Yarn上去運行,這樣一來,只要會寫SQL語句,你就能構建強大的MapReduce分佈式應用程序。

2.3 Hive JDBC之hiveserver2

Hive提供了一個命令行終端,在安裝了Hive的機器上,配置好了元數據信息數據庫和指定了Hadoop的配置文件之後輸入hive命令,就可以進入到hive的交互式終端,接下來只要編寫SQL語句即可,這跟傳統RDB數據庫提供的終端是類似的。

我們知道傳統的RDB數據庫,比如MySQL,不僅提供了交互式終端操作,也可以在編碼在代碼中去連接MySQL以進行操作,比如在Java中可以通過JDBC進行連接,畢竟在實際業務中,更多時候是使用其提供的編程接口,而不是僅僅是交互式終端。

Hive也是類似的。Hive除了提供前面的cli用戶接口,還提供了jdbc的用戶接口,但是如果需要使用該接口,則需要先啓動hiveserver2服務,啓動該服務後,可以通過hive提供的beeline繼續以cli的方式操作hive(不過需要注意的是,此時是通過jdbc接口進行操作hive的),也可以通過手工編寫java代碼來進行操作。

通過hiverserver2,就可以通過Java JDBC進行連接,這樣以實現更多更復雜的業務邏輯。

2.4 Spark

Spark也是一個分佈式計算引擎,其將處理的數據抽象爲RDD或Dataset保存到內存中,中間處理結果也保存到內存中,因此其速度比MapReduce要快10到100倍。

基於Spark提供的接口和各種算子,可以十分輕易地開發出功能強大的分佈式數據處理程序。

2.5 Spark SQL

使用Spark的基本功能時,也是需要使用代碼進行操作的,爲了更方便地使用Spark,其也提供了SQL相關接口——Spark SQL。

這似乎跟Hive在MapReduce中提供的CLI功能很相似,不過與Hive不同的在於,使用Spark SQL,仍然需要一定程序地使用代碼進行相關表的創建和元數據設置,之後纔可以繼續使用SQL語句進行表的操作,這點使用過Spark SQL的同學應該很清楚。而使用Hive時,直接編寫SQL語句創建表、寫入數據、分析數據即可,不需要額外的代碼操作。

2.6 Spark SQL On Hive

如何避免前面Spark SQL中的這種尷尬?Spark SQL的其中一個分支就是Spark on Hive,也就是使用Hive中HQL的解析、邏輯執行計劃翻譯、執行計劃優化等邏輯,可以近似認爲僅將物理執行計劃從MR作業替換成了Spark作業。SparkSql整合hive就是獲取hive表中的元數據信息,然後通過SparkSql來操作數據。

2.7 Spark SQL JDBC之Spark Thrift JDBCServer

跟hiveserver2的作用一樣,Spark Thrift JDBCServer是Spark的一個進程,啓動之後就可以通過Java JDBC代碼進行連接操作,該進程本質上是Spark的一個Application。

Spark Thrift JDBCServer本身也是可以和Hive整合使用。

Spark Thrift JDBCServer的使用是基於下面和個方面的考慮:

  • 1.希望使用SQL進行數據分析;
  • 2.能夠通過Java JDBC的方式進行連接;
  • 3.基於內存計算,快速處理數據;
  • 4.可以跟Hive進行整合;
  • 5.可以基於Yarn進行資源的調度;

2.8 Spark、Hadoop和Hive的整合

現在一般Spark應用程序會部署到Hadoop的Yarn上進行調度,雖然Spark本身也提供了standalone的部署模式。

而在使用Spark SQL時,因爲大部分數據一般都是保存在HDFS上,而Hive本身就是操作HDFS上的數據,因此一般會將Spark SQL和Hive整合使用,即如2.6中所提到的,元數據信息是使用Hive表的,而真正處理數據時使用的計算引擎是Spark的。

當希望通過Java JDBC的方式使用Spark SQL的能力時,就可以使用Spark Thrift JDBCServer,並且其本身也是可以和Hive整合使用。

3 Spark Thrift JDBCServer實戰

3.1 Spark Thrift JDBCServer快速入門

3.1.1 啓動

其使用非常簡單,幾乎不用做任何操作,這裏使用spark-2.3.3-bin-hadoop2.6.tgz版本,下載鏈接如下:

https://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-2.3.3/spark-2.3.3-bin-hadoop2.6.tgz

這裏使用國內的Apache鏡像源,下載速度非常快!推薦大家使用:https://mirrors.tuna.tsinghua.edu.cn/apache/

將下載的安裝包解壓縮之後,直接啓動:

$ cd sbin/
$ ./start-thriftserver.sh

默認偵聽10000端口:

$ lsof -i:10000
COMMAND  PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    1414 yeyonghao  407u  IPv6 0x3cb645c07427abbb      0t0  TCP *:ndmp (LISTEN)

前面說過了,其本質上是Spark的一個Application,因此可以看到這時4040端口也啓動了:

$ lsof -i:4040
COMMAND  PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    1414 yeyonghao  270u  IPv6 0x3cb645c07427d3fb      0t0  TCP *:yo-main (LISTEN)

使用jps命令查看,可以看到有SparkSubmit進程:

$ jps
901 SecondaryNameNode
1445 Jps
806 DataNode
1414 SparkSubmit
729 NameNode
1132 NodeManager
1053 ResourceManager

我這裏另外還啓動了Hadoop的僞分佈式環境。

不妨打開瀏覽器看一下4040端口的頁面:

Spark Thrift JDBCServer應用場景解析與實戰案例

可以說是相當熟悉的頁面了,注意右上角其名稱爲:Thrift JDBC/ODBC Server,啓動Thriftserver,其本質上就是提交了Spark的一個Application!(如果有使用過Spark Shell的同學也應該知道,Spark Shell也是Spark的一個Application)

3.1.2 使用beeline連接

那麼如何進行連接操作呢?Spark提供了一個beeline連接工具。

$ cd bin/
$ ./beeline

然後連接上Thriftserver:

Beeline version 1.2.1.spark2 by Apache Hive
beeline> !connect jdbc:hive2://localhost:10000
Connecting to jdbc:hive2://localhost:10000
Enter username for jdbc:hive2://localhost:10000:
Enter password for jdbc:hive2://localhost:10000:
2019-07-13 15:58:40 INFO  Utils:310 - Supplied authorities: localhost:10000
2019-07-13 15:58:40 INFO  Utils:397 - Resolved authority: localhost:10000
2019-07-13 15:58:40 INFO  HiveConnection:203 - Will try to open client transport with JDBC Uri: jdbc:hive2://localhost:10000
Connected to: Spark SQL (version 2.3.3)
Driver: Hive JDBC (version 1.2.1.spark2)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://localhost:10000>

之後就可以進行各種SQL操作:

0: jdbc:hive2://localhost:10000> create table person
0: jdbc:hive2://localhost:10000> (
0: jdbc:hive2://localhost:10000> id int,
0: jdbc:hive2://localhost:10000> name string
0: jdbc:hive2://localhost:10000> );
+---------+--+
| Result  |
+---------+--+
+---------+--+
No rows selected (1.116 seconds)
0: jdbc:hive2://localhost:10000> insert into person values(1,'xpleaf');
+---------+--+
| Result  |
+---------+--+
+---------+--+
No rows selected (1.664 seconds)
0: jdbc:hive2://localhost:10000> select * from person;
+-----+---------+--+
| id  |  name   |
+-----+---------+--+
| 1   | xpleaf  |
+-----+---------+--+
1 row selected (0.449 seconds)

這時再去前面說的4040頁面看一下:

Spark Thrift JDBCServer應用場景解析與實戰案例

可以看到我們的操作其實都是被轉換爲了Spark Application中的一個個Job進行操作。

3.1.3 使用Java JDBC進行連接

既然其是一個JDBC服務,那麼當然可以通過Java代碼來進行操作。

創建一個Maven工程,添加下面的依賴:

<dependency>
  <groupId>org.apache.hive</groupId>
  <artifactId>hive-jdbc</artifactId>
  <version>2.1.0</version>
</dependency>

<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-core</artifactId>
  <version>1.2.1</version>
</dependency>

編寫代碼如下:

package cn.xpleaf.spark;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * @author xpleaf
 * @date 2019/7/13 4:06 PM
 */
public class SampleSparkJdbcServer {

    public static void main(String[] args) throws Exception {
        Class.forName("org.apache.hive.jdbc.HiveDriver");

        Connection connection = DriverManager.getConnection("jdbc:hive2://localhost:10000");
        Statement statement = connection.createStatement();
        String sql = "select * from person";
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()) {
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println(String.format("id: %s, name: %s", id, name));
        }
    }

}

啓動後運行結果如下:

id: 1, name: xpleaf

3.1.4 注意事項

前面的方式創建表和寫入的數據,都是保存在內存中,因此只要thirfserver退出,數據就會丟失,所以爲了持久化這些數據,後面我們爲與Hive進行整合。

3.2 Spark Thirft JDBCServer整合Hive

整合Hive的一個明顯好處是,我們既可以藉助了HDFS進行分佈式存儲,持久化我們的數據,也可以藉助Spark本身的快速計算能力以快速處理數據,而這中間,需要藉助Hive來做“中間人”,本質上我們是使用了Hive創建的各種元數據信息表。

3.2.1 Hive安裝

安裝Hive前需要先搭建Hadoop環境,這裏不介紹Hadoop環境如何搭建,在我的機器上,已經搭建了一個Hadoop的僞分佈式環境。

$ jps
901 SecondaryNameNode
1557 RemoteMavenServer
806 DataNode
729 NameNode
1834 Jps
1547
1132 NodeManager
1053 ResourceManager

實際上Hive安裝的三個前提條件爲:

JDK         // Java環境
HADOOP  // Hadoop環境
MySQL       // 關係型數據庫,持久化存儲Hive的元數據信息

這裏是假設這三個步驟都已經完成。

Hive的下載依然可以使用前面介紹的國內Apache鏡像源:

https://mirrors.tuna.tsinghua.edu.cn/apache/hive/hive-2.3.5/apache-hive-2.3.5-bin.tar.gz

即這裏使用的版本爲2.3.5。

下載完成後,解壓縮到指定目錄,然後再配置相關文件。

(1)配置hive-env.sh

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home
export HADOOP_HOME=/Users/yeyonghao/app/hadoop
export HIVE_HOME=/Users/yeyonghao/app2/hive

(2)配置hive-site.xml

<property>
  <name>javax.jdo.option.ConnectionURL</name>
  <value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
  <name>javax.jdo.option.ConnectionDriverName</name>
  <value>com.mysql.jdbc.Driver</value>
</property>
<property>
  <name>javax.jdo.option.ConnectionUserName</name>
  <value>root</value>
</property>
<property>
  <name>javax.jdo.option.ConnectionPassword</name>
  <value>root</value>
</property>
<property>
  <name>hive.querylog.location</name>
  <value>/Users/yeyonghao/app2/hive/tmp</value>
</property>
<property>
  <name>hive.exec.local.scratchdir</name>
  <value>/Users/yeyonghao/app2/hive/tmp</value>
</property>
<property>
  <name>hive.downloaded.resources.dir</name>
  <value>/Users/yeyonghao/app2/hive/tmp</value>
</property>

(3)將mysql驅動拷貝到$HIVE_HOME/lib目錄下

直接從maven中下載:

~/app2/hive/lib$ wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.39/mysql-connector-java-5.1.39.jar

(4)初始化Hive元數據庫

~/app2/hive/bin$ ./schematool -initSchema -dbType mysql -userName root -passWord root

成功後可以在mysql中看到創建的hive數據庫和相關表:

mysql> use hive;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+---------------------------+
| Tables_in_hive            |
+---------------------------+
| AUX_TABLE                 |
| BUCKETING_COLS            |
| CDS                       |
| COLUMNS_V2                |
| COMPACTION_QUEUE          |
| COMPLETED_COMPACTIONS     |
| COMPLETED_TXN_COMPONENTS  |
| DATABASE_PARAMS           |
| DBS                       |
| DB_PRIVS                  |
| DELEGATION_TOKENS         |
| FUNCS                     |
| FUNC_RU                   |
| GLOBAL_PRIVS              |
| HIVE_LOCKS                |
| IDXS                      |
| INDEX_PARAMS              |
| KEY_CONSTRAINTS           |
| MASTER_KEYS               |
| NEXT_COMPACTION_QUEUE_ID  |
| NEXT_LOCK_ID              |
| NEXT_TXN_ID               |
| NOTIFICATION_LOG          |
| NOTIFICATION_SEQUENCE     |
| NUCLEUS_TABLES            |
| PARTITIONS                |
| PARTITION_EVENTS          |
| PARTITION_KEYS            |
| PARTITION_KEY_VALS        |
| PARTITION_PARAMS          |
| PART_COL_PRIVS            |
| PART_COL_STATS            |
| PART_PRIVS                |
| ROLES                     |
| ROLE_MAP                  |
| SDS                       |
| SD_PARAMS                 |
| SEQUENCE_TABLE            |
| SERDES                    |
| SERDE_PARAMS              |
| SKEWED_COL_NAMES          |
| SKEWED_COL_VALUE_LOC_MAP  |
| SKEWED_STRING_LIST        |
| SKEWED_STRING_LIST_VALUES |
| SKEWED_VALUES             |
| SORT_COLS                 |
| TABLE_PARAMS              |
| TAB_COL_STATS             |
| TBLS                      |
| TBL_COL_PRIVS             |
| TBL_PRIVS                 |
| TXNS                      |
| TXN_COMPONENTS            |
| TYPES                     |
| TYPE_FIELDS               |
| VERSION                   |
| WRITE_SET                 |
+---------------------------+
57 rows in set (0.00 sec)

(5)Hive測試

啓動Hive Cli:

~/app2/hive/bin$ ./hive

創建相關表並寫入數據:

hive> show databases;
OK
default
Time taken: 0.937 seconds, Fetched: 1 row(s)
hive> show tables;
OK
Time taken: 0.059 seconds
hive> create table person
    > (
    > id int,
    > name string
    > );
OK
Time taken: 0.284 seconds
hive> insert into person values(1,'xpleaf');
...省略提交MapReduce作業信息...
MapReduce Jobs Launched:
Stage-Stage-1: Map: 1   HDFS Read: 4089 HDFS Write: 79 SUCCESS
Total MapReduce CPU Time Spent: 0 msec
OK
Time taken: 17.54 seconds
hive> select * from person;
OK
1   xpleaf
Time taken: 0.105 seconds, Fetched: 1 row(s)

3.2.2 Spark Thirftserver整合Hive

官方文檔關於這部分的說明:

Configuration of Hive is done by placing your hive-site.xml, core-site.xml and hdfs-site.xml files in conf/.

其實也就是將Hive的配置文件hive-site.xml,Hadoop的配置文件core-site.xml和hdfs-site.xml放到Spark的配置目錄下。

之後再啓動Thirftserver:

~/app2/spark/sbin$ ./start-thriftserver.sh
starting org.apache.spark.sql.hive.thriftserver.HiveThriftServer2, logging to /Users/yeyonghao/app2/spark/logs/spark-yeyonghao-org.apache.spark.sql.hive.thriftserver.HiveThriftServer2-1-yeyonghaodeMacBook-Pro.local.out

但是後面會看到其並沒有啓動:

$ lsof -i:10000

查看啓動日誌,看到其報錯信息如下:

980 Caused by: org.datanucleus.store.rdbms.connectionpool.DatastoreDriverNotFoundException: The specified datastore driver ("com.mysql.jdbc.Driver") was not found in the CLASSPATH. Please check your CLASS    PATH specification, and the name of the driver.
981     at org.datanucleus.store.rdbms.connectionpool.AbstractConnectionPoolFactory.loadDriver(AbstractConnectionPoolFactory.java:58)
982     at org.datanucleus.store.rdbms.connectionpool.BoneCPConnectionPoolFactory.createConnectionPool(BoneCPConnectionPoolFactory.java:54)
983     at org.datanucleus.store.rdbms.ConnectionFactoryImpl.generateDataSources(ConnectionFactoryImpl.java:238)
984     ... 91 more

也就是找不到mysql驅動,可以將之前hive下的該驅動拷貝到spark的jars目錄下:

cp ~/app2/hive/lib/mysql-connector-java-5.1.39.jar ~/app2/spark/jars/

然後再啓動,看日誌時發現其還是報錯:

Caused by: MetaException(message:Hive Schema version 1.2.0 does not match metastore's schema version 2.1.0 Metastore is not upgraded or corrupt)

原因,看spark jars目錄下提供的jar包:

~/app2/spark/jars$ ls hive-
hive-beeline-1.2.1.spark2.jar hive-cli-1.2.1.spark2.jar hive-exec-1.2.1.spark2.jar hive-jdbc-1.2.1.spark2.jar hive-metastore-1.2.1.spark2.jar

顯然都是hive 1.x的版本。

但我安裝的Hive是2.x版本,在mysql中有一個VERSION表保存其版本爲2.1.0。

參考:https://yq.aliyun.com/articles/624494

這裏我在spark的hive-site.xml中關閉版本驗證:

<property>
    <name>hive.metastore.schema.verification</name>
    <value>false</value>
</property>

修改完成後可以看到成功啓動的日誌信息:

...
2019-07-13 17:16:47 INFO  ContextHandler:781 - Started o.s.j.s.ServletContextHandler@1774c4e2{/sqlserver/session,null,AVAILABLE,@Spark}
2019-07-13 17:16:47 INFO  ContextHandler:781 - Started o.s.j.s.ServletContextHandler@f0381f0{/sqlserver/session/json,null,AVAILABLE,@Spark}
2019-07-13 17:16:47 INFO  ThriftCLIService:98 - Starting ThriftBinaryCLIService on port 10000 with 5...500 worker threads

看一下端口號:

~/app2/spark/sbin$ lsof -i:10000
COMMAND  PID      USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    5122 yeyonghao  317u  IPv6 0x3cb645c07a5bcbbb      0t0  TCP *:ndmp (LISTEN)

3.2.3 啓動beeline進行測試

這裏我們啓動beeline進行操作:

~/app2/spark/bin$ ./beeline
Beeline version 1.2.1.spark2 by Apache Hive

之前我們在Hive中創建了一張person表,如果跟Hive整合成功,那麼這裏也應該可以看到,因爲共用的是同一個metastore,如下查看其中的數據:

beeline> !connect jdbc:hive2://localhost:10000
Connecting to jdbc:hive2://localhost:10000
Enter username for jdbc:hive2://localhost:10000:
Enter password for jdbc:hive2://localhost:10000:
2019-07-13 17:20:02 INFO  Utils:310 - Supplied authorities: localhost:10000
2019-07-13 17:20:02 INFO  Utils:397 - Resolved authority: localhost:10000
2019-07-13 17:20:02 INFO  HiveConnection:203 - Will try to open client transport with JDBC Uri: jdbc:hive2://localhost:10000
Connected to: Spark SQL (version 2.3.3)
Driver: Hive JDBC (version 1.2.1.spark2)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://localhost:10000> show tables;
+-----------+------------+--------------+--+
| database  | tableName  | isTemporary  |
+-----------+------------+--------------+--+
| default   | person     | false        |
+-----------+------------+--------------+--+
1 row selected (0.611 seconds)
0: jdbc:hive2://localhost:10000> select * from person;
+-----+---------+--+
| id  |  name   |
+-----+---------+--+
| 1   | xpleaf  |
+-----+---------+--+
1 row selected (1.842 seconds)

可以看到,沒有問題,再查看4040端口:

Spark Thrift JDBCServer應用場景解析與實戰案例

這裏我們再創建一張person2表:

0: jdbc:hive2://localhost:10000> create table person2
0: jdbc:hive2://localhost:10000> (
0: jdbc:hive2://localhost:10000> id int,
0: jdbc:hive2://localhost:10000> name string
0: jdbc:hive2://localhost:10000> );
+---------+--+
| Result  |
+---------+--+
+---------+--+
No rows selected (0.548 seconds)

這時可以去保存元數據信息的mysql數據庫中看一下,在tbls表中保存了我們創建的數據表信息:

mysql> select * from tbls;
+--------+-------------+-------+------------------+-----------+-----------+-------+----------+---------------+--------------------+--------------------+
| TBL_ID | CREATE_TIME | DB_ID | LAST_ACCESS_TIME | OWNER     | RETENTION | SD_ID | TBL_NAME | TBL_TYPE      | VIEW_EXPANDED_TEXT | VIEW_ORIGINAL_TEXT |
+--------+-------------+-------+------------------+-----------+-----------+-------+----------+---------------+--------------------+--------------------+
|      1 |  1563008351 |     1 |                0 | yeyonghao |         0 |     1 | person   | MANAGED_TABLE | NULL               | NULL               |
|      6 |  1563009667 |     1 |                0 | yeyonghao |         0 |     6 | person2  | MANAGED_TABLE | NULL               | NULL               |
+--------+-------------+-------+------------------+-----------+-----------+-------+----------+---------------+--------------------+--------------------+
2 rows in set (0.00 sec)

可以看到已經有person2表的信息了,說明Thirftserver與Hive整合成功。

3.3 更進一步:Spark Thirft JDBCServer On Yarn With Hive

前面3.2其實已經整合了Hive,這裏再跟Yarn做整合。

3.3.1 部署Thirftserver到Yarn原理

前面說了,Thirftserver本質上就是Spark的一個Application,因此,我們也可以在啓動Thirftserver時指定master爲yarn,其實就是將Thirftserver這個Spark Application部署到Yarn上,讓Yarn爲其分配資源,調度其作業的執行。

官方文檔關於這點說明如下:

his script accepts all bin/spark-submit command line options, plus a --hiveconf option to specify Hive properties. You may run ./sbin/start-thriftserver.sh --help for a complete list of all available options. By default, the server listens on localhost:10000. You may override this behaviour via either environment variables, i.e.:
……

也就是說saprk-submit腳本接收的參數,start-thriftserver.sh也能接收。

3.3.2 指定master爲yarn啓動Thirftserver

現在,使用下面的啓動方式:

~/app2/spark/sbin$ ./start-thriftserver.sh --master yarn
starting org.apache.spark.sql.hive.thriftserver.HiveThriftServer2, logging to /Users/yeyonghao/app2/spark/logs/spark-yeyonghao-org.apache.spark.sql.hive.thriftserver.HiveThriftServer2-1-yeyonghaodeMacBook-Pro.local.out
failed to launch: nice -n 0 bash /Users/yeyonghao/app2/spark/bin/spark-submit --class org.apache.spark.sql.hive.thriftserver.HiveThriftServer2 --name Thrift JDBC/ODBC Server --master yarn
  Spark Command: /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/bin/java -cp /Users/yeyonghao/app2/spark/conf/:/Users/yeyonghao/app2/spark/jars/* -Xmx1g org.apache.spark.deploy.SparkSubmit --master yarn --class org.apache.spark.sql.hive.thriftserver.HiveThriftServer2 --name Thrift JDBC/ODBC Server spark-internal
  ========================================
  Exception in thread "main" java.lang.Exception: When running with master 'yarn' either HADOOP_CONF_DIR or YARN_CONF_DIR must be set in the environment.
    at org.apache.spark.deploy.SparkSubmitArguments.validateSubmitArguments(SparkSubmitArguments.scala:288)
    at org.apache.spark.deploy.SparkSubmitArguments.validateArguments(SparkSubmitArguments.scala:248)
    at org.apache.spark.deploy.SparkSubmitArguments.<init>(SparkSubmitArguments.scala:120)
    at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:130)
    at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
full log in /Users/yeyonghao/app2/spark/logs/spark-yeyonghao-org.apache.spark.sql.hive.thriftserver.HiveThriftServer2-1-yeyonghaodeMacBook-Pro.local.out

可以看到其報錯信息,關鍵爲:

When running with master 'yarn' either HADOOP_CONF_DIR or YARN_CONF_DIR must be set in the environment.

直接在spark-env.sh中添加:

HADOOP_CONF_DIR=/Users/yeyonghao/app/hadoop/etc/hadoop
YARN_CONF_DIR=/Users/yeyonghao/app/hadoop/etc/hadoop

之後再啓動就沒有問題了,看日誌可以知道,其本質上就是把Thirftserver作爲Spark Application,然後提交到Yarn上去調度:

  73 2019-07-13 17:35:22 INFO  Client:54 - Application report for application_1563008220920_0002 (state: ACCEPTED)
  74 2019-07-13 17:35:22 INFO  Client:54 -
  75      client token: N/A
  76      diagnostics: N/A
  77      ApplicationMaster host: N/A
  78      ApplicationMaster RPC port: -1
  79      queue: default
  80      start time: 1563010521752
  81      final status: UNDEFINED
  82      tracking URL: http://192.168.1.2:8088/proxy/application_1563008220920_0002/
  83      user: yeyonghao
  84 2019-07-13 17:35:23 INFO  Client:54 - Application report for application_1563008220920_0002 (state: ACCEPTED)
  85 2019-07-13 17:35:24 INFO  Client:54 - Application report for application_1563008220920_0002 (state: ACCEPTED)
  86 2019-07-13 17:35:25 INFO  Client:54 - Application report for application_1563008220920_0002 (state: ACCEPTED)
  87 2019-07-13 17:35:26 INFO  Client:54 - Application report for application_1563008220920_0002 (state: ACCEPTED)
  88 2019-07-13 17:35:27 INFO  Client:54 - Application report for application_1563008220920_0002 (state: ACCEPTED)
  89 2019-07-13 17:35:28 INFO  YarnClientSchedulerBackend:54 - Add WebUI Filter. org.apache.hadoop.yarn.server.webproxy.amfilter.AmIpFilter, Map(PROXY_HOSTS -> 192.168.1.2, PROXY_URI_BASES -> http://192.1     68.1.2:8088/proxy/application_1563008220920_0002), /proxy/application_1563008220920_0002
  90 2019-07-13 17:35:28 INFO  JettyUtils:54 - Adding filter org.apache.hadoop.yarn.server.webproxy.amfilter.AmIpFilter to /jobs, /jobs/json, /jobs/job, /jobs/job/json, /stages, /stages/json, /stages/stag     e, /stages/stage/json, /stages/pool, /stages/pool/json, /storage, /storage/json, /storage/rdd, /storage/rdd/json, /environment, /environment/json, /executors, /executors/json, /executors/threadDump,      /executors/threadDump/json, /static, /, /api, /jobs/job/kill, /stages/stage/kill.
  91 2019-07-13 17:35:28 INFO  YarnSchedulerBackend$YarnSchedulerEndpoint:54 - ApplicationMaster registered as NettyRpcEndpointRef(spark-client://YarnAM)
  92 2019-07-13 17:35:28 INFO  Client:54 - Application report for application_1563008220920_0002 (state: RUNNING)
  93 2019-07-13 17:35:28 INFO  Client:54 -
  94      client token: N/A
  95      diagnostics: N/A
  96      ApplicationMaster host: 192.168.1.2
  97      ApplicationMaster RPC port: 0
  98      queue: default
  99      start time: 1563010521752
 100      final status: UNDEFINED
 101      tracking URL: http://192.168.1.2:8088/proxy/application_1563008220920_0002/
 102      user: yeyonghao
 103 2019-07-13 17:35:28 INFO  YarnClientSchedulerBackend:54 - Application application_1563008220920_0002 has started running.

可以查看8088端口,看一下這個Application的信息:

Spark Thrift JDBCServer應用場景解析與實戰案例

之後我們連接Thirftserver之後,所執行的操作,在Spark中會被轉換爲相應的Job(注意是Spark Application的Job,其又可能包含多個Stage,而Stage又會包含多個Task,對這部分不瞭解的同學可以先學習一下Spark Core相關內容),其資源調度都是由Yarn完成的。

這時如果訪問原來的4040端口,會跳轉到Yarn對該Application的監控,不過界面還是熟悉的Spark UI,如下:

Spark Thrift JDBCServer應用場景解析與實戰案例

之後通過beeline或者JDBC連接操作時,可以看到這裏有job的運行信息:

Spark Thrift JDBCServer應用場景解析與實戰案例

還可以看到session信息:

Spark Thrift JDBCServer應用場景解析與實戰案例

4 總結:你需要使用Spark Thirft JDBCServer嗎?

在生產環境中,可能更多會看到Spark SQL跟Hive的整合使用或3.3所提到的Spark Thirft JDBCServer On Yarn With Hive,不管哪一種情況,其都是出於下面的核心目的進行考慮的:

  • 1.支持使用SQL來對數據進行分析;
  • 2.能夠基於HDFS進行數據的分佈式存儲;
  • 3.速度較快;

而當考慮是否需要提供JDBC的方式進行連接時,則可以考慮使用Spark Thirft JDBCServer。

5 更多的SQL分析大數據平臺

除了前面提及的,其實可以使用SQL進行分析的大數據平臺或者框架還有Storm SQL、Flink SQL,都是目前相當熱門和流行的。

另外,還有Elasticsearch和Druid這些集數據存儲和分析於一體的大數據框架,也是非常流行,同樣支持SQL的查詢。

根據筆者對Elasticsearch一直以來的使用和了解情況,雖然起初Elasticsearch是作爲對標Solr的一個全文檢索框架而誕生,但逐漸會發現隨着版本的迭代更新,Elasticsearch加入了越來越多的數據分析算子,在6.0版本之後更是直接加入了SQL的數據分析查詢能力,儘管目前該能力還相對薄弱,但隨着時間的推移,Elasticsearch SQL也肯定會變得更強大!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章