zoukankan      html  css  js  c++  java
  • 记一次菜鸟的问题排查:Docker搭建hadoop集群,通过JAVA API上传文件时出现异常Exception in thread "main" org.apache.hadoop.ipc.RemoteException(java.io.IOException)

    先说我的情况:

    利用Docker搭建hadoop集群,包含1个master节点,2个slave节点。集群启动时将容器的50070、8088等端口映射到宿主机端口。在通过浏览器访问集群时访问"宿主机IP:映射端口"。到浏览器访问这一步都正常。但是在通过java api向集群上传文件时出现异常如下:

    Exception in thread "main" org.apache.hadoop.ipc.RemoteException(java.io.IOException): File /tmp/hadoop-yarn/staging/root/.staging/job_1556205714449_0006/job.split could only be replicated to 0 nodes instead of minReplication (=1).  There are 3 datanode(s) running and 3 node(s) are excluded in this operation.
        at org.apache.hadoop.hdfs.server.blockmanagement.BlockManager.chooseTarget4NewBlock(BlockManager.java:1625)
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getNewBlockTargets(FSNamesystem.java:3132)
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:3056)
        at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.addBlock(NameNodeRpcServer.java:725)
        at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.addBlock(ClientNamenodeProtocolServerSideTranslatorPB.java:493)
        at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)
        at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:616)
        at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:982)
        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2217)
        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2213)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:422)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1758)
        at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2213)
    
        at org.apache.hadoop.ipc.Client.call(Client.java:1476)
        at org.apache.hadoop.ipc.Client.call(Client.java:1413)
        at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:229)
        at com.sun.proxy.$Proxy10.addBlock(Unknown Source)
        at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.addBlock(ClientNamenodeProtocolTranslatorPB.java:418)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:191)
        at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:102)
        at com.sun.proxy.$Proxy11.addBlock(Unknown Source)
        at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.locateFollowingBlock(DFSOutputStream.java:1603)
        at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.nextBlockOutputStream(DFSOutputStream.java:1388)
        at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:554)
    
    Process finished with exit code 1

     开始我的漫漫排查之路……

    1、先查下异常的原因,最终找到一个靠谱的资料(关键时刻stack over flow是比国内网站各种鱼龙混杂的论坛好用啊)

    https://stackoverflow.com/questions/15571584/writing-to-hdfs-could-only-be-replicated-to-0-nodes-instead-of-minreplication

    根据这个资料,出现问题的原因有可能是集群格式化或者防火墙有问题,

    2、尝试删除文件后重新格式化并启动,关闭防火墙,结果:doesn't work

    偶然发现,在重启成功之后在linux下用hdp客户端进行了一些简单验证,创建文件夹,上传文件,发现都是正常的。这说明我的集群没有问题啊。

    再看看用java api上传文件时,虽然程序提示异常,但是在集群上依然可以看到我上传的文件的文件名,但是文件大小为0。所以我通过api访问集群时和namenode节点的交互也是没有问题的。因为namenode存储的是数据的元数据信息,而datanode存储数据的具体内容。

    所以很有可能是我的java 客户端和datanode的交互出现了问题。是我的编程有问题?重新检查了以下,应该没错。

    我运行java程序的机器跟集群不能连通?通过浏览器访问也是这台机器没有问题啊。

    再去重新看看1中查到的资料,还有一个原因是datanode节点的端口问题。结合我这里出现的只有文件名没有文件数据的情况,很有可能是这个问题。

    hdp客户端和namenode之间有数据传输、client和datanode之间也有数据传输,我的集群没有把datanode和client进行数据传输的50010端口映射到宿主机上。当客户端通过访问“节点名:端口”的方式向端口发送数据的时候是不能成功的。

    2、开放datanode的50010端口。

    但是开放datanode端口有个问题,不像8088这样的端口,一个集群中就只有一个节点需要开放这个端口,每个datanode都会开放一个50010端口,不能全部映射到宿主机的50010端口。如果每个都指定一个映射的话,太麻烦了。其实这个时候,我启动容器的镜像是通过commit的方式创建的,之前查资料看到DockerFile制作的镜像,在启动时候启动端口随机映射就只需要加一个-P,之前一直遗留没有解决的Dockerfile制作镜像的工作决定拾起来做完。

    3、通过Dockerfile制作hadoop镜像

    这期间也是各种踩坑各种踩坑各种踩坑,终于找到了合适的方式,这里是总结的制作过程。在这一步踩坑之后想死的心都有了,总算弄好了,该解决了吧。。。

    4、通过通过DockerFile制作镜像,开放50010端口,启动时使用-P参数。依然doesn't work。

    这是咋回事?我不是已经映射到宿主机端口了吗?难道不是这个端口的问题?回头看了下1中的资料,总觉得问题就在这里。又仔细想了下,我把端口随机映射了,但是我的程序不知道啊,是不是需要配置哪个配置信息让我的客户端知道?配置hdfs-site.xml中的datanode端口为映射后的端口,但是这个每个节点都不一样,该怎么配?查资料,半天,无果。作为以命菜鸟,这中间的原理也没有特别清楚,不知道有没有啥不了解的细节,差不到资料,或许我可以换个思路?

    5、其实,到这一步已经弄清楚了问题的根源。我的问题的关键点就在于,我用于编程的PC和docker的宿主机在一个网段,可以通信,所以当我把容器50070等端口映射到宿主机后就可以通过我的PC访问端口;docker宿主机也可以与运行在它上面的容器进行通信,所以我可以通过在宿主机上执行命令行正确操作集群。那么,我现在只要让我的PC可以和宿主机上的容器集群通信就可以了啊,要是PC可以通过容器的IP访问,那管它hdp内部啥机制,我就把我的环境模拟的更普通集群一样了不久没乱七八糟问题了。为了解决容器向局域网暴露独立IP这一问题,又是一个大坑,具体细节看这里

    6、由于hdp严重依赖主机名进行通信,所以记得在运行java程序的机器上配置host,记录主机名和IP的映射。windows配置host自行百度。

     至此,问题算是解决了,终于可以在本地运行java程序操作集群了,不过啊,本地调试主要还是用单机版。。。。。。

  • 相关阅读:
    Ajax基础:3.Json
    Head First Design Patterns State Pattern
    Head First Design Patterns Template Method Pattern
    Articles For CSS Related
    Head First Design Patterns Decorator Pattern
    代码审查工具
    How To Be More Active In A Group
    Head First Design Patterns Factory Method Pattern
    Head First Design Patterns Composite Pattern
    Tech Articles
  • 原文地址:https://www.cnblogs.com/Jing-Wang/p/10855522.html
Copyright © 2011-2022 走看看