Spark版本:2.4.0+cdh6.3.1
Spark-Windows版本:spark-2.4.0-bin-hadoop2.7
WinUtils版本:hadoop-2.7.1
Python版本:3.7.2
Java版本:1.8.0_121
Scala版本:2.11.8 按需安装
目录
- 前言
- 1 使用PyCharm开发PySpark直连Hive metastore
- 1.1 下载相关包
- 1.2 配置环境变量
- 1.3 设置spark日志级别
- 1.4 启动spark-sql
- 1.5 创建测试表并插入数据
- 1.6 安装相关包
- 1.7 编写脚本测试
- 2 使用Jupyter开发PySpark
- 2.1 放入公共脚本
- 2.2 登录jupyter
- 2.3 新建ipynb
- 2.4 编写脚本
- 2.5 导出脚本
- 3 使用IDEA通过JDBC方式远程连接HiveServer2
前言
俗话说得好,Life is short, you need Python(人生苦短,我用python)。哈哈,这不是俗话,这是出自大名鼎鼎的python之父,Guido van Rossum(吉多•范罗苏姆),就是下图那位。Python作为目前最火的编程语言,而Spark作为目前最火的大数据计算引擎,它俩结合碰撞出了怎样的火花呢。
本文提供了两种在Windows下开发调试PySpark的方法,使用PyCharm和使用Jupyter。此外,本文还提供了使用IDEA通过JDBC方式远程连接HiveServer2。
1 使用PyCharm开发PySpark直连Hive metastore
1.1 下载相关包
Spark-2.4.0:CDH版本不支持Windows下运行,使用开源版本
Hadoop-2.7.1:使用winutils-master里的即可,不需要全量包
Python-3.7.2:python-3.7.2-amd64.exe
Java-1.8.0_121:jdk-8u121-windows-x64.exe
Scala-2.11.8:scala-2.11.8.msi 按需安装
汇总的下载地址:
想白嫖也可以自己找相关包哟,都是开源的~
1.2 配置环境变量
HADOOP_HOME = D:\hadoop-2.7.1
SPARK_HOME = D:\spark
JAVA_HOME = D:\java
SCALA_HOME = D:\scala
1.3 设置spark日志级别
修改{SPARK_HOME}\conf\log4j.properties
log4j.rootCategory=WARN, console
1.4 启动spark-sql
C:\Users\User>spark-sql
需注意的是,因为没有配置元数据库,默认使用derby,在哪里启动就会在哪里创建一个metastore_db,如果要复用表需在同一目录下启动。
1.5 创建测试表并插入数据
spark-sql> create table test_table(id string, age int);
spark-sql> insert into table test_table values('1', 18);
spark-sql> insert into table test_table values('2', 28);
spark-sql> select * from test_table;
2 28
1 18
Time taken: 0.129 seconds, Fetched 2 row(s)
1.6 安装相关包
将{SPARK_HOME}\python\下的pyspark文件夹拷到
{PYTHON_HOME}\Lib\site-packages下
安装py4j:pip install py4j-0.10.9.1-py2.py3-none-any.whl
下载地址:
1.7 编写脚本测试
在metastore_db所在目录下新建脚本test_local_conn.py,使用pycharm打开并执行。
from pyspark.sql import SparkSession
import os
os.environ["HADOOP_HOME"] = "D:\\hadoop-2.7.1"
spark = SparkSession.builder.appName('test_local_conn_hive')\
#.config("hive.metastore.uris", "thrift://xx:9083") \
.master("local[*]")\
.enableHiveSupport().getOrCreate()
spark.sql('show tables').show()
spark.sql('select distinct id from test_table').show()
#spark.sql('create table copy_table as select * from test_table')
spark.sql('show tables').show()
spark.sql("insert into table test_table values('3', 38)")
spark.sql("insert into table test_table values('4', 48)")
spark.sql('select * from test_table').show()
spark.stop()
执行部分结果见下:
注意:
1.执行脚本前需关闭spark-sql shell,不然会冲突报错
ERROR Schema: Failed initialising database.
Caused by: ERROR XSDB6: Another instance of Derby may have already booted the database D:\xx\metastore_db.
pyspark.sql.utils.AnalysisException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient;’
2.连接远程集群没有开启Kerberos认证的hive,只需配置远程metastore uris即可连接
.config(“hive.metastore.uris”, “thrift://xx:9083”)
2 使用Jupyter开发PySpark
2.1 放入公共脚本
在jupyter workspace放入公共脚本或者自己写的脚本,方便import
2.2 登录jupyter
http://xxx:19010/hub/login
2.3 新建ipynb
2.4 编写脚本
2.5 导出脚本
代码测试没有问题后,可直接导出.py文件
3 使用IDEA通过JDBC方式远程连接HiveServer2
使用这种方式可以远程连接开启了Kerberos认证的Hive,但是只能执行SQL,无法测试整个脚本。
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import com.cebbank.entity.AAATable;
/**
* @author: drguo
* @blog: drguo.blog.csdn.net
* @date 2021/1/21 14:33
*/
public class JDBCHiveServer2Util {
private static String CONNECTION_URL ="jdbc:hive2://xxx:10000/;principal=hive/xxx@BANKCHINA.COM";
private static String principal ="xxx";
private static String keytab ="d:\\xxx.keytab";
private static PreparedStatement ps;
private static Connection conn = null;
private static ResultSet resultSet;
static {
// 或把 krb5.ini 放在 C:\Windows 下
System.setProperty("java.security.krb5.conf", "C:\\ProgramData\\MIT\\Kerberos5\\krb5.conf");
Configuration configuration = new Configuration();
configuration.set("hadoop.security.authentication" , "Kerberos");
UserGroupInformation.setConfiguration(configuration);
try {
UserGroupInformation.loginUserFromKeytab(principal, keytab);
} catch (IOException e) {
e.printStackTrace();
}
}
public static <T> ArrayList<T> query(Class<T> clazz, String sql, Object... args) throws SQLException, IOException {
PreparedStatement ps;
Connection conn = null;
ResultSet resultSet;
try {
// 1.获得连接
conn = DriverManager.getConnection(CONNECTION_URL);
// 2.预编译
ps = conn.prepareStatement(sql);
// 填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
// 3.1执行
resultSet = ps.executeQuery();
// 3.2 获得元数据(数据库的字段)
ResultSetMetaData metaData = resultSet.getMetaData();
// 3.2 获得元数据的个数
int columnCount = metaData.getColumnCount();
ArrayList<T> list = new ArrayList<T>();
// 4.返回结果集
while (resultSet.next()) {
// 反射实例化对象
T t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
// 获得值
Object columnValue = resultSet.getObject(i + 1);
// 获得列名
String columnLabel = metaData.getColumnLabel(i + 1);
// 通过反射调用属性并赋值
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columnValue);
}
//将t对象加到集合
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
conn.close();
}
return null;
}
public static void execute(String sql) throws SQLException {
try {
// 1.获得连接
conn = DriverManager.getConnection(CONNECTION_URL);
// 2.预编译
ps = conn.prepareStatement(sql);
// 3. 执行
ps.executeUpdate();
System.out.println("execute success");
} catch (Exception e) {
e.printStackTrace();
} finally {
conn.close();
}
}
public static void main(String[] args) throws IOException, SQLException {
String sql = "select a,b,c,d,e from aaa";
// String sql = "select a,b,c,d,e from TestConnHiveServer2WithKerbs";
// String sql = "insert overwrite table TestConnHiveServer2WithKerbs select d,e,c from aaa";
// String sql = "drop table TestConnHiveServer2WithKerbs";
// String sql = "create table TestConnHiveServer2WithKerbs as select b,d,a,e,c from aaa";
// execute(sql);
ArrayList<AAATable> alist = query(AAATable.class, sql);
for (AAATable aaa : alist){
System.out.println(aaa.toString());
}
}
}
执行结果见下: