如何用javaAPI访问hdfs文件

1.环境:借助阿里云服务器搭建的hadoop平台,hadoop版本3.0.3,伪分布式
2.操作:在idea里通过javaAPI读取hdfs文件里的内容
import java.io.IOException;
 
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.Test;
 
public class HdfsDemoApp {
    @Test
    public static void main(String[] args) {
        try {
 
            //创建Configuration对象
            Configuration conf = new Configuration();
            //设置Hadoop的dfs客户端使用hostname访问datanode
            //conf.set("dfs.client.use.datanode.hostname", "true");
            conf.set("fs.defaultFS", "hdfs://master:9000");
            FileSystem fs = FileSystem.get(conf);
            // 打开hdfs上的文件并读取输出
            Path hello = new Path("/user/hdfs/artist.txt");
            FSDataInputStream ins = fs.open(hello);
            int ch = ins.read();
            while (ch != -1) {
                System.out.print((char) ch);
                ch = ins.read();
            }
            System.out.println();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

3.遇到的问题:无法获取到数据块,报错:Could not obtain block
4.分析原因:文件夹和文件名都是存放在 NameNode 上的,本地可以通过公网访问 NameNode,所以创建文件夹和文件都可以,但是写数据的时候,NameNode 和DataNode 是通过内网通信的,NameNode 会返回给本地 DataNode 的内网 IP,本地就访问不了了。
5.解决方案:让NameNode不返回DataNode的私网IP,而返回的是DataNode的主机名
方案一:在代码中添加配置信息(理论上应该是可行的,但不知是哪里出了问题,我没有成功)(弊端就是程序都要配置)
            //创建Configuration对象
            Configuration conf = new Configuration();
            //设置Hadoop的dfs客户端使用hostname访问datanode
            conf.set("dfs.client.use.datanode.hostname", "true");
 
方案二:修改hdfs-site.xml和core-site.xml并且把这两个配置文件放在IDEA的resources目录下,好处就是在一个项目中只需要配置一次,坏处就是当你用spark读取本地文件的时候,它会自动去读取hdfs上的文件,用file:///(\\\)+绝对路径可访问本地文件
1)hdfs-site.xml
   <!--返回datanode的主机名-->
    <property>
        <description>only cofig in clients</description>
        <name>dfs.client.use.datanode.hostname</name>
        <value>true</value>
    </property>

2)core-site.xml
<configuration>
	        <property>
		            <name>hadoop.tmp.dir</name>
			    <value>file:/opt/hadoop/tmp</value>
		    </property>
		    <property>
			    <name>fs.defaultFS</name>
			    <value>hdfs://master:9000</value>
			    <!-- <value>hdfs://localhost:9000</value> -->
			</property>
 
			<property>
				 <name>hadoop.proxyuser.hadoop.hosts</name>
				  <value>*</value>
			</property> 
			<property>
				   <name>hadoop.proxyuser.hadoop.groups</name>
				    <value>*</value>
				</property>
				<!-- 是否在HDFS中开启权限检查 -->
				        <property>
							 <name>dfs.permissions.enabled</name>
					  		<value>false</value>
				</property>
 
</configuration>

然后,在阿里云的***添加规则,手动添加DataNode用于数据传输服务端口 默认是 9866(hadoop3.0之前的端口是50010)。
附上hadoop3.x的端口变化:
Namenode ports: 50470 --> 9871, 50070 --> 9870, 8020 --> 9820
Secondary NN ports: 50091 --> 9869, 50090 --> 9868
Datanode ports: 50020 --> 9867, 50010 --> 9866, 50475 --> 9865, 50075 --> 9864

 
最后配置本地host映射

hosts文件在Windows下的路径为:

C:\Windows\System32\drivers\etc\hosts

在文件中添加:

    公网IP  主机名(我的是master)


全部评论

相关推荐

数开小菜鸡_暂退沉淀版:大二第三段,还是字节,这下真得点点举办了
点赞 评论 收藏
分享
吴offer选手:学到了,下次面试也放张纸在电脑上,不然老是忘记要说哪几个点
点赞 评论 收藏
分享
刘湘_passion:出国旅游?那就小心你的腰子咯
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务