问题
采用CDH搭建的hadoop集群环境,命令行上传文件正常,Java代码上传报如下错误
could only be replicated to 0 nodes instead of minReplication (=1). There are 3 datanode(s) running
翻译:
只能复制到0个节点,而不是minReplication(=1)。有3个datanode(s)运行
就是说:多个nodedata要做副本处理,结果当前只有一个节点,但是不能到这一个节点
核查
1、首先核对集群状态
服务器名称 | 角色 |
---|---|
cdh1 | namenode、secondynamenode |
cdh2 | datanode |
cdh3 | datanode |
cdh4 | datanode |
表中可知,主节点cdh1并不负责数据的存贮,疑惑是为啥shell端能够上传成功,Java端却失败?
2、接下来查看端口
namenode 端口为 8020
8020 是客户端访问hdfs的namenode端口
datanode端口为9866
9866端口是hdfs文件系统datanode的数据传输接口
分析HDFS文件写流程
以hadoop fs -put a.txt /这条命令为例,假设副本数为3。
1.客户端执行了命令后,会向NameNode发起上传请求,走的是RPC协议。
2.NameNode收到请求,会校验是否有权限操作,而且会检查目录是否存在。
3.NameNode给客户端反馈是否可以上传的标记。
4.如果可以上传,则客户端会将文件切片,假如是将a.txt切成了三片。
5.客户端发起上传第一个block的请求。
6.NameNode会根据副本放置策略以及主机优秀程度选出三台主机,并将主机列表返回给客户端。
7.客户端和主机列表中排在最前面的主机建立pipeline,最前面的主机又会和第二台主机建立pipeline,第二台和第三台也建立pipeline,形成一个从客户端到三台主机的线性管道。
8.考虑到网络传输性能,客户端上传block时会再次切片,将block切成多个64KB大小的package,一个个的上传。
9.第一台主机收到package,会缓存,然后传给第二台,第二台缓存传给第三台,第三台缓存后返回写应答表示收到了,第二台收到应答,给第一台写应答,第一台收到给客户端写应答。
10.客户端收到写应答,会传下一个package。
11.重复这个过程,直到所有的package传完,三台主机会将缓存中的package合成block,落盘。
12.之后上传第二个和第三个block。
13.都传完后,客户端会向NameNode汇报上传完成。
14.NameNode更新元数据。
总结:客户端直接访问Datanode节点去写入数据
尝试
公司产品对hdfs的使用场景为:创建文件夹、上传文件等
1、首先测试文件夹创建功能:可以正常创建,但是上传文件的时候却报错
更具上述原理推测,namenode维护文件索引,Java程序能成功访问namenode节点(cdh1),所以能够成功创建,但是访问不到另外三台Datanode的机器(cdh2,cdh3,cdh4),所以导致上传失败。
证明:该产品有2套,分别为:正式环境、测试环境,正式环境产品的hdfs使用没有任何问题,且能够成功创建和上传,测试环境没法上传
后续发现正式环境的IP和CDH集群属于同一网段,且CDH主机防火墙已经关闭,所以不存在网络不通之说,而测试环境和CDH不是同一网段,所以存在网络不通
2、网络不通的判定
1)datanode节点之间
hdfs-site.xml个配置,datanode的 client通信是否使用域名,默认为false,改为true
<!-- datanode 通信是否使用域名,默认为false,改为true -->
<property>
<name>dfs.client.use.datanode.hostname</name>
<value>true</value>
<description>Whether datanodes should use datanode hostnames when
connecting to other datanodes for data transfer.
</description>
</property>
询问开发,代码中添加相关配置,所以, hadoop集群中的从节点之间是通过域名去通信的,通过核查 /etc/hosts发现,三台主机均配置主机映射,况且就算datanode节点之间没有主机映射,Java客户端只要能成功访问某一台datanode主机,也能成功上传文件,最多没法复制副本,所以,该可能性排除。
2)Java端的主机访问不到Datanode主机
查看网络发现,产品跟环境主机之间的通信是通过端口映射,也就是客户端并没法完全访问到CDH集群的所有主机,只能访问部分,如果datanode的9866端口并没有开放给Java端,也就没法上传文件。
测试远程端口是否开放:
yum -y install nmap
nmap 192.2.x.x -p 9866 # 测试端口
根据显示close/open确定端口是否打开。
发现端口并未开放,通知用户开放相应端口
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类