hadoop异常: java.io.EOFException: Unexpected end of input stream

本文详细解析了在执行Hadoop任务时遇到的EOFException错误,主要由HDFS上异常结束的文件引起,特别是flume采集的日志文件。文章深入介绍了flume采集日志的逻辑,并提供了两种解决方案:一是删除空的gz文件;二是调整文件分割参数以避免分割压缩文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

执行hadoop任务时报错:

2019-06-05 03:23:36,173 INFO [main] org.apache.hadoop.mapred.MapTask: Processing split: Paths:/flume/nginx/app1/2019-06-05/00/app1@flume23_10003_4.1559665890953.gz:0+0,/flume/nginx/app2/2019-06-05/00/app2@flume174_10003_9.1559665804394.gz:0+307548
2019-06-05 03:23:36,257 WARN [main] org.apache.hadoop.security.UserGroupInformation: PriviledgedActionException as:kwang (auth:SIMPLE) cause:java.io.EOFException: Unexpected end of input stream
2019-06-05 03:23:36,258 WARN [main] org.apache.hadoop.mapred.YarnChild: Exception running child : java.io.EOFException: Unexpected end of input stream 
    at org.apache.hadoop.io.compress.DecompressorStream.decompress(DecompressorStream.java:165)
    at org.apache.hadoop.io.compress.DecompressorStream.read(DecompressorStream.java:105)
    at java.io.InputStream.read(InputStream.java:101)
    at org.apache.hadoop.util.LineReader.fillBuffer(LineReader.java:180)
    at org.apache.hadoop.util.LineReader.readDefaultLine(LineReader.java:216)
    at org.apache.hadoop.util.LineReader.readLine(LineReader.java:174)
    at org.apache.hadoop.mapreduce.lib.input.LineRecordReader.skipUtfByteOrderMark(LineRecordReader.java:144)
    at org.apache.hadoop.mapreduce.lib.input.LineRecordReader.nextKeyValue(LineRecordReader.java:184)
    at org.apache.hadoop.mapreduce.lib.input.CombineFileRecordReaderWrapper.nextKeyValue(CombineFileRecordReaderWrapper.java:90)
    at org.apache.hadoop.mapreduce.lib.input.CombineFileRecordReader.nextKeyValue(CombineFileRecordReader.java:69)
    at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.nextKeyValue(MapTask.java:562)
    at org.apache.hadoop.mapreduce.task.MapContextImpl.nextKeyValue(MapContextImpl.java:80)
    at org.apache.hadoop.mapreduce.lib.map.WrappedMapper$Context.nextKeyValue(WrappedMapper.java:91)
    at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:793)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341)
    at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:164)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:415)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1924)
    at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)

产生原因:

以上报错原因基本都是由于HDFS上的文件异常结束导致的,通过查看log,发现/flume/nginx/app1/2019-06-05/00/app1@flume23_10003_4.1559665890953.gz:0+0 这个文件的大小为0字节。要理解空文件的产生,先需要清楚集群flume采集日志的逻辑,集群中采用flume采集到日志写入到HDFS,采集过程中flume会先新建一个*.gz.tmp文件,flume持续的向*.gz.tmp文件中追加数据,在写周期到达时将*.gz.tmp重命名为*.gz,而空文件产生的原因是flume新建了*.gz.tmp文件后,没有新数据产生,重命名后文件大小为空。

解决办法:
将空gz文件删除后重新运行任务即可。

 

还有另一种原因,当设置了如下参数对文件进行分割切片时,导致部分文件为空文件,从而解析过程中出现异常。当然,这种原因取决于文件的原始格式是否可压缩,像gz、snappy、lzo文件是不可分割的,设置如下参数就不会出现以上报错,像orc文件是可分割的,设置如下参数可能会出现以上异常。

-Dmapreduce.input.fileinputformat.split.minsize=134217728 -Dmapreduce.input.fileinputformat.split.maxsize=512000000

 

【参考资料】

[1]. 菜菜光, hadoop Unexpected end of input stream 错误.

转载于:https://www.cnblogs.com/walker-/p/10980995.html

<think>我们正在处理一个复杂的Hadoop集群问题,涉及两个节点(hadoop2和hadoop3)上的datanode进程无法启动,并且日志中出现java.io.EOFException错误。同时,用户提到了9820端口(可能是datanode的IPC端口)以及HA配置环境。根据提供的引用内容,错误信息与“PrematureEOFfrominputStream”有关,引用[2]指出可能的原因包括文件操作超租期(文件被删除)或datanode的并发处理线程数达到上限。让我们逐步分析并解决此问题:###1.理解错误根本原因根据引用[1][2]:-`java.io.IOException:PrematureEOFfrominputStream`通常发生在数据传输过程中流提前结束。-在HDFS中,常见原因包括:-**文件被删除**:当多个任务(如MapReduce任务)操作同一个文件时,一个任务完成删除文件会导致其他任务访问该文件时出现此错误(引用[2])。-**datanode并发线程数限制**:`dfs.datanode.max.transfer.threads`参数(默认4096)设置datanode同时处理请求的上限。如果达到上限,可能导致新连接被拒绝,从而引发此错误(引用[2])。在HA配置下,datanode需要同时与多个namenode通信,可能会增加线程使用量。###2.检查datanode无法启动的具体原因由于用户明确说明datanode进程未启动,我们需要先检查datanode日志以确定启动失败的原因。通常,datanode日志位于`$HADOOP_HOME/logs/hadoop-<username>-datanode-<hostname>.log`。####关键排查步骤:-**检查日志**:在hadoop2和hadoop3节点上查看datanode日志,搜索`ERROR`、`FATAL`或`Exception`。-**检查端口冲突**:9820端口是datanode的IPC端口,确保该端口未被其他进程占用:```bashnetstat-tuln|grep9820```-**检查HA配置**:确认datanode的`hdfs-site.xml`中HA相关配置是否正确(如nameserviceID、namenodeRPC地址等)。###3.解决`java.io.EOFException`问题根据引用[3],用户提供了一个脚本用于删除HDFS上大小为0的文件。这提示我们:**HDFS上的空文件或损坏文件可能导致异常**。如果datanode在启动过程中需要加载某些块,而相关文件为空或损坏,就可能导致EOF异常。####解决方案:-**删除空文件**:运行用户提供的脚本(引用[3])或类似逻辑,清除HDFS上所有大小为0的文件。注意:该脚本会遍历指定目录并删除空文件,但需根据实际路径调整。-**增加datanode线程数**:如果并发线程不足,可适当增加`dfs.datanode.max.transfer.threads`(最大值8192):```xml<!--在hdfs-site.xml中添加--><property><name>dfs.datanode.max.transfer.threads</name><value>8192</value></property>```-**检查块完整性**:使用`hdfsfsck/`检查HDFS文件系统完整性,并修复损坏的块。###4.HA配置下datanode的特殊处理在HA环境中,datanode会向所有活动的namenode注册。确保:-**ZooKeeper配置正确**:datanode通过ZKFC(ZooKeeperFailoverController)获取活跃namenode信息。-**检查ZKFC状态**:在namenode节点上运行`hdfshaadmin-getServiceStatenn1`(nn1为namenodeID)确认活跃节点。###5.端口问题:98209820端口通常用于datanodeIPC(内部进程通信)。如果该端口被占用,datanode将无法启动。解决方案:-停止占用9820端口的进程,或修改datanode端口(不推荐,需同步修改所有相关配置)。###6.操作步骤总结1.**检查datanode日志**:找到启动失败的直接原因。2.**清理空文件**:运行HDFS空文件清理脚本(参考引用[3])。3.**调整并发线程数**:在`hdfs-site.xml`中增加`dfs.datanode.max.transfer.threads`。4.**检查端口占用**:释放9820端口或确认其可用。5.**验证HA配置**:确保ZKFC和namenode状态正常。6.**重启datanode**:依次重启hadoop2和hadoop3上的datanode:```bashhadoop-daemon.shstopdatanode#如果已有进程,先停止hadoop-daemon.shstartdatanode```###7.预防措施-**监控线程使用**:定期检查datanode的线程使用情况。-**任务调度优化**:避免多个任务同时删除同一文件。-**定期维护**:使用`hdfsfsck`定期检查文件系统健康状态。如果以上步骤仍不能解决问题,请提供具体的datanode日志内容以便深入分析。§§相关问题§§1.如何监控HDFSdatanode的并发线程使用情况?2.HadoopHA配置下datanode注册失败的可能原因?3.除了空文件,还有哪些原因会导致HDFS读写过程中出现`PrematureEOF`错误?</think> ### Hadoop HA环境下DataNode无法启动排查与解决方案(java.io.EOFException) #### 问题定位 1. **根本原因分析** `java.io.EOFException: Premature EOF from inputStream` 错误通常由以下原因引起(参考引用[2][3]): - **文件操作超租期**:HDFS文件在读写过程中被其他任务删除 - **并发线程耗尽**:`dfs.datanode.max.transfer.threads`(默认4096)达到上限 - **空文件/损坏块**:大小为0的lzo压缩文件或损坏数据块(引用[3]) - **HA同步问题**:在HA配置中,DataNode与多个NameNode通信时资源竞争加剧 2. **关键排查点** - DataNode日志(位置:`$HADOOP_HOME/logs/hadoop-*-datanode-*.log`) - 9820端口状态:`netstat -tuln | grep 9820`(确认端口占用情况) - 文件完整性检查:`hdfs fsck / -list-corruptfileblocks` #### 解决步骤(HA配置适用) ```bash # 1. 停止Hadoop服务(所有节点) stop-all.sh # 2. 检查空文件并清理(参考引用[3]脚本) for file in $(hdfs dfs -ls /path/to/data | awk '{print $8}'); do if [ $(hdfs dfs -count $file | awk '{print $2}') -eq 0 ]; then hdfs dfs -rm $file fi done # 3. 调整关键参数(hdfs-site.xml) <property> <name>dfs.datanode.max.transfer.threads</name> <value>8192</value> <!-- 最大允许值 --> </property> <property> <name>dfs.client.block.write.replace-datanode-on-failure.policy</name> <value>NEVER</value> <!-- 防止HA环境下的写入冲突 --> </property> # 4. 修复元数据(NameNode节点) hdfs namenode -recover -force # 5. 重启HA服务 hdfs --daemon start journalnode # 所有JournalNode hdfs --daemon start zkfc # 所有ZKFC hdfs --daemon start namenode # Active/Standby NN hdfs --daemon start datanode # 所有DataNode ``` #### HA环境特殊处理 1. **端口冲突检查** 9820端口是DataNode IPC端口,HA环境下需确保: ```bash # 查看端口冲突 ss -tuln | grep ':9820' # 解决方案:修改hdfs-site.xml <property> <name>dfs.datanode.ipc.address</name> <value>0.0.0.0:9821</value> <!-- 更换端口 --> </property> ``` 2. **HA同步验证** ```bash # 检查NameNode HA状态 hdfs haadmin -getServiceState nn1 hdfs haadmin -getServiceState nn2 # 检查ZKFC日志(位置:$HADOOP_HOME/logs/hadoop-*-zkfc-*.log) ``` #### 预防措施 1. **定期维护脚本** ```bash # 每日检查空文件(加入crontab) hdfs dfs -ls -R / | awk '$5==0 {print $8}' | xargs hdfs dfs -rm ``` 2. **监控配置** ```xml <!-- 启用线程监控 --> <property> <name>dfs.datanode.transfer.socket.recv.buffer.size</name> <value>65536</value> <!-- 增大缓冲区 --> </property> ``` > 若问题持续,优先检查`DataNode`日志中具体错误堆栈,定位是在读写哪个文件时触发EOF异常[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值