11-03Windows10系统下Hadoop和Hive开发环境搭建填坑指南
source link: http://www.throwable.club/2020/11/03/hadoop-hive-dev-env-in-win-10/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前提
笔者目前需要搭建数据平台,发现了 Windows
系统下, Hadoop
和 Hive
等组件的安装和运行存在大量的坑,而本着有坑必填的目标,笔者还是花了几个晚上的下班时候在多个互联网参考资料的帮助下完成了 Windows10
系统下 Hadoop
和 Hive
开发环境的搭建。这篇文章记录了整个搭建过程中的具体步骤、遇到的问题和对应的解决方案。
环境准备
基于笔者的软件版本洁癖,所有选用的组件都会使用当前(2020-10-30)最高的版本。
软件 版本 备注Windows
10
操作系统
JDK
8
暂时不要选用大于等于 JDK9
的版本,因为启动虚拟机会发生未知异常
MySQL
8.x
用于管理 Hive
的元数据
Apache Hadoop
3.3.0
-
Apache Hive
3.1.2
-
Apache Hive src
1.2.2
因为只有 1.x
版本的 Hive
源码提供了 .bat
启动脚本,有能力可以自己写脚本就不用下此源码包
winutils
hadoop-3.3.0
Hadoop
的 Windows
系统下的启动依赖
下面列举部分组件对应的下载地址:
-
Apache Hadoop 3.3.0
:https://mirror.bit.edu.cn/apache/hadoop/common/hadoop-3.3.0/hadoop-3.3.0.tar.gz
-
Apache Hive 3.1.2
:https://mirrors.bfsu.edu.cn/apache/hive/hive-3.1.2/apache-hive-3.1.2-bin.tar.gz
-
Apache Hive 1.2.2 src
:https://mirrors.bfsu.edu.cn/apache/hive/hive-1.2.2/apache-hive-1.2.2-src.tar.gz
-
winutils
:https://github.com/kontext-tech/winutils
(如果下载速度慢,可以先把仓库导入gitee.com
再下载,或者用笔者已经同步好的仓库https://gitee.com/throwableDoge/winutils
)
下载完这一些列软件之后, MySQL
正常安装为系统服务随系统自启。解压 hadoop-3.3.0.tar.gz
、 apache-hive-3.1.2-bin.tar.gz
、 apache-hive-1.2.2-src.tar.gz
和 winutils
到指定目录:
接着把源码包 apache-hive-1.2.2-src.tar.gz
解压后的 bin
目录下的文件拷贝到 apache-hive-3.1.2-bin
的 bin
目录中:
然后把 winutils
中的 hadoop-3.3.0\bin
目录下的 hadoop.dll
和 winutils.exe
文件拷贝到 Hadoop
的解压目录的 bin
文件夹下:
最后再配置一下 JAVA_HOME
和 HADOOP_HOME
两个环境变量,并且在 Path
中添加 %JAVA_HOME%\bin;
和 %HADOOP_HOME%\bin
:
笔者本地安装的JDK版本为1.8.0.212,理论上任意一个小版本的JDK8都可以。
接着用命令行测试一下,如果上述步骤没问题,控制台输出如下:
配置和启动Hadoop
在 HADOOP_HOME
的 etc\hadoop
子目录下,找到并且修改下面的几个配置文件:
core-site.xml(这里的 tmp
目录一定要配置一个非虚拟目录,别用默认的 tmp
目录,否则后面会遇到权限分配失败的问题)
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/e:/LittleData/hadoop-3.3.0/data/tmp</value> </property> </configuration>
hdfs-site.xml(这里要预先创建 nameNode
和 dataNode
的数据存放目录,注意一下每个目录要以 /
开头,笔者这里预先在 HADOOP_HOME/data
创建了 nameNode
和 dataNode
子目录)
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.http.address</name> <value>0.0.0.0:50070</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/e:/LittleData/hadoop-3.3.0/data/nameNode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/e:/LittleData/hadoop-3.3.0/data/dataNode</value> </property> <property> <name>dfs.permissions.enabled</name> <value>false</value> </property> </configuration>
mapred-site.xml
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration>
yarn-site.xml
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name> <value>org.apache.hadoop.mapred.ShuffleHandler</value> </property> </configuration>
至此,最小化配置基本完成。接着需要格式化 namenode
并且启动 Hadoop
服务。切换至 $HADOOP_HOME/bin
目录下,使用 CMD
输入命令 hdfs namenode -format
(格式化 namenode
切记不要重复执行):
格式化 namenode
完毕后,切换至 $HADOOP_HOME/sbin
目录下,执行 start-all.cmd
脚本:
这里命令行会提示 start-all.cmd
脚本已经过期,建议使用 start-dfs.cmd
和 start-yarn.cmd
替代。同理,如果执行 stop-all.cmd
也会有类似的提示,可以使用 stop-dfs.cmd
和 stop-yarn.cmd
替代。 start-all.cmd
成功执行后,会拉起四个 JVM
实例(见上图中的 Shell
窗口自动新建了四个 Tab
),此时可以通过 jps
查看当前的 JVM
实例:
λ jps 19408 ResourceManager 16324 NodeManager 14792 Jps 15004 NameNode 2252 DataNode
可见已经启动了 ResourceManager
、 NodeManager
、 NameNode
和 DataNode
四个应用,至此 Hadoop
的单机版已经启动成功。通过 stop-all.cmd
命令退出这四个进程。可以通过 http://localhost:8088/
查看调度任务的状态:
通过 http://localhost:50070/
去查看 HDFS
的状态和文件:
重启 Hadoop
的办法:先执行 stop-all.cmd
脚本,再执行 start-all.cmd
脚本。
配置和启动Hive
Hive
是构筑于 HDFS
上的,所以务必确保 Hadoop
已经启动。 Hive
在 HDFS
中默认的文件路径前缀是 /user/hive/warehouse
,因此可以先通过命令行在 HDFS
中创建此文件夹:
hdfs dfs -mkdir /user/hive/warehouse hdfs dfs -chmod -R 777 /user/hive/warehouse
同时需要通过下面的命令创建并为 tmp
目录赋予权限:
hdfs dfs -mkdir /tmp hdfs dfs -chmod -R 777 /tmp
在系统变量中添加 HIVE_HOME
,具体的值配置为 E:\LittleData\apache-hive-3.1.2-bin
,同时在 Path
变量添加 %HIVE_HOME%\bin;
,跟之前配置 HADOOP_HOME
差不多。下载和拷贝一个 mysql-connector-java-8.0.x.jar
到 $HIVE_HOME/lib
目录下:
创建 Hive
的配置文件,在 $HIVE_HOME/conf
目录下已经有对应的配置文件模板,需要拷贝和重命名,具体如下:
-
$HIVE_HOME/conf/hive-default.xml.template
=>$HIVE_HOME/conf/hive-site.xml
-
$HIVE_HOME/conf/hive-env.sh.template
=>$HIVE_HOME/conf/hive-env.sh
-
$HIVE_HOME/conf/hive-exec-log4j.properties.template
=>$HIVE_HOME/conf/hive-exec-log4j.properties
-
$HIVE_HOME/conf/hive-log4j.properties.template
=>$HIVE_HOME/conf/hive-log4j.properties
修改 hive-env.sh
脚本,在尾部添加下面内容:
export HADOOP_HOME=E:\LittleData\hadoop-3.3.0 export HIVE_CONF_DIR=E:\LittleData\apache-hive-3.1.2-bin\conf export HIVE_AUX_JARS_PATH=E:\LittleData\apache-hive-3.1.2-bin\lib
修改 hive-site.xml
文件,主要修改下面的属性项:
hive.metastore.warehouse.dir
/user/hive/warehouse
Hive
的数据存储目录,这个是默认值
hive.exec.scratchdir
/tmp/hive
Hive
的临时数据目录,这个是默认值
javax.jdo.option.ConnectionURL
jdbc:mysql://localhost:3306/hive?characterEncoding=UTF-8&serverTimezone=UTC
Hive
元数据存放的数据库连接
javax.jdo.option.ConnectionDriverName
com.mysql.cj.jdbc.Driver
Hive
元数据存放的数据库驱动
javax.jdo.option.ConnectionUserName
root
Hive
元数据存放的数据库用户
javax.jdo.option.ConnectionPassword
root
Hive
元数据存放的数据库密码
hive.exec.local.scratchdir
E:/LittleData/apache-hive-3.1.2-bin/data/scratchDir
创建本地目录 $HIVE_HOME/data/scratchDir
hive.downloaded.resources.dir
E:/LittleData/apache-hive-3.1.2-bin/data/resourcesDir
创建本地目录 $HIVE_HOME/data/resourcesDir
hive.querylog.location
E:/LittleData/apache-hive-3.1.2-bin/data/querylogDir
创建本地目录 $HIVE_HOME/data/querylogDir
hive.server2.logging.operation.log.location
E:/LittleData/apache-hive-3.1.2-bin/data/operationDir
创建本地目录 $HIVE_HOME/data/operationDir
datanucleus.autoCreateSchema
true
可选
datanucleus.autoCreateTables
true
可选
datanucleus.autoCreateColumns
true
可选
hive.metastore.schema.verification
false
可选
修改完毕之后,在本地的 MySQL
服务新建一个数据库 hive
,编码和字符集可以选用范围比较大的 utf8mb4
(虽然官方建议是 latin1
,但是字符集往大范围选没有影响):
上面的准备工作做完之后,可以进行 Hive
的元数据库初始化,在 $HIVE_HOME/bin
目录下执行下面的脚本:
hive --service schematool -dbType mysql -initSchema
这里有个小坑, hive-site.xml
文件的第 3215
行有个神奇的无法识别的符号:
此无法识别符号会导致 Hive
的命令执行异常,需要去掉。当控制台输出 Initialization script completed schemaTool completed
的时候,说明元数据库已经初始化完毕:
在 $HIVE_HOME/bin
目录下,通过 hive.cmd
可以连接 Hive
(关闭控制台即可退出):
> hive.cmd
尝试创建一个表 t_test
:
hive> create table t_test(id INT,name string); hive> show tables;
查看 http://localhost:50070/
确认 t_test
表已经创建成功。
尝试执行一个写入语句和查询语句:
hive> insert into t_test(id,name) values(1,'throwx'); hive> select * from t_test;
写用了 30
多秒,读用了 0.165
秒。
使用JDBC连接Hive
HiveServer2
是 Hive
服务端接口模块,必须启动此模块,远程客户端才能对 Hive
进行数据写入和查询。目前,此模块还是基于 Thrift RPC
实现,它是 HiveServer
的改进版,支持多客户端接入和身份验证等功能。配置文件 hive-site.xml
中可以修改下面几个关于 HiveServer2
的常用属性:
hive.server2.thrift.min.worker.threads
5
最小工作线程数,默认值为5
hive.server2.thrift.max.worker.threads
500
最大工作线程数,默认值为500
hive.server2.thrift.port
10000
侦听的 TCP
端口号,默认值为10000
hive.server2.thrift.bind.host
127.0.0.1
绑定的主机,默认值为 127.0.0.1
hive.execution.engine
mr
执行引擎,默认值为 mr
在 $HIVE_HOME/bin
目录下执行下面的命令可以启动 HiveServer2
:
hive.cmd --service hiveserver2
客户端需要引入 hadoop-common
和 hive-jdbc
依赖,依赖的版本尽量和对接的 Hadoop
和 Hive
版本对应。
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.apache.hive</groupId> <artifactId>hive-jdbc</artifactId> <version>3.1.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> <version>2.3.5.RELEASE</version> </dependency>
hadoop-common
依赖链比较长,会连带下载大量其他相关依赖,所以可以找个空闲时间在某个 Maven
项目先挂起该依赖下载的任务(笔者挂起此依赖下载任务洗完澡仍然没下完,还会出现 org.glassfish:javax.el
的快照包无法下载的问题,不过不影响正常使用)。最后添加一个单元测试类 HiveJdbcTest
:
@Slf4j public class HiveJdbcTest { private static JdbcTemplate TEMPLATE; private static HikariDataSource DS; @BeforeClass public static void beforeClass() throws Exception { HikariConfig config = new HikariConfig(); config.setDriverClassName("org.apache.hive.jdbc.HiveDriver"); // 这里笔者修改过hive-site.xml的对应配置,因为端口不是默认的10000 // config.setJdbcUrl("jdbc:hive2://127.0.0.1:10091"); config.setJdbcUrl("jdbc:hive2://127.0.0.1:10091/db_test"); DS = new HikariDataSource(config); TEMPLATE = new JdbcTemplate(DS); } @AfterClass public static void afterClass() throws Exception { DS.close(); } @Test public void testCreateDb() throws Exception { TEMPLATE.execute("CREATE DATABASE db_test"); } @Test public void testCreateTable() throws Exception { TEMPLATE.execute("CREATE TABLE IF NOT EXISTS t_student(id INT,name string,major string)"); log.info("创建t_student表成功"); } @Test public void testInsert() throws Exception { int update = TEMPLATE.update("INSERT INTO TABLE t_student(id,name,major) VALUES(?,?,?)", p -> { p.setInt(1, 10087); p.setString(2, "throwable"); p.setString(3, "math"); }); log.info("写入t_student成功,更新记录数:{}", update); // 这里比较神奇,数据写入了,返回的update数量为0 } @Test public void testSelect() throws Exception { List<Student> result = TEMPLATE.query("SELECT * FROM t_student", rs -> { List<Student> list = new ArrayList<>(); while (rs.next()) { Student student = new Student(); student.setId(rs.getLong("id")); student.setName(rs.getString("name")); student.setMajor(rs.getString("major")); list.add(student); } return list; }); // 打印日志:查询t_student成功,结果:[HiveJdbcTest.Student(id=10087, name=throwable, major=math)] log.info("查询t_student成功,结果:{}", result); } @Data private static class Student { private Long id; private String name; private String major; } }
可能遇到的问题
下面小结一下可能遇到的问题。
Java虚拟机启动失败
目前定位到是 Hadoop
无法使用 JDK[9+
的任意版本 JDK
,建议切换为任意 JDK8
的小版本。
出现找不到Hadoop执行文件异常
确保已经把 winutils
中的 hadoop-3.3.0\bin
目录下的 hadoop.dll
和 winutils.exe
文件拷贝到 Hadoop
的解压目录的 bin
文件夹中。
start-all.cmd
脚本执行时有可能出现找不到批处理脚本的异常。此问题在公司的开发机出现过,在家用的开发机没有重现,具体解决方案是在 start-all.cmd
脚本的首行加入 cd $HADOOP_HOME
,如 cd E:\LittleData\hadoop-3.3.0
。
无法访问localhost:50070
一般是因为 hdfs-site.xml
配置遗漏了 dfs.http.address
配置项,添加:
<property> <name>dfs.http.address</name> <value>0.0.0.0:50070</value> </property>
然后调用 stop-all.cmd
,再调用 start-all.cmd
重启 Hadoop
即可。
Hive连接MySQL异常
注意 MySQL
的驱动包是否已经正确拷贝到 $HIVE_HOME/lib
下,并且检查 javax.jdo.option.ConnectionURL
等四个属性是否配置正确。如果都正确,注意是否 MySQL
的版本存在问题,或者服务的版本与驱动版本不匹配。
Hive找不到批处理文件
一般描述是 'xxx.cmd' is not recognized as an internal or external command...
,一般是 Hive
的命令执行时的异常,需要把 Hive 1.x
的源码包的 bin
目录下的所有 .cmd
脚本拷贝到 $HIVE_HOME/bin
对应的目录下。
文件夹权限问题
常见如 CreateSymbolicLink
异常,会导致 Hive
无法使用 INSERT
或者 LOAD
命令写入数据。出现这类问题可以通过下面方式解决:
-
Win + R
然后运行gpedit.msc
- 计算机设置 -Windows
设置 — 安全设置 - 本地策略 - 用户权限分配 - 创建符号链接 - 添加当前用户。
或者 直接使用管理员账号或者管理员权限启动 CMD
,然后执行对应的脚本启动 Hadoop
或者 Hive
。
SessionNotRunning异常
启动 HiveServer2
中或者外部客户端连接 HiveServer2
时候有可能出现此异常,具体是 java.lang.ClassNotFoundException: org.apache.tez.dag.api.TezConfiguration
的异常。解决方案是:配置文件 hive-site.xml
中的 hive.execution.engine
属性值由 tez
修改为 mr
,然后重启 HiveServer2
即可。因为没有集成 tez
,重启后依然会报错,但是 60000
ms后会自动重试启动(一般重试后会启动成功):
这算是一个遗留问题,但是不影响客户端正常连接,只是启动时间会多了 60
秒。
HiveServer2端口冲突
修改配置文件 hive-site.xml
中的 hive.server2.thrift.port
属性值为未被占用的端口,重启 HiveServer2
即可。
数据节点安全模式异常
一般是出现 SafeModeException
异常,提示 Safe mode is ON
。通过命令 hdfs dfsadmin -safemode leave
解除安全模式即可。
AuthorizationException
常见的是 Hive
通过 JDBC
客户端连接 HiveServer2
服务时候会出现这个异常,具体是信息是: User: xxx is not allowed to impersonate anonymous
。这种情况只需要修改 Hadoop
的配置文件 core-site.xml
,添加:
<property> <name>hadoop.proxyuser.xxx.hosts</name> <value>*</value> </property> <property> <name>hadoop.proxyuser.xxx.groups</name> <value>*</value> </property>
这里的xxx是指报错时候具体的系统用户名,例如笔者开发机的系统用户名为doge
然后重启 Hadoop
服务即可。
MapRedTask的权限问题
常见的是 Hive
通过 JDBC
客户端连接 HiveServer2
服务执行 INSERT
或者 LOAD
操作时候抛出的异常,一般描述是 Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask. Permission denied: user=anonymous, access=EXECUTE, inode="/tmp/hadoop-yarn":xxxx:supergroup:drwx------
。通过命令 hdfs dfs -chmod -R 777 /tmp
赋予匿名用户 /tmp
目录的读写权限即可。
小结
没什么事最好还是直接在 Linux
或者 Unix
系统中搭建 Hadoop
和 Hive
的开发环境比较合理, Windows
系统的文件路径和权限问题会导致很多意想不到的问题。本文参考了大量互联网资料和 Hadoop
和 Hive
的入门书籍,这里就不一一贴出,站在巨人的肩膀上。
(本文完 c-4-d e-a-20201102)
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK