《大数据技术基础》课程机房上机实验报告 | |||||
题目 | 实验1.熟悉常用Linux的操作和Hadoop操作 | 姓名 | 软件工程21-1班3212052051354朱扬宇 | 日期 | 2024年5月14日 |
实验环境:操作系统:Linux;Hadoop版本:3.1.3。 | |||||
实验内容与完成情况: (一)安装Linux虚拟机 1.Ubuntn系统准备 2.VMware上安装Ubuntn系统 创建新的虚拟机,选择自定义(高级),点击下一步。 查看版本和硬件兼容性之后点击下一步 选择稍后安装虚拟机,点击下一步。 按默认,继续下一步。 给自己的虚拟机命名,并且选择安装路径。 根据自己的电脑配置调整处理器的数量和内核数 选择16GB,点击下一步。 选择网络地址转化,点击下一步。 默认,点击下一步。 选择创建新的磁盘,点击下一步 选择将磁盘拆分为多个文件。 得到虚拟机 导入映像文件 开启虚拟机,就可以进行实验了。 (二)创建hadoop用户 输入如下命令创建新用户 : sudo useradd -m hadoop -s /bin/bash 接着使用如下命令设置密码,可简单设置为 hadoop,按提示输入两次密码: sudo passwd hadoop 为 hadoop 用户增加管理员权限: sudo adduser hadoop sudo 更新apt:用 hadoop 用户登录后,执行如下命令: sudo apt-get update 安装vim sudo apt-get install vim 安装 SSH server: sudo apt-get install openssh-server 安装后,可以使用如下命令登陆本机: ssh localhost 但这样登陆是需要每次输入密码的,我们需要配置成SSH无密码登陆比较方便。首先退出刚才的 ssh,就回到了我们原先的终端窗口,然后利用 ssh-keygen 生成密钥,并将密钥加入到授权中: exit # 退出刚才的 ssh localhost cd ~/.ssh/ # 若没有该目录,请先执行一次ssh localhost ssh-keygen -t rsa # 会有提示,都按回车就可以 cat ./id_rsa.pub >> ./authorized_keys # 加入授权 一些需要的东西已经下好了 安装JDK1.8 cd /usr/lib sudo mkdir jvm #创建/usr/lib/jvm目录用来存放JDK文件 cd ~ #进入hadoop用户的主目录 cd 下载 #注意区分大小写字母,刚才已经通过FTP软件把JDK安装包jdk-8u162-linux-x64.tar.gz上传到该目录下 sudo tar -zxvf ./jdk-8u162-linux-x64.tar.gz -C /usr/lib/jvm #把JDK文件解压到/usr/lib/jvm目录下 JDK文件解压缩以后,可以执行如下命令到/usr/lib/jvm目录查看一下: 下面继续执行如下命令,设置环境变量: cd ~ vim ~/.bashrc 在这个文件的开头位置,添加如下几行内容: export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_162 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH 继续执行如下命令让.bashrc文件的配置立即生效: source ~/.bashrc 使用如下命令查看是否安装成功: java -version 将 Hadoop 安装至 /usr/local/ 中: sudo tar -zxf ~/下载/hadoop-3.1.3.tar.gz -C /usr/local # 解压到/usr/local中 cd /usr/local/ sudo mv ./hadoop-3.1.3/ ./hadoop # 将文件夹名改为hadoop sudo chown 777 hadoop ./hadoop # 修改文件权限 Hadoop 解压后即可使用。输入如下命令来检查 Hadoop 是否可用,成功则会显示 Hadoop 版本信息: 修改配置文件 core-site.xml <configuration> <property> <name>hadoop.tmp.dir</name> <value>file:/usr/local/hadoop/tmp</value> <description>Abase for other temporary directories.</description> </property> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> </configuration> 修改配置文件 hdfs-site.xml: <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/usr/local/hadoop/tmp/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/usr/local/hadoop/tmp/dfs/data</value> </property> </configuration> 配置完成后,执行 NameNode 的格式化: cd /usr/local/hadoop ./bin/hdfs namenode -format 接着开启 NameNode 和 DataNode 守护进程。 cd /usr/local/hadoop ./sbin/start-dfs.sh #start-dfs.sh是个完整的可执行文件,中间没有空格 启动完成后,可以通过命令 jps 来判断是否成功启动,若成功启动则会列出如下进程: "NameNode"、"DataNode" 和 "SecondaryNameNode"(如果 SecondaryNameNode 没有启动,请运行 sbin/stop-dfs.sh 关闭进程,然后再次尝试启动尝试)。如果没有 NameNode 或 DataNode ,那就是配置不成功,请仔细检查之前步骤,或通过查看启动日志排查原因。 成功启动后,可以访问 Web 界面 http://localhost:9870 查看 NameNode 和 Datanode 信息,还可以在线查看 HDFS 中的文件。 (三)熟悉常用的Linux操作 请按要求上机实践如下linux基本命令。 cd命令:切换目录 (1)切换到目录 /usr/local cd /usr/local (2)去到目前的上层目录 cd .. (3)回到自己的主文件夹 cd ~ ls命令:查看文件与目录 (4)查看目录/usr下所有的文件 ls /usr mkdir命令:新建新目录 (5)进入/tmp目录,创建一个名为a的目录,并查看有多少目录存在 cd /tmp mkdir a ls | wc -l (6)创建目录a1/a2/a3/a4 mkdir -p a1/a2/a3/a4 rmdir命令:删除空的目录 (7)将上例创建的目录a(/tmp下面)删除 rmdir /tmp/a (8)删除目录a1/a2/a3/a4,查看有多少目录存在 rm -r a1; ls | wc -l cp命令:复制文件或目录 (9)将主文件夹下的.bashrc复制到/usr下,命名为bashrc1 cp ~/.bashrc /usr/bashrc1 (10)在/tmp下新建目录test,再复制这个目录内容到/usr mkdir /tmp/test; cp -r /tmp/test /usr mv命令:移动文件与目录,或更名 (11)将上例文件bashrc1移动到目录/usr/test mv /usr/bashrc1 /usr/test (12)将上例test目录重命名为test2 mv /tmp/test /tmp/test2 rm命令:移除文件或目录 (13)将上例复制的bashrc1文件删除 rm /usr/bashrc1 (14)将上例的test2目录删除 rm -r /tmp/test2 cat命令:查看文件内容 (15)查看主文件夹下的.bashrc文件内容 cat ~/.bashrc tac命令:反向列示 (16)反向查看主文件夹下.bashrc文件内容 tac ~/.bashrc more命令:一页一页翻动查看 (17)翻页查看主文件夹下.bashrc文件内容 more ~/.bashrc 每次enter查看内容%会增加 head命令:取出前面几行 (18)查看主文件夹下.bashrc文件内容前20行. head -20 ~/.bashrc (19)查看主文件夹下.bashrc文件内容,后面50行不显示,只显示前面几行 head ~/.bashrc 只查看前20行: 后面50行不显示,只显示前面几行: tail命令:取出后面几行 (20)查看主文件夹下.bashrc文件内容最后20行 tail -20 ~/.bashrc (21) 查看主文件夹下.bashrc文件内容,只列出50行以后的数据 tail -n +50 ~/.bashrc 最后20行: 50行之后: touch命令:修改文件时间或创建新文件 (22)在/tmp下创建一个空文件hello并查看时间 touch /tmp/hello; ls -l /tmp/hello (23)修改hello文件,将日期调整为5天前 touch -d '5 days ago' /tmp/hello; ls -l /tmp/hello chown命令:修改文件所有者权限 (24)将hello文件所有者改为root帐号,并查看属性 sudo chown root /tmp/hello; ls -l /tmp/hello find命令:文件查找 (25)找出主文件夹下文件名为.bashrc的文件 find ~ -name .bashrc tar命令:压缩命令 (26)在/目录下新建文件夹test,然后在/目录下打包成test.tar.gz mkdir /test; tar -czvf test.tar.gz /test (27)解压缩到/tmp目录 tar -xzvf test.tar.gz -C /tmp grep命令:查找字符串 (28)从~/.bashrc文件中查找字符串'examples' grep 'examples' ~/.bashrc (29)配置Java环境变量,在~/.bashrc中设置 echo 'export JAVA_HOME=/path/to/java' >> ~/.bashrc (30)查看JAVA_HOME变量的值 source ~/.bashrc; echo $JAVA_HOME (四)熟悉常用的Hadoop操作 (31)启动hadoop,在HDFS中创建用户目录(现在已经在hadoop目录/usr/local/hadoop) ./sbin/start-dfs.sh ;hdfs dfs -mkdir -p /user/hadoop (32)接着在此用户目录下创建text文件夹,并查看文件列表 hdfs dfs -mkdir test; hdfs dfs -ls (33)将~/.bashrc文件上传到HDFS的test文件夹,并查看test hdfs dfs -put ~/.bashrc test;hdfs dfs -ls test
hdfs dfs -get test ./test | |||||
出现的问题: 1.虚拟机安装Linux时卡住或报错。 2.Hadoop启动失败,无法识别NameNode或DataNode。 3.SSH无密码登陆配置不成功。 4.Java或Hadoop环境变量设置不成功,导致命令行找不到java或hadoop命令。 5.Linux基本命令执行结果不如预期。 6.hadoop:未找到命令 | |||||
解决方案(列出遇到的问题和解决办法,列出没有解决的问题): 1.问题:虚拟机安装Linux时卡住或报错。 解决方案:确保虚拟机设置中的内存和处理器核心数适合您的系统。检查ISO镜像文件是否完整未损坏。尝试使用不同版本的VMware或VirtualBox。 2.问题:Hadoop启动失败,无法识别NameNode或DataNode。 解决方案:确保Hadoop的配置文件core-site.xml和hdfs-site.xml正确无误。查看Hadoop日志文件,通常位于$HADOOP_HOME/logs/目录下,以了解具体错误信息。重新格式化NameNode(注意:这将清除所有HDFS数据):hdfs namenode -format 3.问题:SSH无密码登陆配置不成功。 解决方案:确保.ssh/authorized_keys文件中包含了您的公钥。检查目录及文件权限,确保.ssh目录权限为700,authorized_keys文件权限为600。检查SSH服务的配置文件/etc/ssh/sshd_config,确保无密码登录被允许。 4.问题:Java或Hadoop环境变量设置不成功,导致命令行找不到java或hadoop命令。 解决方案:确保.bashrc或.profile中设置的环境变量正确,并且没有语法错误。使用source ~/.bashrc重新加载环境变量。使用echo $PATH和echo $JAVA_HOME检查环境变量是否已正确设置。 5.问题:Linux基本命令执行结果不如预期。 解决方案:确保命令的语法正确;使用man命令查看命令的使用手册,如man ls。 6.问题hadoop:未找到命令; 解决方案:vim ~/.bashrc export PATH=$PATH:/usr/local/hadoop/bin:/usr/local/hadoop/sbin 未解决问题: 2024-05-30 17:08:12,696 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable。这个问题一般不会阻止Hadoop的运行,但可能会影响性能,因为Java实现相比本地实现通常速度较慢,但是可以用,所以我未解决。 |
《大数据技术基础》课程机房上机实验报告 | |||||
题目 | 实验二.Hadoop3.1.3安装教程单机/伪分布式配置 | 姓名 | 软件工程21-1班3212052051354朱扬宇 | 日期 | 2024年5月20日 |
实验环境:操作系统:Linux;Hadoop版本:3.1.3;JDK版本:1.8版本; | |||||
实验内容与完成情况: 1.创建hadoop用户 如果你安装 Ubuntu 的时候不是用的 "hadoop" 用户,那么需要增加一个名为 hadoop 的用户。首先按 ctrl+alt+t 打开终端窗口,输入如下命令创建新用户 : sudo useradd -m hadoop -s /bin/bash 接着使用如下命令设置密码,可简单设置为 hadoop,按提示输入两次密码: sudo passwd hadoop 为 hadoop 用户增加管理员权限: sudo adduser hadoop sudo 2.更新apt 更新apt:用 hadoop 用户登录后,执行如下命令: sudo apt-get update 安装vim sudo apt-get install vim 3.安装SSH、配置SSH无密码登陆 安装 SSH server: sudo apt-get install openssh-server 安装后,可以使用如下命令登陆本机: ssh localhost 但这样登陆是需要每次输入密码的,我们需要配置成SSH无密码登陆比较方便。首先退出刚才的 ssh,就回到了我们原先的终端窗口,然后利用 ssh-keygen 生成密钥,并将密钥加入到授权中: exit # 退出刚才的 ssh localhost cd ~/.ssh/ # 若没有该目录,请先执行一次ssh localhost ssh-keygen -t rsa # 会有提示,都按回车就可以 cat ./id_rsa.pub >> ./authorized_keys # 加入授权 4.安装Java环境 安装JDK1.8 cd /usr/lib sudo mkdir jvm #创建/usr/lib/jvm目录用来存放JDK文件 cd ~ #进入hadoop用户的主目录 cd 下载 #注意区分大小写字母,刚才已经通过FTP软件把JDK安装包jdk-8u162-linux-x64.tar.gz上传到该目录下 sudo tar -zxvf ./jdk-8u162-linux-x64.tar.gz -C /usr/lib/jvm #把JDK文件解压到/usr/lib/jvm目录下 JDK文件解压缩以后,可以执行如下命令到/usr/lib/jvm目录查看一下: 下面继续执行如下命令,设置环境变量: cd ~ vim ~/.bashrc 在这个文件的开头位置,添加如下几行内容: export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_162 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH 继续执行如下命令让.bashrc文件的配置立即生效: source ~/.bashrc 使用如下命令查看是否安装成功: java -version 5.安装 Hadoop3.1.3 将 Hadoop 安装至 /usr/local/ 中: sudo tar -zxf ~/下载/hadoop-3.1.3.tar.gz -C /usr/local # 解压到/usr/local中 cd /usr/local/ sudo mv ./hadoop-3.1.3/ ./hadoop # 将文件夹名改为hadoop sudo chown 777 hadoop ./hadoop # 修改文件权限 Hadoop 解压后即可使用。输入如下命令来检查 Hadoop 是否可用,成功则会显示 Hadoop 版本信息: 6.Hadoop单机配置(非分布式) Hadoop 默认模式为非分布式模式(本地模式),无需进行其他配置即可运行。非分布式即单 Java 进程,方便进行调试。现在我们可以执行例子来感受下 Hadoop 的运行。Hadoop 附带了丰富的例子(运行 ./bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar 可以看到所有例子),包括 wordcount、terasort、join、grep 等。 在此我们选择运行 grep 例子,我们将 input 文件夹中的所有文件作为输入,筛选当中符合正则表达式 dfs[a-z.]+ 的单词并统计出现的次数,最后输出结果到 output 文件夹中。 7.Hadoop伪分布式配置 Hadoop 的配置文件位于 /usr/local/hadoop/etc/hadoop/ 中,伪分布式需要修改2个配置文件 core-site.xml 和 hdfs-site.xml 。Hadoop的配置文件是 xml 格式,每个配置以声明 property 的 name 和 value 的方式来实现。 修改配置文件 core-site.xml <configuration> <property> <name>hadoop.tmp.dir</name> <value>file:/usr/local/hadoop/tmp</value> <description>Abase for other temporary directories.</description> </property> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> </configuration> 修改配置文件 hdfs-site.xml: <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/usr/local/hadoop/tmp/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/usr/local/hadoop/tmp/dfs/data</value> </property> </configuration> 配置完成后,执行 NameNode 的格式化: cd /usr/local/hadoop ./bin/hdfs namenode -format 接着开启 NameNode 和 DataNode 守护进程。 cd /usr/local/hadoop ./sbin/start-dfs.sh #start-dfs.sh是个完整的可执行文件,中间没有空格 启动完成后,可以通过命令 jps 来判断是否成功启动,若成功启动则会列出如下进程: "NameNode"、"DataNode" 和 "SecondaryNameNode"(如果 SecondaryNameNode 没有启动,请运行 sbin/stop-dfs.sh 关闭进程,然后再次尝试启动尝试)。如果没有 NameNode 或 DataNode ,那就是配置不成功,请仔细检查之前步骤,或通过查看启动日志排查原因。 成功启动后,可以访问 Web 界面 http://localhost:9870 查看 NameNode 和 Datanode 信息,还可以在线查看 HDFS 中的文件。 7.运行Hadoop伪分布式实例 伪分布式读取的则是 HDFS 上的数据。要使用 HDFS,首先需要在 HDFS 中创建用户目录:./bin/hdfs dfs -mkdir -p /user/hadoop 接着将 ./etc/hadoop 中的 xml 文件作为输入文件复制到分布式文件系统中,即将 /usr/local/hadoop/etc/hadoop 复制到分布式文件系统中的 /user/hadoop/input 中。我们使用的是 hadoop 用户,并且已创建相应的用户目录 /user/hadoop ,因此在命令中就可以使用相对路径如 input,其对应的绝对路径就是 /user/hadoop/input: ./bin/hdfs dfs -mkdir input ./bin/hdfs dfs -put ./etc/hadoop/*.xml input ./bin/hdfs dfs -ls input 伪分布式运行 MapReduce 作业的方式跟单机模式相同,区别在于伪分布式读取的是HDFS中的文件(可以将单机步骤中创建的本地 input 文件夹,输出结果 output 文件夹都删掉来验证这一点)。 ./bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar grep input output 'dfs[a-z.]+' 查看运行结果的命令(查看的是位于 HDFS 中的输出结果): ./bin/hdfs dfs -cat output/* 我们也可以将运行结果取回到本地: rm -r ./output # 先删除本地的 output 文件夹(如果存在) ./bin/hdfs dfs -get output ./output # 将 HDFS 上的 output 文件夹拷贝到本机 cat ./output/* Hadoop 运行程序时,输出目录不能存在,否则会提示错误 "org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://localhost:9000/user/hadoop/output already exists" ,因此若要再次执行,需要执行如下命令删除 output 文件夹: ./bin/hdfs dfs -rm -r output # 删除 output 文件夹 运行程序时,输出目录不能存在: 运行 Hadoop 程序时,为了防止覆盖结果,程序指定的输出目录(如 output)不能存在,否则会提示错误,因此运行前需要先删除输出目录。在实际开发应用程序时,可考虑在程序中加上如下代码,能在每次运行时自动删除输出目录,避免繁琐的命令行操作: Configuration conf = new Configuration(); Job job = new Job(conf); /* 删除输出目录 */ Path outputPath = new Path(args[1]); outputPath.getFileSystem(conf).delete(outputPath, true); | |||||
出现的问题: 1.问题:虚拟机安装Linux时卡住或报错。 2.问题:Hadoop启动失败,无法识别NameNode或DataNode。 3.问题:SSH无密码登陆配置不成功。 4.问题:Java或Hadoop环境变量设置不成功,导致命令行找不到java或hadoop命令。 | |||||
解决方案(列出遇到的问题和解决办法,列出没有解决的问题): 1.问题:虚拟机安装Linux时卡住或报错。 解决方案:确保虚拟机设置中的内存和处理器核心数适合我的系统。检查ISO镜像文件是否完整未损坏。尝试使用不同版本的VMware 2.问题:Hadoop启动失败,无法识别NameNode或DataNode。 解决方案:确保Hadoop的配置文件core-site.xml和hdfs-site.xml正确无误。查看Hadoop日志文件,通常位于$HADOOP_HOME/logs/目录下,以了解具体错误信息。重新格式化NameNode(注意:这将清除所有HDFS数据):hdfs namenode -format 3.问题:SSH无密码登陆配置不成功。 解决方案:确保.ssh/authorized_keys文件中包含了您的公钥。检查目录及文件权限,确保.ssh目录权限为700,authorized_keys文件权限为600。检查SSH服务的配置文件/etc/ssh/sshd_config,确保无密码登录被允许。 4.问题:Java或Hadoop环境变量设置不成功,导致命令行找不到java或hadoop命令。 解决方案:确保.bashrc或.profile中设置的环境变量正确,并且没有语法错误。使用source ~/.bashrc重新加载环境变量。使用echo $PATH和echo $JAVA_HOME检查环境变量是否已正确设置。 未解决的问题: 2024-05-30 17:08:12,696 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable。这个问题一般不会阻止Hadoop的运行,但可能会影响性能,因为Java实现相比本地实现通常速度较慢,但是可以用,所以我未解决。 |
《大数据技术基础》课程机房上机实验报告 | |||||
题目 | 实验三.HDFS编程实践(Hadoop3.1.3) | 姓名 | 软件工程21-1班3212052051354朱扬宇 | 日期 | 2024年6月29日 |
实验环境:操作系统:Linux;Hadoop版本:3.1.3;JDK版本:1.8版本;Java IDE:Eclipse。 | |||||
实验内容与完成情况: 一、利用Shell命令与HDFS进行交互 Hadoop支持很多Shell命令,其中fs是HDFS最常用的命令,利用fs可以查看HDFS文件系统的目录结构、上传和下载数据、创建文件等。 注意: 教材《大数据技术原理与应用》的命令是以"./bin/hadoop dfs"开头的Shell命令方式,实际上有三种shell命令方式。 1. hadoop fs 2. hadoop dfs 3. hdfs dfs hadoop fs适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统 hadoop dfs只能适用于HDFS文件系统 hdfs dfs跟hadoop dfs的命令作用一样,也只能适用于HDFS文件系统 我们可以在终端输入如下命令,查看fs总共支持了哪些命令 ./bin/hadoop fs 在终端输入如下命令,可以查看具体某个命令的作用 例如:我们查看put命令如何使用,可以输入如下命令 ./bin/hadoop fs -help put 二.目录操作 Hadoop系统安装好以后,第一次使用HDFS时,需要首先在HDFS中创建用户目录。本教程全部采用hadoop用户登录Linux系统,因此,需要在HDFS中为hadoop用户创建一个用户目录,命令如下: cd /usr/local/hadoop ./bin/hdfs dfs -mkdir -p /user/hadoop “/user/hadoop”目录就成为hadoop用户对应的用户目录,可以使用如下命令显示HDFS中与当前用户hadoop对应的用户目录下的内容: ./bin/hdfs dfs -ls . 该命令中,“-ls”表示列出HDFS某个目录下的所有内容,“.”表示HDFS中的当前用户目录,也就是“/user/hadoop”目录,因此,上面的命令和下面的命令是等价的: ./bin/hdfs dfs -ls /user/hadoop 下面,可以使用如下命令创建一个input目录: ./bin/hdfs dfs -mkdir input 在创建个input目录时,采用了相对路径形式,实际上,这个input目录创建成功以后,它在HDFS中的完整路径是“/user/hadoop/input”。如果要在HDFS的根目录下创建一个名称为input的目录,则需要使用如下命令: ./bin/hdfs dfs -mkdir /input 可以使用rm命令删除一个目录,比如,可以使用如下命令删除刚才在HDFS中创建的“/input”目录(不是“/user/hadoop/input”目录): ./bin/hdfs dfs -rm -r /input 三.文件操作 在实际应用中,经常需要从本地文件系统向HDFS中上传文件,或者把HDFS中的文件下载到本地文件系统中。 首先,使用vim编辑器,在本地Linux文件系统的“/home/hadoop/”目录下创建一个文件myLocalFile.txt,里面可以随意输入一些单词,比如,输入如下三行: Hadoop Spark XMU DBLAB cd /home/hadoop/ vim myLocalFile.txt 然后,可以使用如下命令把本地文件系统的“/home/hadoop/myLocalFile.txt”上传到HDFS中的当前用户目录的input目录下,也就是上传到HDFS的“/user/hadoop/input/”目录下: ./bin/hdfs dfs -put /home/hadoop/myLocalFile.txt input 可以使用ls命令查看一下文件是否成功上传到HDFS中,具体如下: ./bin/hdfs dfs -ls input 下面使用如下命令查看HDFS中的myLocalFile.txt这个文件的内容: ./bin/hdfs dfs -cat input/myLocalFile.txt 下面把HDFS中的myLocalFile.txt文件下载到本地文件系统中的“/home/hadoop/下载/”这个目录下,命令如下: ./bin/hdfs dfs -get input/myLocalFile.txt /home/hadoop/下载 可以使用如下命令,到本地文件系统查看下载下来的文件myLocalFile.txt: cd ~ cd 下载 ls cat myLocalFile.txt 最后,了解一下如何把文件从HDFS中的一个目录拷贝到HDFS中的另外一个目录。比如,如果要把HDFS的“/user/hadoop/input/myLocalFile.txt”文件,拷贝到HDFS的另外一个目录“/input”中(注意,这个input目录位于HDFS根目录下),可以使用如下命令: ./bin/hdfs dfs -cp input/myLocalFile.txt /input 四、利用Web界面管理HDFS 打开Linux自带的Firefox浏览器,点击打开WEB界面的访问地址http://localhost:9870,即可看到HDFS的web管理界面。 五、利用Java API与HDFS进行交互 在Ubuntu中安装Eclipse Eclipse是常用的程序开发工具,本教程很多程序代码都是使用Eclipse开发调试,因此,需要在Linux系统中安装Eclipse。可以到Eclipse官网(https://www.eclipse.org/downloads/)下载安装包。或者直接点击这里从百度云盘下载软件(提取码:lnwl),位于“软件”目录下,文件名是eclipse-4.7.0-linux.gtk.x86_64.tar.gz。假设安装文件下载后保存在了Linux系统的目录“~/Downloads”下,下面执行如下命令对文件进行解压缩: cd ~/Downloads sudo tar -zxvf ./eclipse-4.7.0-linux.gtk.x86_64.tar.gz -C /usr/local 3 cd /usr/local/eclipse ./eclipse 在Eclipse创建项目 第一次打开Eclipse,需要填写workspace(工作空间),用来保存程序所在的位置,这里按照默认,不需要改动,如下图 可以看出,由于当前是采用hadoop用户登录了Linux系统,因此,默认的工作空间目录位于hadoop用户目录“/home/hadoop”下。 Eclipse启动以后,会呈现如下图所示的界面。 选择“File->New->Java Project”菜单,开始创建一个Java工程,会弹出如图所示界面。 在“Project name”后面输入工程名称“HDFSExample”,选中“Use default location”,让这个Java工程的所有文件都保存到“/home/hadoop/workspace/HDFSExample”目录下。在“JRE”这个选项卡中,可以选择当前的Linux系统中已经安装好的JDK,比如java-8-openjdk-amd64。然后,点击界面底部的“Next>”按钮,进入下一步的设置。 进入下一步的设置以后,会弹出如图4-5所示界面。 需要在这个界面中加载该Java工程所需要用到的JAR包,这些JAR包中包含了可以访问HDFS的Java API。这些JAR包都位于Linux系统的Hadoop安装目录下,对于本教程而言,就是在“/usr/local/hadoop/share/hadoop”目录下。点击界面中的“Libraries”选项卡,然后,点击界面右侧的“Add External JARs…”按钮,会弹出如图所示界面。 为了编写一个能够与HDFS交互的Java应用程序,一般需要向Java工程中添加以下JAR包: (1)"/usr/local/hadoop/share/hadoop/common”目录下的hadoop-common-2.7.1.jar和haoop-nfs-2.7.1.jar; (2)/usr/local/hadoop/share/hadoop/common/lib”目录下的所有JAR包; (3)“/usr/local/hadoop/share/hadoop/hdfs”目录下的haoop-hdfs-2.7.1.jar和haoop-hdfs-nfs-2.7.1.jar; (4)“/usr/local/hadoop/share/hadoop/hdfs/lib”目录下的所有JAR包。 然后就可以进行实验了。 六. 编写Java应用程序 下面编写一个Java应用程序。 请在Eclipse工作界面左侧的“Package Explorer”面板中(如下图所示),找到刚才创建好的工程名称“HDFSExample”,然后在该工程名称上点击鼠标右键,在弹出的菜单中选择“New-->Class”菜单。 选择“New-->Class”菜单以后会出现如下图所示界面。 在该界面中,只需要在“Name”后面输入新建的Java类文件的名称,这里采用名称“MergeFile”,其他都可以采用默认设置,然后,点击界面右下角“Finish”按钮,出现如下图所示界面。 可以看出,Eclipse自动创建了一个名为“MergeFile.java”的源代码文件,请在该文件中输入以下代码: import java.io.IOException; import java.io.PrintStream; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; /** * 过滤掉文件名满足特定条件的文件 */ class MyPathFilter implements PathFilter { String reg = null; MyPathFilter(String reg) { this.reg = reg; } public boolean accept(Path path) { if (!(path.toString().matches(reg))) return true; return false; } } /*** * 利用FSDataOutputStream和FSDataInputStream合并HDFS中的文件 */ public class MergeFile { Path inputPath = null; //待合并的文件所在的目录的路径 Path outputPath = null; //输出文件的路径 public MergeFile(String input, String output) { this.inputPath = new Path(input); this.outputPath = new Path(output); } public void doMerge() throws IOException { Configuration conf = new Configuration(); conf.set("fs.defaultFS","hdfs://localhost:9000"); conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem"); FileSystem fsSource = FileSystem.get(URI.create(inputPath.toString()), conf); FileSystem fsDst = FileSystem.get(URI.create(outputPath.toString()), conf); //下面过滤掉输入目录中后缀为.abc的文件 FileStatus[] sourceStatus = fsSource.listStatus(inputPath, new MyPathFilter(".*\\.abc")); FSDataOutputStream fsdos = fsDst.create(outputPath); PrintStream ps = new PrintStream(System.out); //下面分别读取过滤之后的每个文件的内容,并输出到同一个文件中 for (FileStatus sta : sourceStatus) { //下面打印后缀不为.abc的文件的路径、文件大小 System.out.print("路径:" + sta.getPath() + " 文件大小:" + sta.getLen() + " 权限:" + sta.getPermission() + " 内容:"); FSDataInputStream fsdis = fsSource.open(sta.getPath()); byte[] data = new byte[1024]; int read = -1; while ((read = fsdis.read(data)) > 0) { ps.write(data, 0, read); fsdos.write(data, 0, read); } fsdis.close(); } ps.close(); fsdos.close(); } public static void main(String[] args) throws IOException { MergeFile merge = new MergeFile( "hdfs://localhost:9000/user/hadoop/", "hdfs://localhost:9000/user/hadoop/merge.txt"); merge.doMerge(); } } 七.编译运行程序 然后,要确保HDFS的“/user/hadoop”目录下已经存在file1.txt、file2.txt、file3.txt、file4.abc和file5.abc,每个文件里面有内容。这里,假设文件内容如下: file1.txt的内容是: this is file1.txt file2.txt的内容是: this is file2.txt file3.txt的内容是: this is file3.txt file4.abc的内容是: this is file4.abc file5.abc的内容是: this is file5.abc 命令如下: echo "this is file1.txt" > file1.txt echo "this is file2.txt" > file2.txt echo "this is file3.txt" > file3.txt echo "this is file4.abc" > file4.abc echo "this is file5.abc" > file5.abc hdfs dfs -put file1.txt /user/hadoop/input hdfs dfs -put file2.txt /user/hadoop/input hdfs dfs -put file3.txt /user/hadoop/input hdfs dfs -put file4.abc /user/hadoop/input hdfs dfs -put file5.abc /user/hadoop/input 现在就可以编译运行上面编写的代码。可以直接点击Eclipse工作界面上部的运行程序的快捷按钮,当把鼠标移动到该按钮上时,在弹出的菜单中选择“Run As”,继续在弹出来的菜单中选择“Java Application”,如下图所示。 然后,会弹出如下图所示界面。 在该界面中,点击界面右下角的“OK”按钮,开始运行程序。程序运行结束后,会在底部的“Console”面板中显示运行结果信息(如下图所示)。 如果程序运行成功,这时,可以到HDFS中查看生成的merge.txt文件,比如,可以在Linux终端中执行如下命令: cd /usr/local/hadoop ./bin/hdfs dfs -ls /user/hadoop ./bin/hdfs dfs -cat /user/hadoop/merge.txt 八. 应用程序的部署 下面介绍如何把Java应用程序生成JAR包,部署到Hadoop平台上运行。首先,在Hadoop安装目录下新建一个名称为myapp的目录,用来存放我们自己编写的Hadoop应用程序,可以在Linux的终端中执行如下命令: cd /usr/local/hadoop mkdir myapp 然后,请在Eclipse工作界面左侧的“Package Explorer”面板中,在工程名称“HDFSExample”上点击鼠标右键,在弹出的菜单中选择“Export”,如下图所示。 然后,会弹出如下图所示界面。 在该界面中,选择“Runnable JAR file”,然后,点击“Next>”按钮,弹出如下图所示界面。 在该界面中,“Launch configuration”用于设置生成的JAR包被部署启动时运行的主类,需要在下拉列表中选择刚才配置的类“MergeFile-HDFSExample”。在“Export destination”中需要设置JAR包要输出保存到哪个目录,比如,这里设置为“/usr/local/hadoop/myapp/HDFSExample.jar”。在“Library handling”下面选择“Extract required libraries into generated JAR”。然后,点击“Finish”按钮,会出现如下图所示界面。 可以忽略该界面的信息,直接点击界面右下角的“OK”按钮,启动打包过程。打包过程结束后,会出现一个警告信息界面,如下图所示。 可以忽略该界面的信息,直接点击界面右下角的“OK”按钮。至此,已经顺利把HDFSExample工程打包生成了HDFSExample.jar。可以到Linux系统中查看一下生成的HDFSExample.jar文件, 可以看到,“/usr/local/hadoop/myapp”目录下已经存在一个HDFSExample.jar文件。 由于之前已经运行过一次程序,已经生成了merge.txt,因此,需要首先执行如下命令删除该文件: cd /usr/local/hadoop ./bin/hdfs dfs -rm /user/hadoop/merge.txt 现在,就可以在Linux系统中,使用hadoop jar命令运行程序,命令如下: cd /usr/local/hadoop ./bin/hadoop jar ./myapp/HDFSExample.jar 上面程序执行结束以后,可以到HDFS中查看生成的merge.txt文件,比如,可以在Linux终端中执行如下命令: ./bin/hdfs dfs -ls /user/hadoop ./bin/hdfs dfs -cat /user/hadoop/merge.txt 可以看到如下结果: | |||||
出现的问题: 1.问题hadoop:未找到命令;用不了hdfs dfs以及hadoop fs 2.问题2:Java程序中路径处理错误:运行合并文件的Java程序时,程序尝试将/user/hadoop/input目录当作文件来处理,导致报错java.io.FileNotFoundException: Path is not a file: /user/hadoop/input。 3.问题:在尝试将文件从本地上传到HDFS目录/user/hadoop/input时,执行命令hdfs dfs -put file1.txt /user/hadoop/input后,出现了错误提示,导致文件上传失败。 . | |||||
解决方案(列出遇到的问题和解决办法,列出没有解决的问题): 1.问题hadoop:未找到命令;用不了hdfs dfs以及hadoop fs 解决方案:vim ~/.bashrc export PATH=$PATH:/usr/local/hadoop/bin:/usr/local/hadoop/sbin 2.问题2:Java程序中路径处理错误:运行合并文件的Java程序时,程序尝试将/user/hadoop/input目录当作文件来处理,导致报错java.io.FileNotFoundException: Path is not a file: /user/hadoop/input。 解决方案:把路径"hdfs://localhost:9000/user/hadoop/"改成"hdfs://localhost:9000/user/hadoop/input/"。 3.问题:在尝试将文件从本地上传到HDFS目录/user/hadoop/input时,执行命令hdfs dfs -put file1.txt /user/hadoop/input后,出现了错误提示,导致文件上传失败。 解决方案: 确保HDFS服务正常运行,并检查HDFS用户目录的权限。如果HDFS服务未启动或者权限不足,可能导致文件上传失败。执行以下步骤检查并解决问题: 确保HDFS服务已启动: start-dfs.sh 检查HDFS目录权限: hdfs dfs -chmod 755 /user/hadoop/input 重新上传文件: hdfs dfs -put file1.txt /user/hadoop/input 未解决的问题: 暂时无 |
《大数据技术基础》课程机房上机实验报告 | |||||
题目 | 实验四.HBase2.2.2安装和编程实践指南 | 姓名 | 软件工程21-1班3212052051354朱扬宇 | 日期 | 2024年6月29日 |
实验环境:操作系统:Linux;Hadoop版本:3.1.3;JDK版本:1.8版本;Java IDE:Eclipse。HBase版本:1.1.2或以上版本 | |||||
实验内容与完成情况: 一.安装并配置HBase2.2.2 解压安装包hbase-2.2.2-bin.tar.gz至路径 /usr/local,命令如下: sudo tar -zxf ~/下载/hbase-2.2.2-bin.tar.gz -C /usr/local 将解压的文件名hbase-2.2.2改为hbase,以方便使用,命令如下: sudo mv /usr/local/hbase-2.2.2 /usr/local/hbase 编辑~/.bashrc文件 vi ~/.bashrc 如果没有引入过PATH请在~/.bashrc文件尾行添加如下内容: export PATH=$PATH:/usr/local/hbase/bin 编辑完成后,再执行source命令使上述配置在当前终端立即生效,命令如下: source ~/.bashrc 添加HBase权限 cd /usr/local sudo chown -R hadoop ./hbase #将hbase下的所有文件的所有者改为hadoop,hadoop是当前用户的用户名。 查看HBase版本,确定hbase安装成功,命令如下: 二. HBase配置 2.1单机模式配置 配置/usr/local/hbase/conf/hbase-env.sh 。配置JAVA环境变量,并添加配置HBASE_MANAGES_ZK为true,用vi命令打开并编辑hbase-env.sh,命令如下: vi /usr/local/hbase/conf/hbase-env.sh 配置JAVA环境变量;配置HBASE_MANAGES_ZK为true,表示由hbase自己管理zookeeper,不需要单独的zookeeper。hbase-env.sh中本来就存在这些变量的配置,大家只需要删除前面的#并修改配置内容即可(#代表注释): export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_162 export HBASE_MANAGES_ZK=true 配置/usr/local/hbase/conf/hbase-site.xml,打开并编辑hbase-site.xml,命令如下: vi /usr/local/hbase/conf/hbase-site.xml 在启动HBase前需要设置属性hbase.rootdir,用于指定HBase数据的存储位置,因为如果不设置的话,hbase.rootdir默认为/tmp/hbase-${user.name},这意味着每次重启系统都会丢失数据。此处设置为HBase安装目录下的hbase-tmp文件夹即(/usr/local/hbase/hbase-tmp),添加配置如下: <configuration> <property> <name>hbase.rootdir</name> <value>file:///usr/local/hbase/hbase-tmp</value> </property> </configuration> 接下来测试运行。首先切换目录至HBase安装目录/usr/local/hbase;再启动HBase。命令如下: cd /usr/local/hbase bin/start-hbase.sh bin/hbase shell sudo bin/start-hbase.sh用于启动HBase,bin/hbase shell用于打开shell命令行模式,用户可以通过输入shell命令操作HBase数据库。成功启动HBase,截图如下: 停止HBase运行,命令如下: bin/stop-hbase.sh 2.2.伪分布式模式配置 配置/usr/local/hbase/conf/hbase-env.sh。命令如下: vi /usr/local/hbase/conf/hbase-env.sh 配置JAVA_HOME,HBASE_CLASSPATH,HBASE_MANAGES_ZK. HBASE_CLASSPATH设置为本机Hadoop安装目录下的conf目录(即/usr/local/hadoop/conf) export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_162 export HBASE_CLASSPATH=/usr/local/hadoop/conf export HBASE_MANAGES_ZK=true 配置/usr/local/hbase/conf/hbase-site.xml 用命令vi打开并编辑hbase-site.xml,命令如下: vi /usr/local/hbase/conf/hbase-site.xml 修改hbase.rootdir,指定HBase数据在HDFS上的存储路径;将属性hbase.cluter.distributed设置为true。假设当前Hadoop集群运行在伪分布式模式下,在本机上运行,且NameNode运行在9000端口。 <configuration> <property> <name>hbase.rootdir</name> <value>hdfs://localhost:9000/hbase</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> </configuration> 接下来测试运行HBase。 第一步:首先登陆ssh,之前设置了无密码登陆,因此这里不需要密码;再切换目录至/usr/local/hadoop ;再启动hadoop,如果已经启动hadoop请跳过此步骤。命令如下: ssh localhost cd /usr/local/hadoop ./sbin/start-dfs.sh 第二步:切换目录至/usr/local/hbase;再启动HBase.命令如下: cd /usr/local/hbase bin/start-hbase.sh 启动成功,输入命令jps,看到以下界面说明hbase启动成功 进入shell界面: bin/hbase shell 三、 编程实践 1. 利用Shell命令 1.1 HBase中创建表 HBase中用create命令创建表,具体如下: create 'student','Sname','Ssex','Sage','Sdept','course' 此时,即创建了一个“student”表,属性有:Sname,Ssex,Sage,Sdept,course。因为HBase的表中会有一个系统默认的属性作为行键,无需自行创建,默认为put命令操作中表名后第一个数据。创建完“student”表后,可通过describe命令查看“student”表的基本信息。命令执行截图如下: describe ‘student’ 1.2 HBase数据库基本操作 添加数据 HBase中用put命令添加数据,注意:一次只能为一个表的一行数据的一个列,也就是一个单元格添加一个数据,所以直接用shell命令插入数据效率很低,在实际应用中,一般都是利用编程操作数据。 当运行命令:put ‘student’,’95001’,’Sname’,’LiYing’时,即为student表添加了学号为95001,名字为LiYing的一行数据,其行键为95001。 put 'student','95001','Sname','LiYing' 命令执行截图如下,即为student表添加了学号为95001,名字为LiYing的一行数据,其行键为95001。 put 'student','95001','course:math','80' 命令执行截图如下,即为95001行下的course列族的math列添加了一个数据。 put 'student','95001','Ssex','Male' 上面的命令为95001行下的Ssex列添加了一个数据。 删除数据 在HBase中用delete以及deleteall命令进行删除数据操作,它们的区别是:1. delete用于删除一个数据,是put的反向操作;2. deleteall操作用于删除一行数据。 delete命令 delete 'student','95001','Ssex' 命令执行截图如下, 即删除了student表中95001行下的Ssex列的所有数据。 deleteall命令 deleteall 'student','95001' 查看数据 HBase中有两个用于查看数据的命令:1. get命令,用于查看表的某一行数据;2. scan命令用于查看某个表的全部数据 1. get命令 get 'student','95001' language-bash 命令执行截图如下, 返回的是‘student’表‘95001’行的数据。 scan命令 scan 'student' 命令执行截图如下, 返回的是‘student’表的全部数据。 删除表 删除表有两步,第一步先让该表不可用,第二步删除表。 disable 'student' drop 'student' 1.3 查询表历史数据 查询表的历史版本,需要两步。 1、在创建表的时候,指定保存的版本数(假设指定为5) create 'teacher',{NAME=>'username',VERSIONS=>5} 2、插入数据然后更新数据,使其产生历史版本数据,注意:这里插入数据和更新数据都是用put命令 put 'teacher','91001','username','Mary' put 'teacher','91001','username','Mary1' put 'teacher','91001','username','Mary2' put 'teacher','91001','username','Mary3' put 'teacher','91001','username','Mary4' put 'teacher','91001','username','Mary5' 查询时,指定查询的历史版本数。默认会查询出最新的数据。(有效取值为1到5) get 'teacher','91001',{COLUMN=>'username',VERSIONS=>5} 查询结果截图如下: 四.HBase Java API编程实践 本实例采用Eclipse开发工具。 启动Eclipse,启动以后,出现如下图所示界面,点击界面右下角的“Launch”按钮。 启动进入Eclipse以后的程序开发界面如下图所示。 点击界面顶部的“File”菜单,在弹出的子菜单(如下图所示)中选择“New”,再选择子菜单中的“Java Project”。 这时会弹出一个Java工程创建对话框(如下图所示),在“Project name”文本框中输入“HBaseExample”,在“JRE”选项卡中选中第2项“Use a project specific JRE”,然后点击界面底部的“Next”按钮。 在弹出的界面中(如下图所示),用鼠标点击“Libraries”选项卡,然后,点击界面右侧的“Add External JARs...”按钮。 在弹出的“JAR Selection”界面中(如下图所示),进入到“/usr/local/hbase/lib”目录,选中该目录下的所有jar文件(注意,不要选中client-facing-thirdparty、ruby、shaded-clients和zkcli这四个目录),然后,点击界面底部的“OK”按钮。 然后,在“JAR Selection”界面中(如下图所示),点击进入到“client-facing-thirdparty”目录下。 在“client-facing-thirdparty”目录下(如下图所示),选中所有jar文件,再点击界面底部的“OK”按钮。 然后,再点击界面(如下图所示)底部的“Finish”按钮。 在界面(如下图所示)左侧的“HBaseExample”工程名称上单击鼠标右键,在弹出的菜单中选择“New”,再在弹出的子菜单中选择“Class”。 在弹出的“New Java Class”对话框(如下图所示)中,在“Name”文本框中输入“ExampleForHBase”,然后,点击界面底部的“Finish”按钮。 在代码窗口中(如下图所示),ExampleForHBase.java代码内容输入。 import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.*; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.util.Bytes; import java.io.IOException; public class ExampleForHBase { public static Configuration configuration; public static Connection connection; public static Admin admin; public static void main(String[] args)throws IOException{ init(); createTable("student",new String[]{"score"}); insertData("student","zhangsan","score","English","69"); insertData("student","zhangsan","score","Math","86"); insertData("student","zhangsan","score","Computer","77"); getData("student", "zhangsan", "score","English"); close(); } public static void init(){ configuration = HBaseConfiguration.create(); configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase"); try{ connection = ConnectionFactory.createConnection(configuration); admin = connection.getAdmin(); }catch (IOException e){ e.printStackTrace(); } } public static void close(){ try{ if(admin != null){ admin.close(); } if(null != connection){ connection.close(); } }catch (IOException e){ e.printStackTrace(); } } public static void createTable(String myTableName,String[] colFamily) throws IOException { TableName tableName = TableName.valueOf(myTableName); if(admin.tableExists(tableName)){ System.out.println("talbe is exists!"); }else { TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(tableName); for(String str:colFamily){ ColumnFamilyDescriptor family = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(str)).build(); tableDescriptor.setColumnFamily(family); } admin.createTable(tableDescriptor.build()); } } public static void insertData(String tableName,String rowKey,String colFamily,String col,String val) throws IOException { Table table = connection.getTable(TableName.valueOf(tableName)); Put put = new Put(rowKey.getBytes()); put.addColumn(colFamily.getBytes(),col.getBytes(), val.getBytes()); table.put(put); table.close(); } public static void getData(String tableName,String rowKey,String colFamily, String col)throws IOException{ Table table = connection.getTable(TableName.valueOf(tableName)); Get get = new Get(rowKey.getBytes()); get.addColumn(colFamily.getBytes(),col.getBytes()); Result result = table.get(get); System.out.println(new String(result.getValue(colFamily.getBytes(),col==null?null:col.getBytes()))); table.close(); } } 程序运行成功以后,如下图所示,会在运行结果中出现“69”。 这时,可以到HBase Shell交互式环境中,使用如下命令查看student表是否创建成功: hbase> list 该命令执行效果如下图所示: 再在HBase Shell交互式环境中,使用如下命令查看student表中的数据: hbase> scan ‘student’ 该命令执行效果如下图所示: | |||||
出现的问题: 1.验证Hbase是否安装成功时爆出一大堆信息: | |||||
1.验证Hbase是否安装成功时爆出一大堆信息: 解决方法: 进入 /usr/local/hbase/conf/hbase-env 文件,将最后一行不允许注释 未解决的问题: 1.在执行大规模数据操作时,HBase的读写性能表现出不稳定的情况。 潜在原因:可能是由于HBase配置中的内存和资源分配不合理,或者Hadoop集群的网络带宽限制。 2.在设计HBase表的结构时,列族和列限定符的设计不合理,导致数据管理和查询复杂度增加。 潜在原因:对HBase的Schema设计缺乏经验,未能充分利用HBase的列族和列的优势。 需要进一步的解决步骤:重新审视HBase表的设计,根据实际业务需求和数据访问模式进行优化,参考HBase的最佳实践进行Schema设计。 |
《大数据技术基础》课程机房上机实验报告 | |||||
题目 | 实验五.MapReduce编程实践(Hadoop3.1.3) | 姓名 | 软件工程21-1班3212052051354朱扬宇 | 日期 | 2024年6月29日 |
实验环境:操作系统:Linux;Hadoop版本:3.1.3;JDK版本:1.8版本;Java IDE:Eclipse。 | |||||
实验内容与完成情况: 一. 词频统计任务要求 1.首先,在Linux系统本地创建两个文件,即文件wordfile1.txt和wordfile2.txt。在实际应用中,这两个文件可能会非常大,会被分布存储到多个节点上。但是,为了简化任务,这里的两个文件只包含几行简单的内容。需要说明的是,针对这两个小数据集样本编写的MapReduce词频统计程序,不作任何修改,就可以用来处理大规模数据集的词频统计。 文件wordfile1.txt的内容如下: I love Spark I love Hadoop 文件wordfile2.txt的内容如下: Hadoop is good Spark is fast 命令如下: echo -e "I love Spark\nI love Hadoop" > wordfile1.txt echo -e "Hadoop is good\nSpark is fast" > wordfile2.txt hdfs dfs -put wordfile1.txt input hdfs dfs -put wordfile2.txt input 假设HDFS中有一个/user/hadoop/input文件夹,并且文件夹为空,请把文件wordfile1.txt和wordfile2.txt上传到HDFS中的input文件夹下。现在需要设计一个词频统计程序,统计input文件夹下所有文件中每个单词的出现次数,也就是说,程序应该输出如下形式的结果: fast 1 good 1 Hadoop 2 I 2 is 2 love 2 Spark 2 2. 在Eclipse中创建项目 首先,启动Eclipse,启动以后会弹出如下图所示界面,提示设置工作空间(workspace)。 可以直接采用默认的设置“/home/hadoop/workspace”,点击“OK”按钮。可以看出,由于当前是采用hadoop用户登录了Linux系统,因此,默认的工作空间目录位于hadoop用户目录“/home/hadoop”下。 Eclipse启动以后,呈现的界面如下图所示。 选择“File-->New-->Java Project”菜单,开始创建一个Java工程,弹出如下图所示界面。 在“Project name”后面输入工程名称“WordCount”,选中“Use default location”,让这个Java工程的所有文件都保存到“/home/hadoop/workspace/WordCount”目录下。在“JRE”这个选项卡中,可以选择当前的Linux系统中已经安装好的JDK,比如jdk1.8.0_162。然后,点击界面底部的“Next>”按钮,进入下一步的设置。 3. 为项目添加需要用到的JAR包 进入下一步的设置以后,会弹出如下图所示界面。 需要在这个界面中加载该Java工程所需要用到的JAR包,这些JAR包中包含了与Hadoop相关的Java API。这些JAR包都位于Linux系统的Hadoop安装目录下,对于本教程而言,就是在“/usr/local/hadoop/share/hadoop”目录下。点击界面中的“Libraries”选项卡,然后,点击界面右侧的“Add External JARs…”按钮,弹出如下图所示界面。 在该界面中,上面有一排目录按钮(即“usr”、“local”、“hadoop”、“share”、“hadoop”、“mapreduce”和“lib”),当点击某个目录按钮时,就会在下面列出该目录的内容。 为了编写一个MapReduce程序,一般需要向Java工程中添加以下JAR包: (1)“/usr/local/hadoop/share/hadoop/common”目录下的hadoop-common-3.1.3.jar和haoop-nfs-3.1.3.jar; (2)“/usr/local/hadoop/share/hadoop/common/lib”目录下的所有JAR包; (3)“/usr/local/hadoop/share/hadoop/mapreduce”目录下的所有JAR包,但是,不包括jdiff、lib、lib-examples和sources目录,具体如下图所示。 (4)“/usr/local/hadoop/share/hadoop/mapreduce/lib”目录下的所有JAR包。 比如,如果要把“/usr/local/hadoop/share/hadoop/common”目录下的hadoop-common-3.1.3.jar和haoop-nfs-3.1.3.jar添加到当前的Java工程中,可以在界面中点击相应的目录按钮,进入到common目录,然后,界面会显示出common目录下的所有内容(如下图所示)。 请在界面中用鼠标点击选中hadoop-common-3.1.3.jar和haoop-nfs-3.1.3.jar,然后点击界面右下角的“确定”按钮,就可以把这两个JAR包增加到当前Java工程中,出现的界面如下图所示。 从这个界面中可以看出,hadoop-common-3.1.3.jar和haoop-nfs-3.1.3.jar已经被添加到当前Java工程中。然后,按照类似的操作方法,可以再次点击“Add External JARs…”按钮,把剩余的其他JAR包都添加进来。需要注意的是,当需要选中某个目录下的所有JAR包时,可以使用“Ctrl+A”组合键进行全选操作。全部添加完毕以后,就可以点击界面右下角的“Finish”按钮,完成Java工程WordCount的创建。 4. 编写Java应用程序 下面编写一个Java应用程序,即WordCount.java。请在Eclipse工作界面左侧的“Package Explorer”面板中(如下图所示),找到刚才创建好的工程名称“WordCount”,然后在该工程名称上点击鼠标右键,在弹出的菜单中选择“New-->Class”菜单。 选择“New-->Class”菜单以后会出现如下图所示界面。 在该界面中,只需要在“Name”后面输入新建的Java类文件的名称,这里采用名称“WordCount”,其他都可以采用默认设置,然后,点击界面右下角“Finish”按钮,出现如下图所示界面。 可以看出,Eclipse自动创建了一个名为“WordCount.java”的源代码文件,并且包含了代码“public class WordCount{}”,请清空该文件里面的代码,然后在该文件中输入完整的词频统计程序代码,具体如下: import java.io.IOException; import java.util.Iterator; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.util.GenericOptionsParser; public class WordCount { public WordCount() { } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); String[] otherArgs = (new GenericOptionsParser(conf, args)).getRemainingArgs(); if(otherArgs.length < 2) { System.err.println("Usage: wordcount <in> [<in>...] <out>"); System.exit(2); } Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCount.class); job.setMapperClass(WordCount.TokenizerMapper.class); job.setCombinerClass(WordCount.IntSumReducer.class); job.setReducerClass(WordCount.IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); for(int i = 0; i < otherArgs.length - 1; ++i) { FileInputFormat.addInputPath(job, new Path(otherArgs[i])); } FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length - 1])); System.exit(job.waitForCompletion(true)?0:1); } public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> { private static final IntWritable one = new IntWritable(1); private Text word = new Text(); public TokenizerMapper() { } public void map(Object key, Text value, Mapper<Object, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException { StringTokenizer itr = new StringTokenizer(value.toString()); while(itr.hasMoreTokens()) { this.word.set(itr.nextToken()); context.write(this.word, one); } } } public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> { private IntWritable result = new IntWritable(); public IntSumReducer() { } public void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException { int sum = 0; IntWritable val; for(Iterator i$ = values.iterator(); i$.hasNext(); sum += val.get()) { val = (IntWritable)i$.next(); } this.result.set(sum); context.write(key, this.result); } } } 5. 编译打包程序 现在就可以编译上面编写的代码。可以直接点击Eclipse工作界面上部的运行程序的快捷按钮,当把鼠标移动到该按钮上时,在弹出的菜单中选择“Run as”,继续在弹出来的菜单中选择“Java Application”,如下图所示。 然后,会弹出如下图所示界面。 点击界面右下角的“OK”按钮,开始运行程序。程序运行结束后,会在底部的“Console”面板中显示运行结果信息(如下图所示)。 下面就可以把Java应用程序打包生成JAR包,部署到Hadoop平台上运行。现在可以把词频统计程序放在“/usr/local/hadoop/myapp”目录下。 首先,请在Eclipse工作界面左侧的“Package Explorer”面板中,在工程名称“WordCount”上点击鼠标右键,在弹出的菜单中选择“Export”,如下图所示。 在该界面中,选择“Runnable JAR file”,然后,点击“Next>”按钮,弹出如下图所示界面。 在该界面中,“Launch configuration”用于设置生成的JAR包被部署启动时运行的主类,需要在下拉列表中选择刚才配置的类“WordCount-WordCount”。在“Export destination”中需要设置JAR包要输出保存到哪个目录,比如,这里设置为“/usr/local/hadoop/myapp/WordCount.jar”。在“Library handling”下面选择“Extract required libraries into generated JAR”。然后,点击“Finish”按钮,会出现如下图所示界面。 可以忽略该界面的信息,直接点击界面右下角的“OK”按钮,启动打包过程。打包过程结束后,会出现一个警告信息界面,如下图所示。 可以忽略该界面的信息,直接点击界面右下角的“OK”按钮。至此,已经顺利把WordCount工程打包生成了WordCount.jar。可以到Linux系统中查看一下生成的WordCount.jar文件,可以在Linux的终端中执行如下命令: cd /usr/local/hadoop/myapp ls 可以看到,“/usr/local/hadoop/myapp”目录下已经存在一个WordCount.jar文件。 5. 运行程序 在运行程序之前,需要启动Hadoop,命令如下: cd /usr/local/hadoop ./sbin/start-dfs.sh 在启动Hadoop之后,需要首先删除HDFS中与当前Linux用户hadoop对应的input和output目录(即HDFS中的“/user/hadoop/input”和“/user/hadoop/output”目录),这样确保后面程序运行不会出现问题,具体命令如下: cd /usr/local/hadoop ./bin/hdfs dfs -rm -r input ./bin/hdfs dfs -rm -r output 然后,再在HDFS中新建与当前Linux用户hadoop对应的input目录,即“/user/hadoop/input”目录,具体命令如下: cd /usr/local/hadoop ./bin/hdfs dfs -mkdir input 然后,把之前在第7.1节中在Linux本地文件系统中新建的两个文件wordfile1.txt和wordfile2.txt(假设这两个文件位于“/usr/local/hadoop”目录下,并且里面包含了一些英文语句),上传到HDFS中的“/user/hadoop/input”目录下,命令如下: ./bin/hdfs dfs -put ./wordfile1.txt input ./bin/hdfs dfs -put ./wordfile2.txt input 现在,就可以在Linux系统中,使用hadoop jar命令运行程序,命令如下: cd /usr/local/hadoop ./bin/hadoop jar ./myapp/WordCount.jar input output 词频统计结果已经被写入了HDFS的“/user/hadoop/output”目录中,可以执行如下命令查看词频统计结果: ./bin/hdfs dfs -cat output/* 至此,词频统计程序顺利运行结束。需要注意的是,如果要再次运行WordCount.jar,需要首先删除HDFS中的output目录,否则会报错。 | |||||
出现的问题: 无 | |||||
解决方案(列出遇到的问题和解决办法,列出没有解决的问题): 无 未解决的问题: 无 |
《大数据技术基础》课程机房上机实验报告 | |||||
题目 | 实验四.Hive3.1.2安装指南 | 姓名 | 软件工程21-1班3212052051354朱扬宇 | 日期 | 2024年6月29日 |
实验环境:操作系统:Linux;Hadoop版本:3.1.3;JDK版本:1.8版本;Java IDE:Eclipse;Mysql8. | |||||
实验内容与完成情况: 一、安装Hive3.1.2 1. 下载并解压Hive安装包 首先需要下载Hive安装包文件,进入百度网盘后,进入“软件”目录,找到apache-hive-3.1.2-bin.tar.gz文件,下载到本地。 cd ~/下载 sudo tar -zxvf ./apache-hive-3.1.2-bin.tar.gz -C /usr/local # 解压到/usr/local中 cd /usr/local/ sudo mv apache-hive-3.1.2-bin hive # 将文件夹名改为hive sudo chown -R hadoop:hadoop hive # 修改文件权限 2. 配置环境变量 为了方便使用,我们把hive命令加入到环境变量中去, 请使用vim编辑器打开.bashrc文件,命令如下: vim ~/.bashrc 在该文件最前面一行添加如下内容: export HIVE_HOME=/usr/local/hive export PATH=$PATH:$HIVE_HOME/bin export HADOOP_HOME=/usr/local/hadoop HADOOP_HOME需要被配置成你机器上Hadoop的安装路径,比如这里是安装在/usr/local/hadoop目录。 保存退出后,运行如下命令使配置立即生效: source ~/.bashrc 3. 修改/usr/local/hive/conf下的hive-site.xml 执行如下命令: cd /usr/local/hive/conf mv hive-default.xml.template hive-default.xml 上面命令是将hive-default.xml.template重命名为hive-default.xml; 然后,使用vim编辑器新建一个配置文件hive-site.xml,命令如下: vim hive-site.xml 在hive-site.xml中添加如下配置信息: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <configuration> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value> <description>JDBC connect string for a JDBC metastore</description> </property> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.cj.jdbc.Driver</value> <description>Driver class name for a JDBC metastore</description> </property> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>hive</value> <description>username to use against metastore database</description> </property> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>123456</value> <description>password to use against metastore database</description> </property> </configuration> 这里记得把mysql-connector-j-8.2.0.jar放到/usr/local/hive/lib文件下 顺便把guava-19.jar换掉 二、安装并配置mysql 下载最新版mysql:sudo apt install -y mysql-server 启动MySQL服务 sudo systemctl start mysql sudo systemctl enable mysql sudo systemctl status mysql sudo mysql # 登录mysql,在默认安装时如果没有让我们设置密码,则直接回车就能登录成功。 mysql -uroot -p # 设置密码 mysql8.0 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码'; 配置8.0版本参考:我这里通过这种方式没有实现所有IP都能访问;我是通过直接修改配置文件才实现的,MySQL8.0版本把配置文件 my.cnf 拆分成mysql.cnf 和mysqld.cnf,我们需要修改的是mysqld.cnf文件:sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf 修改 bind-address,保存后重启MySQL即可。 bind-address = 0.0.0.0 重启MySQL重新加载一下配置: sudo systemctl restart mysql 备注: 创建用户 CREATE USER 'username'@'host' IDENTIFIED BY 'password'; username:你将创建的用户名 host:指定该用户在哪个主机上可以登陆,如果是本地用户可用localhost,如果想让该用户可以从任意远程主机登陆,可以使用通配符% password:该用户的登陆密码,密码可以为空,如果为空则该用户可以不需要密码登陆服务器 注意,使用%通配符创建外网访问用户后,登录时需要明确访问的IP地址,例如 mysql -u pig -h 115.28.203.224 -p 例子 CREATE USER 'pig'@'localhost' IDENTIFIED BY '123456'; CREATE USER 'pig'@'192.168.1.101' IDENTIFIED BY '123456'; CREATE USER 'pig'@'%' IDENTIFIED BY '123456'; CREATE USER 'pig'@'%' IDENTIFIED BY ''; CREATE USER 'pig'@'%'; 用户授权 GRANT privileges ON databasename.tablename TO 'username'@'host'; privileges:用户的操作权限,如SELECT,INSERT,UPDATE等,如果要授予所的权限则使用ALL databasename:数据库名 tablename:表名 如果要授予该用户对所有数据库和表的相应操作权限则可用*表示,如*.* 注意:用以上命令授权的用户不能给其它用户授权,如果想让被授权的用户可以将他的拥有的权限授给其他用户,用以下命令 GRANT privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION; 刷新授权 flush privileges; 这一步一定要做,不然无法成功!这句表示从mysql数据库的grant表中重新加载权限数据,因为MySQL把权限都放在了cache中,所以在做完更改后需要重新加载。 三.mysql连接hive 1.新建hive数据库。 create database hive; #这个hive数据库与hive-site.xml中localhost:3306/hive的hive对应,用来保存hive元数据 2.配置mysql允许hive接入: 创建 hive 用户并设置密码: CREATE USER 'hive'@'localhost' IDENTIFIED BY '123456'; 授予权限: GRANT ALL PRIVILEGES ON *.* TO 'hive'@'localhost'; FLUSH PRIVILEGES; 3. 启动hive 启动hive之前,请先启动hadoop集群。 ./sbin/start-dfs.sh #启动Hadoop的HDFS 尝试一下以下方法: ./bin/schematool -dbType mysql -initSchema cd /usr/local/hive ./bin/hive 使用mysql作为元数据库时登陆 三、Hive的常用HiveQL操作 1)Hive基本数据类型 首先,我们简单叙述一下HiveQL的基本数据类型。Hive支持基本数据类型和复杂类型, 基本数据类型主要有数值类型(INT、FLOAT、DOUBLE ) 、布尔型和字符串, 复杂类型有三种:ARRAY、MAP 和 STRUCT。 a.基本数据类型 TINYINT: 1个字节 SMALLINT: 2个字节 INT: 4个字节 BIGINT: 8个字节 BOOLEAN: TRUE/FALSE FLOAT: 4个字节,单精度浮点型 DOUBLE: 8个字节,双精度浮点型STRING 字符串 b.复杂数据类型 ARRAY: 有序字段 MAP: 无序字段 STRUCT: 一组命名的字段 2)常用的HiveQL操作命令 a.数据定义:主要用于创建修改和删除数据库、表、视图、函数和索引。 创建、修改和删除数据库 create database if not exists hive; #创建数据库 show databases; #查看Hive中包含数据库 show databases like 'h.*'; #查看Hive中以h开头数据库 describe databases; #查看hive数据库位置等信息 alter database hive set dbproperties; #为hive设置键值对属性 use hive; #切换到hive数据库下 drop database if exists hive; #删除不含表的数据库 drop database if exists hive cascade; #删除数据库和它中的表 创建、修改和删除表 #创建内部表(管理表) CREATE TABLE IF NOT EXISTS hive.usr ( name STRING COMMENT 'username', pwd STRING COMMENT 'password', address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT> COMMENT 'home address', identify MAP<INT, TINYINT> COMMENT 'number, sex' ) COMMENT 'description of the table' TBLPROPERTIES ('creator'='me', 'time'='2016.1.1'); #创建外部表 CREATE EXTERNAL TABLE IF NOT EXISTS usr2 ( name STRING, pwd STRING, address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>, identify MAP<INT, TINYINT> ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LOCATION '/usr/local/hive/warehouse/hive.db/usr'; #创建分区表 create table if not exists usr3( name string, pwd string, address struct<street:string,city:string,state:string,zip:int>, identify map<int,tinyint>) partitioned by(city string,state string); #复制usr表的表模式 create table if not exists hive.usr1 like hive.usr; show tables in hive; show tables 'u.*'; #查看hive中以u开头的表 describe hive.usr; #查看usr表相关信息 alter table hive.usr rename to hive.custom; #重命名表
use hive; #切换到hive数据库下 drop table if exists usr1; #删除表 drop database if exists hive cascade; #删除数据库和它中的表 3)数据操作 主要实现的是将数据装载到表中(或是从表中导出),并进行相应查询操作,对熟悉SQL语言的用户应该不会陌生。 向表中装载数据 这里我们以只有两个属性的简单表为例来介绍。首先创建表stu和course,stu有两个属性id与name,course有两个属性cid与sid。 create table if not exists hive.stu(id int,name string) row format delimited fields terminated by '\t'; create table if not exists hive.course(cid int,sid int) row format delimited fields terminated by '\t'; 向表中装载数据有两种方法:从文件中导入和通过查询语句插入。 a.从文件中导入 假如这个表中的记录存储于文件stu.txt中,该文件的存储路径为/usr/local/hadoop/examples/stu.txt,内容如下。 stu.txt: 1 xiapi 2 xiaoxue 3 qingqing mkdir -p /usr/local/hadoop/examples echo -e "1\txiapi\n2\txiaoxue\n3\tqingqing" | sudo tee /usr/local/hadoop/examples/stu.txt 下面我们把这个文件中的数据装载到表stu中,操作如下: load data local inpath '/usr/local/hadoop/examples/stu.txt' overwrite into table stu; 如果stu.txt文件存储在HDFS 上,则不需要 local 关键字。 b.通过查询语句插入 使用如下命令,创建stu1表,它和stu表属性相同,我们要把从stu表中查询得到的数据插入到stu1中: create table stu1 as select id,name from stu; 上面是创建表,并直接向新表插入数据;若表已经存在,向表中插入数据需执行以下命令: insert overwrite table stu1 select id,name from stu where(条件); 这里关键字overwrite的作用是替换掉表(或分区)中原有数据,换成into关键字,直接追加到原有内容后。 四、Hive简单编程实践 下面我们以词频统计算法为例,来介绍怎么在具体应用中使用Hive。词频统计算法又是最能体现MapReduce思想的算法之一,这里我们可以对比它在MapReduce中的实现,来说明使用Hive后的优势。 MapReduce实现词频统计的代码可以通过下载Hadoop源码后,在 $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar 包中找到(wordcount类),wordcount类由63行Java代码编写而成。下面首先简单介绍一下怎么使用MapReduce中wordcount类来统计单词出现的次数,具体步骤如下: 1)创建input目录,output目录会自动生成。其中input为输入目录,output目录为输出目录。命令如下: cd /usr/local/hadoop mkdir input 2)然后,在input文件夹中创建两个测试文件file1.txt和file2.txt,命令如下: cd /usr/local/hadoop/input echo "hello world" > file1.txt echo "hello hadoop" > file2.txt Shell 3)执行如下hadoop命令: cd .. ./bin/hadoop jar ./myapp/WordCount.jar input output 4)我们可以到output文件夹中查看结果,结果如下: 下面我们通过HiveQL实现词频统计功能,此时只要编写下面7行代码,而且不需要进行编译生成jar来执行。HiveQL实现命令如下: create table docs(line string); load data inpath 'file:///usr/local/hadoop/input' overwrite into table docs; create table word_count as select word, count(1) as count from (select explode(split(line,' '))as word from docs) w group by word order by word; select * from word_count 由上可知,采用Hive实现最大的优势是,对于非程序员,不用学习编写Java MapReduce代码了,只需要用户学习使用HiveQL就可以了,而这对于有SQL基础的用户而言是非常容易的。 | |||||
出现的问题: 1.在启动hive时报错: 2.java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument 3.问题:org.datanucleus.store.rdbms.exceptions.MissingTableException: Required table missing : “VERSION” in Catalog “” Schema “”. DataNucleus requires this table to perform its persistence operations. 4.问题: 在执行 schematool -dbType mysql -initSchema -verbose 这个命令时出现错误 | |||||
解决方案(列出遇到的问题和解决办法,列出没有解决的问题): 解决方案: 1.在启动hive时报错: 设置mysql时区,useSSL1 <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://localhost:3306/db_hive?createDatabaseIfNotExist=true&serverTimezone=GMT&useSSL=false</value> <description>JDBC connect string for a JDBC metastore</description> </property> 2.问题:java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument 原因:com.google.common.base.Preconditions.checkArgument 这是因为hive内依赖的guava.jar和hadoop内的版本不一致造成的。 解决方案: ①.查看hadoop安装目录下share/hadoop/common/lib内guava.jar版本 ②.查看hive安装目录下lib内guava.jar的版本 如果两者不一致,删除版本低的,并拷贝高版本的 问题解决! 3.问题:org.datanucleus.store.rdbms.exceptions.MissingTableException: Required table missing : “VERSION” in Catalog “” Schema “”. DataNucleus requires this table to perform its persistence operations. 【解决方案】 进入hive安装目录(比如/usr/local/hive),执行如下命令:./bin/schematool -dbType mysql -initSchema 4.问题: 在执行 schematool -dbType mysql -initSchema -verbose 这个命令时出现错误 解决方法: 下载并安装 MySQL JDBC 驱动程序,然后将其复制到 Hive 的lib类路径中,即可解决 未解决的问题: 1.开启hive遇到 SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/usr/local/hive/lib/log4j-slf4j-impl-2.10.0.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/usr/local/hadoop/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory] 移除其中一个绑定文件后:rm /usr/local/hive/lib/log4j-slf4j-impl-2.10.0.jar或者rm /usr/local/hadoop/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar后会运行不了 2.遇到WARN DataNucleus.MetaData: Metadata has jdbc-type of null yet this is not valid. Ignored |
《大数据技术基础》课程机房上机实验报告 | |||||
题目 | 实验七.Spark安装和编程实践(Spark2.4.0) | 姓名 | 软件工程21-1班3212052051354朱扬宇 | 日期 | 2024年6月29日 |
实验环境:操作系统:Linux;Hadoop版本:3.1.3;JDK版本:1.8版本;Java IDE:Eclipse;Spark:2.4.0。 | |||||
实验内容与完成情况 一、安装Spark(Local模式) sudo tar -zxf ~/下载/spark-2.4.0-bin-without-hadoop.tgz -C /usr/local/ cd /usr/local sudo mv ./spark-2.4.0-bin-without-hadoop/ ./spark sudo chown -R hadoop:hadoop ./spark # 此处的 hadoop 为你的用户名 安装后,还需要修改Spark的配置文件spark-env.sh cd /usr/local/spark cp ./conf/spark-env.sh.template ./conf/spark-env.sh 编辑spark-env.sh文件(vim ./conf/spark-env.sh),在第一行添加以下配置信息: export SPARK_DIST_CLASSPATH=$(/usr/local/hadoop/bin/hadoop classpath) 配置完成后就可以直接使用,不需要像Hadoop运行启动命令。 通过运行Spark自带的示例,验证Spark是否安装成功。 cd /usr/local/spark bin/run-example SparkPi 执行时会输出非常多的运行信息,输出结果不容易找到,可以通过 grep 命令进行过滤(命令中的 2>&1 可以将所有的信息都输出到 stdout 中,否则由于输出日志的性质,还是会输出到屏幕中): cd /usr/local/spark bin/run-example SparkPi 2>&1 | grep "Pi is" 这里涉及到Linux Shell中管道的知识,详情可以参考Linux Shell中的管道命令 过滤后的运行结果如下图示: 二、使用 Spark Shell 编写代码 1.启动Spark Shell cd /usr/local/spark bin/spark-shell 2.加载text文件 spark创建sc,可以加载本地文件和HDFS文件创建RDD。这里用Spark自带的本地文件README.md文件测试。 val textFile = sc.textFile("file:///usr/local/spark/README.md") 加载HDFS文件和本地文件都是使用textFile,区别是添加前缀(hdfs://和file:///)进行标识。 3.简单RDD操作 //获取RDD文件textFile的第一行内容 textFile.first() //获取RDD文件textFile所有项的计数 textFile.count() //抽取含有“Spark”的行,返回一个新的RDD val lineWithSpark = textFile.filter(line => line.contains("Spark")) //统计新的RDD的行数 lineWithSpark.count() 可以通过组合RDD操作进行组合,可以实现简易MapReduce操作 //找出文本中每行的最多单词数 textFile.map(line => line.split(" ").size).reduce((a, b) => if (a > b) a else b) 退出Spark Shell 三、独立应用程序编程 接着我们通过一个简单的应用程序 SimpleApp 来演示如何通过 Spark API 编写一个独立应用程序。使用 Scala 编写的程序需要使用 sbt (或者Maven)进行编译打包,相应地,Java 程序使用 Maven 编译打包,而 Python 程序通过 spark-submit 直接提交。 (一)使用sbt对Scala独立应用程序进行编译打包 1. 安装sbt 这里我们把sbt安装到“/usr/local/sbt”目录下,请使用hadoop用户登录Linux系统,新建一个终端,在终端中执行如下命令: sudo mkdir /usr/local/sbt # 创建安装目录 cd ~/下载 sudo tar -zxvf ./sbt-1.3.8.tgz -C /usr/local cd /usr/local/sbt sudo chown -R hadoop /usr/local/sbt # 此处的hadoop为系统当前用户名 cp ./bin/sbt-launch.jar ./ #把bin目录下的sbt-launch.jar复制到sbt安装目录下 接着在安装目录中使用下面命令创建一个Shell脚本文件,用于启动sbt: vim /usr/local/sbt/sbt #!/bin/bash SBT_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M" java $SBT_OPTS -jar `dirname $0`/sbt-launch.jar "$@" 保存后,还需要为该Shell脚本文件增加可执行权限: chmod u+x /usr/local/sbt/sbt 更换仓库地址,加快编译速度 cd ~ mkdir .sbt #如果该目录已经存在,就不用创建了 cd .sbt vim repositories #使用vim编辑器创建repositories文件 然后,在文件repositories中输入如下内容: [repositories] local huaweicloud-maven: https://repo.huaweicloud.com/repository/maven/ maven-central: https://repo1.maven.org/maven2/ sbt-plugin-repo: https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] 保存该文件。 然后,修改SBT配置文件。打开/usr/local/sbt/conf/sbtopts 文件,在末尾新增一行,内容如下: -Dsbt.override.build.repos=true 通过上述设置以后,再去运行sbt编译打包,就会快很多。 然后,可以使用如下命令查看sbt版本信息: cd /usr/local/sbt ./sbt sbtVersion 2. Scala应用程序代码 在终端中执行如下命令创建一个文件夹 sparkapp 作为应用程序根目录: cd ~ # 进入用户主文件夹 mkdir ./sparkapp # 创建应用程序根目录 mkdir -p ./sparkapp/src/main/scala # 创建所需的文件夹结构 在 ./sparkapp/src/main/scala 下建立一个名为 SimpleApp.scala 的文件(vim ./sparkapp/src/main/scala/SimpleApp.scala),添加代码如下: /* SimpleApp.scala */ import org.apache.spark.SparkContext import org.apache.spark.SparkContext._ import org.apache.spark.SparkConf object SimpleApp { def main(args: Array[String]) { val logFile = "file:///usr/local/spark/README.md" // Should be some file on your system val conf = new SparkConf().setAppName("Simple Application") val sc = new SparkContext(conf) val logData = sc.textFile(logFile, 2).cache() val numAs = logData.filter(line => line.contains("a")).count() val numBs = logData.filter(line => line.contains("b")).count() println("Lines with a: %s, Lines with b: %s".format(numAs, numBs)) } } 该程序计算 /usr/local/spark/README 文件中包含 "a" 的行数 和包含 "b" 的行数。代码第8行的 /usr/local/spark 为 Spark 的安装目录,如果不是该目录请自行修改。不同于 Spark shell,独立应用程序需要通过 val sc = new SparkContext(conf) 初始化 SparkContext,SparkContext 的参数 SparkConf 包含了应用程序的信息。 该程序依赖 Spark API,因此我们需要通过 sbt 进行编译打包。 在~/sparkapp这个目录中新建文件simple.sbt,命令如下: cd ~/sparkapp vim simple.sbt 在simple.sbt中添加如下内容,声明该独立应用程序的信息以及与 Spark 的依赖关系: name := "Simple Project" version := "1.0" scalaVersion := "2.11.12" libraryDependencies += "org.apache.spark" %% "spark-core" % "2.4.0" 文件 simple.sbt 需要指明 Spark 和 Scala 的版本。在上面的配置信息中,scalaVersion用来指定scala的版本,sparkcore用来指定spark的版本,这两个版本信息都可以在之前的启动 Spark shell 的过程中,从屏幕的显示信息中找到。下面就是笔者在启动过程当中,看到的相关版本信息(备注:屏幕显示信息会很长,需要往回滚动屏幕仔细寻找信息)。 3. 使用 sbt 打包 Scala 程序 为保证 sbt 能正常运行,先执行如下命令检查整个应用程序的文件结构: cd ~/sparkapp find . 接着,我们就可以通过如下代码将整个应用程序打包成 JAR(首次运行同样需要下载依赖包 ): /usr/local/sbt/sbt package 打包成功的话,会输出如下图内容: 生成的 jar 包的位置为 ~/sparkapp/target/scala-2.11/simple-project_2.11-1.0.jar。 4. 通过 spark-submit 运行程序 最后,我们就可以将生成的 jar 包通过 spark-submit 提交到 Spark 中运行了,命令如下: /usr/local/spark/bin/spark-submit --class "SimpleApp" ~/sparkapp/target/scala-2.11/simple-project_2.11-1.0.jar # 上面命令执行后会输出太多信息,可以不使用上面命令,而使用下面命令查看想要的结果 /usr/local/spark/bin/spark-submit --class "SimpleApp" ~/sparkapp/target/scala-2.11/simple-project_2.11-1.0.jar 2>&1 | grep "Lines with a:" (二)使用Maven对Java独立应用程序进行编译打包 1. 安装Maven Ubuntu中没有自带安装maven,需要手动安装maven。可以访问maven官方下载自己下载。这里直接给出apache-maven-3.6.3-bin.zip的下载地址,直接点击下载即可。 这里选择安装在/usr/local/maven目录中: sudo unzip ~/下载/apache-maven-3.6.3-bin.zip -d /usr/local cd /usr/local sudo mv apache-maven-3.6.3/ ./maven sudo chown -R hadoop ./maven 2. Java应用程序代码 在终端执行如下命令创建一个文件夹sparkapp2作为应用程序根目录 cd ~ #进入用户主文件夹 mkdir -p ./sparkapp2/src/main/java 在 ./sparkapp2/src/main/java 下建立一个名为 SimpleApp.java 的文件(vim ./sparkapp2/src/main/java/SimpleApp.java),添加代码如下: /*** SimpleApp.java ***/ import org.apache.spark.api.java.*; import org.apache.spark.api.java.function.Function; import org.apache.spark.SparkConf; public class SimpleApp { public static void main(String[] args) { String logFile = "file:///usr/local/spark/README.md"; // Should be some file on your system SparkConf conf=new SparkConf().setMaster("local").setAppName("SimpleApp"); JavaSparkContext sc=new JavaSparkContext(conf); JavaRDD<String> logData = sc.textFile(logFile).cache(); long numAs = logData.filter(new Function<String, Boolean>() { public Boolean call(String s) { return s.contains("a"); } }).count(); long numBs = logData.filter(new Function<String, Boolean>() { public Boolean call(String s) { return s.contains("b"); } }).count(); System.out.println("Lines with a: " + numAs + ", lines with b: " + numBs); } } 该程序依赖Spark Java API,因此我们需要通过Maven进行编译打包。在./sparkapp2目录中新建文件pom.xml,命令如下: cd ~/sparkapp2 vim pom.xml 在pom.xml文件中添加内容如下,声明该独立应用程序的信息以及与Spark的依赖关系: <project> <groupId>cn.edu.xmu</groupId> <artifactId>simple-project</artifactId> <modelVersion>4.0.0</modelVersion> <name>Simple Project</name> <packaging>jar</packaging> <version>1.0</version> <repositories> <repository> <id>jboss</id> <name>JBoss Repository</name> <url>http://repository.jboss.com/maven2/</url> </repository> </repositories> <dependencies> <dependency> <!-- Spark dependency --> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.11</artifactId> <version>2.4.0</version> </dependency> </dependencies> </project> 3. 使用Maven打Java程序 为了保证maven能够正常运行,先执行如下命令检查整个应用程序的文件结构: cd ~/sparkapp2 find . 接着,我们可以通过如下代码将这整个应用程序打包成Jar(注意:电脑需要保持连接网络的状态,而且首次运行同样下载依赖包,同样消耗几分钟的时间): 可以通过修改Maven的配置文件,让Maven到国内的阿里云仓库下载相关依赖,大大提高打包的速度。 cd /usr/local/maven/conf vim settings.xml 将settings.xml中的文本改为以下内容: <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <mirrors> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云谷歌仓库</name> <url>https://maven.aliyun.com/repository/google</url> </mirror> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云阿帕奇仓库</name> <url>https://maven.aliyun.com/repository/apache-snapshots</url> </mirror> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云spring仓库</name> <url>https://maven.aliyun.com/repository/spring</url> </mirror> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云spring插件仓库</name> <url>https://maven.aliyun.com/repository/spring-plugin</url> </mirror> </mirrors> </settings> cd ~/sparkapp2 /usr/local/maven/bin/mvn package 4. 通过spark-submit 运行程序 最后,可以通过将生成的jar包通过spark-submit提交到Spark中运行,如下命令: /usr/local/spark/bin/spark-submit --class "SimpleApp" ~/sparkapp2/target/simple-project-1.0.jar # 上面命令执行后会输出太多信息,可以不使用上面命令,而使用下面命令查看想要的结果 /usr/local/spark/bin/spark-submit --class "SimpleApp" ~/sparkapp2/target/simple-project-1.0.jar 2>&1 | grep "Lines with a" 最后得到的结果如下: (三)使用Maven对Scala独立应用程序进行编译打包 1. 安装Maven 已经安装Maven,就不用重复安装了 2. Scala应用程序代码 在终端中执行如下命令创建一个文件夹 sparkapp3作为应用程序根目录: cd ~ # 进入用户主文件夹 mkdir ./sparkapp3 # 创建应用程序根目录 mkdir -p ./sparkapp3/src/main/scala # 创建所需的文件夹结构 在./sparkapp3/src/main/scala 下建立一个名为 SimpleApp.scala 的文件(vim ./sparkapp3/src/main/scala/SimpleApp.scala),添加代码如下: /* SimpleApp.scala */ import org.apache.spark.SparkContext import org.apache.spark.SparkContext._ import org.apache.spark.SparkConf object SimpleApp { def main(args: Array[String]) { val logFile = "file:///usr/local/spark/README.md" // Should be some file on your system val conf = new SparkConf().setAppName("Simple Application") val sc = new SparkContext(conf) val logData = sc.textFile(logFile, 2).cache() val numAs = logData.filter(line => line.contains("a")).count() val numBs = logData.filter(line => line.contains("b")).count() println("Lines with a: %s, Lines with b: %s".format(numAs, numBs)) } } 该程序计算 /usr/local/spark/README 文件中包含 "a" 的行数 和包含 "b" 的行数。代码第8行的 /usr/local/spark 为 Spark 的安装目录,如果不是该目录请自行修改。不同于 Spark shell,独立应用程序需要通过 val sc = new SparkContext(conf) 初始化 SparkContext,SparkContext 的参数 SparkConf 包含了应用程序的信息。 3.使用Maven进行编译打包 该程序依赖Spark Java API,因此我们需要通过Maven进行编译打包。在./sparkapp3目录中新建文件pom.xml,命令如下: cd ~/sparkapp3 vim pom.xml 然后,在pom.xml文件中添加如下内容,用来声明该独立应用程序的信息以及与Spark的依赖关系: <project> <groupId>cn.edu.xmu</groupId> <artifactId>simple-project</artifactId> <modelVersion>4.0.0</modelVersion> <name>Simple Project</name> <packaging>jar</packaging> <version>1.0</version> <repositories> <repository> <id>jboss</id> <name>JBoss Repository</name> <url>http://repository.jboss.com/maven2/</url> </repository> </repositories> <dependencies> <dependency> <!-- Spark dependency --> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.11</artifactId> <version>2.4.0</version> </dependency> </dependencies> <build> <sourceDirectory>src/main/scala</sourceDirectory> <plugins> <plugin> <groupId>org.scala-tools</groupId> <artifactId>maven-scala-plugin</artifactId> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> <configuration> <scalaVersion>2.11.12</scalaVersion> <args> <arg>-target:jvm-1.8</arg> </args> </configuration> </plugin> </plugins> </build> </project> 为了保证Maven能够正常运行,先执行如下命令检查整个应用程序的文件结构: cd ~/sparkapp3 find . 文件结构应该是类似如下的内容: 接下来,我们可以通过如下代码将整个应用程序打包成JAR包(注意:计算机需要保持连接网络的状态,而且首次运行打包命令时,Maven会自动下载依赖包,需要消耗几分钟的时间): cd ~/sparkapp3 #一定把这个目录设置为当前目录 /usr/local/maven/bin/mvn package 4.通过 spark-submit 运行程序 最后,我们就可以将生成的 jar 包通过 spark-submit 提交到 Spark 中运行了,命令如下: /usr/local/spark/bin/spark-submit --class "SimpleApp" ~/sparkapp3/target/simple-project-1.0.jar #上面命令执行后会输出太多信息,可以不使用上面命令,而使用下面命令查看想要的结果 /usr/local/spark/bin/spark-submit --class "SimpleApp" ~/sparkapp3/target/simple-project-1.0.jar 2>&1 | grep "Lines with a:" 最终得到的结果如下: 到此,就顺利完成 Spark 应用程序的Maven编译打包运行了。 | |||||
出现的问题: 1.没有更换仓库,执行“./sbt sbtVersion”这个命令以后,屏幕会长时间停止在如下状态: $ ./sbt sbtVersionJava HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256M; support was removed in 8.0[info] [launcher] getting org.scala-sbt sbt 1.3.8 (this may take some time)...显示上述信息以后,屏幕就会一动不动。 | |||||
解决方案(列出遇到的问题和解决办法,列出没有解决的问题): 1.没有更换仓库,执行“./sbt sbtVersion”这个命令以后,屏幕会长时间停止在如下状态: $ ./sbt sbtVersionJava HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256M; support was removed in 8.0[info] [launcher] getting org.scala-sbt sbt 1.3.8 (this may take some time)...显示上述信息以后,屏幕就会一动不动。 解决方案: 更换仓库地址,见安装教程。 未解决的问题: 无 |
《大数据技术基础》课程机房上机实验报告 | |||||
题目 | 实验六.Flink安装与编程实践(Flink1.9.1) | 姓名 | 软件工程21-1班3212052051354朱扬宇 | 日期 | 2024年6月29日 |
实验环境:操作系统:Linux;Hadoop版本:3.1.3;JDK版本:1.8版本;Java IDE:Eclipse;Flink:1.9.1。 | |||||
实验内容与完成情况: 一. 安装Flink Flink的运行需要Java环境的支持,因此,在安装Flink之前,请先参照相关资料安装Java环境(比如Java8)。然后,到Flink官网下载安装包,比如下载得到的安装文件为flink-1.9.1-bin-scala_2.11.tgz,并且保存在Linux系统中(假设当前使用hadoop用户名登录了Linux系统,并且安装文件被保存到了“/home/下载”目录下)。 cd ~/下载 sudo tar -zxvf flink-1.9.1-bin-scala_2.11.tgz -C /usr/local 修改目录名称,并设置权限,命令如下: cd /usr/local sudo mv ./ flink-1.9.1 ./flink sudo chown -R hadoop:hadoop ./flink Flink对于本地模式是开箱即用的,如果要修改Java运行环境,可以修改“/usr/local/flink/conf/flink-conf.yaml”文件中的env.java.home参数,设置为本地Java的绝对路径。 使用如下命令添加环境变量: vim ~/.bashrc 在.bashrc文件中添加如下内容: export FLINK_HOME=/usr/local/flink export PATH=$FLINK_HOME/bin:$PATH 保存并退出.bashrc文件,然后执行如下命令让配置文件生效: 使用如下命令启动Flink: cd /usr/local/flink ./bin/start-cluster.sh 使用jps命令查看进程: Flink的JobManager同时会在8081端口上启动一个Web前端,可以在浏览器中输入“http://localhost:8081”来访问。 Flink安装包中自带了测试样例,这里可以运行WordCount样例程序来测试Flink的运行效果,具体命令如下: cd /usr/local/flink/bin ./flink run /usr/local/flink/examples/batch/WordCount.jar 二. 编程实现WordCount程序 1. 安装Maven 已安装,跳过 2. 编写代码 在Linux终端中执行如下命令,在用户主文件夹下创建一个文件夹flinkapp作为应用程序根目录: cd ~ #进入用户主文件夹 mkdir -p ./flinkapp/src/main/java 然后,使用vim编辑器在“./flinkapp/src/main/java”目录下建立三个代码文件,即WordCountData.java、WordCountTokenizer.java和WordCount.java。 vim ./flinkapp/src/main/java/WordCountData.java WordCountData.java用于提供原始数据,其内容如下: package cn.edu.xmu; import org.apache.flink.api.java.DataSet; import org.apache.flink.api.java.ExecutionEnvironment; public class WordCountData { public static final String[] WORDS=new String[]{"To be, or not to be,--that is the question:--", "Whether \'tis nobler in the mind to suffer", "The slings and arrows of outrageous fortune", "Or to take arms against a sea of troubles,", "And by opposing end them?--To die,--to sleep,--", "No more; and by a sleep to say we end", "The heartache, and the thousand natural shocks", "That flesh is heir to,--\'tis a consummation", "Devoutly to be wish\'d. To die,--to sleep;--", "To sleep! perchance to dream:--ay, there\'s the rub;", "For in that sleep of death what dreams may come,", "When we have shuffled off this mortal coil,", "Must give us pause: there\'s the respect", "That makes calamity of so long life;", "For who would bear the whips and scorns of time,", "The oppressor\'s wrong, the proud man\'s contumely,", "The pangs of despis\'d love, the law\'s delay,", "The insolence of office, and the spurns", "That patient merit of the unworthy takes,", "When he himself might his quietus make", "With a bare bodkin? who would these fardels bear,", "To grunt and sweat under a weary life,", "But that the dread of something after death,--", "The undiscover\'d country, from whose bourn", "No traveller returns,--puzzles the will,", "And makes us rather bear those ills we have", "Than fly to others that we know not of?", "Thus conscience does make cowards of us all;", "And thus the native hue of resolution", "Is sicklied o\'er with the pale cast of thought;", "And enterprises of great pith and moment,", "With this regard, their currents turn awry,", "And lose the name of action.--Soft you now!", "The fair Ophelia!--Nymph, in thy orisons", "Be all my sins remember\'d."}; public WordCountData() { } public static DataSet<String> getDefaultTextLineDataset(ExecutionEnvironment env){ return env.fromElements(WORDS); } } vim ./flinkapp/src/main/java/WordCountTokenizer.java WordCountTokenizer.java用于切分句子,其内容如下: package cn.edu.xmu; import org.apache.flink.api.common.functions.FlatMapFunction; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.util.Collector; public class WordCountTokenizer implements FlatMapFunction<String, Tuple2<String,Integer>>{ public WordCountTokenizer(){} public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception { String[] tokens = value.toLowerCase().split("\\W+"); int len = tokens.length; for(int i = 0; i<len;i++){ String tmp = tokens[i]; if(tmp.length()>0){ out.collect(new Tuple2<String, Integer>(tmp,Integer.valueOf(1))); } } } } vim ./flinkapp/src/main/java/WordCount.java WordCount.java提供主函数,其内容如下: package cn.edu.xmu; import org.apache.flink.api.java.DataSet; import org.apache.flink.api.java.ExecutionEnvironment; import org.apache.flink.api.java.operators.AggregateOperator; import org.apache.flink.api.java.utils.ParameterTool; public class WordCount { public WordCount(){} public static void main(String[] args) throws Exception { ParameterTool params = ParameterTool.fromArgs(args); ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); env.getConfig().setGlobalJobParameters(params); Object text; //如果没有指定输入路径,则默认使用WordCountData中提供的数据 if(params.has("input")){ text = env.readTextFile(params.get("input")); }else{ System.out.println("Executing WordCount example with default input data set."); System.out.println("Use -- input to specify file input."); text = WordCountData.getDefaultTextLineDataset(env); } AggregateOperator counts = ((DataSet)text).flatMap(new WordCountTokenizer()).groupBy(new int[]{0}).sum(1); //如果没有指定输出,则默认打印到控制台 if(params.has("output")){ counts.writeAsCsv(params.get("output"),"\n", " "); env.execute(); }else{ System.out.println("Printing result to stdout. Use --output to specify output path."); counts.print(); } } } 该程序依赖Flink Java API,因此,我们需要通过Maven进行编译打包。需要新建文件pom.xml,然后,在pom.xml文件中添加如下内容,用来声明该独立应用程序的信息以及与Flink的依赖关系: cd ~/flinkapp vim pom.xml <project> <groupId>cn.edu.xmu</groupId> <artifactId>simple-project</artifactId> <modelVersion>4.0.0</modelVersion> <name>Simple Project</name> <packaging>jar</packaging> <version>1.0</version> <repositories> <repository> <id>jboss</id> <name>JBoss Repository</name> <url>http://repository.jboss.com/maven2/</url> </repository> </repositories> <dependencies> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-java</artifactId> <version>1.9.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-streaming-java_2.11</artifactId> <version>1.9.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-clients_2.11</artifactId> <version>1.9.1</version> </dependency> </dependencies> </project> 3.使用Maven打包Java程序 为了保证Maven能够正常运行,先执行如下命令检查整个应用程序的文件结构: cd ~/flinkapp find . 接下来,我们可以通过如下代码将整个应用程序打包成JAR包(注意:计算机需要保持连接网络的状态,而且首次运行打包命令时,Maven会自动下载依赖包,需要消耗几分钟的时间): cd ~/flinkapp #一定把这个目录设置为当前目录 /usr/local/maven/bin/mvn package 4.通过flink run命令运行程序 最后,可以将生成的JAR包通过flink run命令提交到Flink中运行(请确认已经启动Flink),命令如下: /usr/local/flink/bin/flink run --class cn.edu.xmu.WordCount ~/flinkapp/target/simple-project-1.0.jar 执行成功后,可以在屏幕上看到词频统计结果。 三、使用IntelliJ IDEA开发调试WordCount程序 1.IntelliJ IDEA的安装。 cd ~/下载 sudo tar -zxf ~/下载/ideaIC-2024.1.2.tar.gz -C /usr/local/ cd /usr/local sudo mv ./idea-IC-241.17011.79 ./idea sudo chown -R hadoop:hadoop ./idea cd /usr/local/idea/bin ./idea.sh 2、配置IDEA环境变量 配置IDEA环境变量的目的是无论终端在哪个工作目录,都可以通过idea.sh指令启动IDEA,不用进入到IDEA的环境目录了。 我们通过vim指令对环境变量文件进行编辑: vim ~/.bashrc 然后将如下的内容添加至~/.bashrc文件 export IDEA_HOME=/usr/local/idea export PATH=:$PATH:${IDEA_HOME}/bin 然后通过:wq进行保存即可。 接着我们让系统重新加载我们修改好的环境变量: source ~/.bashrc 之后我们就可以在任意目录下输入idea.sh启动IDEA图形化界面了。 3.给IDEA安装中文插件(可用可不用) 我们首先启动IDEA,认真阅读使用协议后,选择同意,并点击Continue. 选择完毕后,就进入了IDEA的欢迎界面了,我们点击左侧的Plugins. 在顶部的搜索框里面,输入Chinese,就可以找到中文的汉化插件。 在开始本实验之前,首先要启动Flink。 下面介绍如何使用IntelliJ IDEA工具开发WordCount程序。 启动进入IDEA,如下图所示,新建一个项目。填写GroupId和ArtifactId。这里的GroupId是dblab,ArtifactId是FlinkWordCount。设置Project name为FlinkWordCount。 打开pom.xml文件,输入如下内容: <dependencies> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-java</artifactId> <version>1.9.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-streaming-java_2.11</artifactId> <version>1.9.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-clients_2.11</artifactId> <version>1.9.1</version> </dependency> </dependencies> 创建Package输入package的名称为“cn.edu.xmu”。再新建一个java class文件。输入文件名称WordCountData。WordCountData.java用于提供原始数据,其内容如下: package cn.edu.xmu; import org.apache.flink.api.java.DataSet; import org.apache.flink.api.java.ExecutionEnvironment; public class WordCountData { public static final String[] WORDS=new String[]{"To be, or not to be,--that is the question:--", "Whether \'tis nobler in the mind to suffer", "The slings and arrows of outrageous fortune", "Or to take arms against a sea of troubles,", "And by opposing end them?--To die,--to sleep,--", "No more; and by a sleep to say we end", "The heartache, and the thousand natural shocks", "That flesh is heir to,--\'tis a consummation", "Devoutly to be wish\'d. To die,--to sleep;--", "To sleep! perchance to dream:--ay, there\'s the rub;", "For in that sleep of death what dreams may come,", "When we have shuffled off this mortal coil,", "Must give us pause: there\'s the respect", "That makes calamity of so long life;", "For who would bear the whips and scorns of time,", "The oppressor\'s wrong, the proud man\'s contumely,", "The pangs of despis\'d love, the law\'s delay,", "The insolence of office, and the spurns", "That patient merit of the unworthy takes,", "When he himself might his quietus make", "With a bare bodkin? who would these fardels bear,", "To grunt and sweat under a weary life,", "But that the dread of something after death,--", "The undiscover\'d country, from whose bourn", "No traveller returns,--puzzles the will,", "And makes us rather bear those ills we have", "Than fly to others that we know not of?", "Thus conscience does make cowards of us all;", "And thus the native hue of resolution", "Is sicklied o\'er with the pale cast of thought;", "And enterprises of great pith and moment,", "With this regard, their currents turn awry,", "And lose the name of action.--Soft you now!", "The fair Ophelia!--Nymph, in thy orisons", "Be all my sins remember\'d."}; public WordCountData() { } public static DataSet<String> getDefaultTextLineDataset(ExecutionEnvironment env){ return env.fromElements(WORDS); } } 按照刚才同样的操作,创建第2个文件WordCountTokenizer.java。 WordCountTokenizer.java用于切分句子,其内容如下: package cn.edu.xmu; import org.apache.flink.api.common.functions.FlatMapFunction; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.util.Collector; public class WordCountTokenizer implements FlatMapFunction<String, Tuple2<String,Integer>>{ public WordCountTokenizer(){} public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception { String[] tokens = value.toLowerCase().split("\\W+"); int len = tokens.length; for(int i = 0; i<len;i++){ String tmp = tokens[i]; if(tmp.length()>0){ out.collect(new Tuple2<String, Integer>(tmp,Integer.valueOf(1))); } } } } 按照刚才同样的操作,创建第3个文件WordCount.java。 WordCount.java提供主函数,其内容如下: package cn.edu.xmu; import org.apache.flink.api.java.DataSet; import org.apache.flink.api.java.ExecutionEnvironment; import org.apache.flink.api.java.operators.AggregateOperator; import org.apache.flink.api.java.utils.ParameterTool; public class WordCount { public WordCount(){} public static void main(String[] args) throws Exception { ParameterTool params = ParameterTool.fromArgs(args); ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); env.getConfig().setGlobalJobParameters(params); Object text; //如果没有指定输入路径,则默认使用WordCountData中提供的数据 if(params.has("input")){ text = env.readTextFile(params.get("input")); }else{ System.out.println("Executing WordCount example with default input data set."); System.out.println("Use -- input to specify file input."); text = WordCountData.getDefaultTextLineDataset(env); } AggregateOperator counts = ((DataSet)text).flatMap(new WordCountTokenizer()).groupBy(new int[]{0}).sum(1); //如果没有指定输出,则默认打印到控制台 if(params.has("output")){ counts.writeAsCsv(params.get("output"),"\n", " "); env.execute(); }else{ System.out.println("Printing result to stdout. Use --output to specify output path."); counts.print(); } } } 项目目录结构如下图所示。 执行成功以后,可以看到词频统计结果。 下面要把代码进行编译打包,打包成jar包。为此,需要做一些准备工作。 如下图所示,进入设置界面。 如下图所示进入Project Structure界面。 如下图所示进行设置。 如下图所示进行设置。 如下图所示进行设置。 如下图所示进行设置。 如下图所示进行设置。在搜索框中输入“WordCount”就会自动搜索到主类,然后在搜索到的结果条上双击鼠标。 如下图所示,设置META-INF目录。 如下图所示进行设置。 如下图所示,进入编译打包菜单。 如下图所示,编译打包成功以后,可以看到生成的FlinkWordCount.jar文件。 最后,到Flink中运行FlinkWordCount.jar。这里一定要注意,要确认已经开启Flink系统。运行的命令和执行结果如下图所示。 /usr/local/flink/bin/flink run --class cn.edu.xmu.WordCount ~/IdeaProjects/FlinkWordCount/out/artifacts/FlinkWordCount.jar | |||||
出现的问题: 1.新建java的maven工程遇到Cannot resolve plugin org.apache.maven.plugins:maven-clean-plugin:3.2.0 | |||||
解决方案(列出遇到的问题和解决办法,列出没有解决的问题): 1.新建java的maven工程遇到Cannot resolve plugin org.apache.maven.plugins:maven-clean-plugin:3.2.0 解决方案:去设置里面把maven换成虚拟机目录下的maven地址 未解决的问题: 黄色波浪线仍存在,但是不影响运行 |