1. 背景
在 Hadoop 3.1 中执行 DataNode 动态刷新配置时,使用了下面的命令:
hdfs dfsadmin -reconfig datanode xx.88:50010 properties
命令执行后,DataNode 日志中出现如下异常:
ERROR datanode.DataNode (DataXceiver.java:run(321)) - xx:50010:DataXceiver error processing unknown operation src: /xx.28:52724 dst: /xx.28:50010
java.io.IOException: Version Mismatch (Expected: 28, Received: 26738 )
at org.apache.hadoop.hdfs.protocol.datatransfer.Receiver.readOp(Receiver.java:73)
at org.apache.hadoop.hdfs.server.datanode.DataXceiver.run(DataXceiver.java:269)
at java.lang.Thread.run(Thread.java:748)
从日志看,报错位置在 DataXceiver,不是 NameNode,也不是 dfsadmin 客户端本身。
这个问题的原因不是 Hadoop 版本不一致,也不是 DataNode 真的不能 reconfig,而是命令中使用了错误的 DataNode 端口。
2. 问题现象
异常中有几个关键信息:
dst: /xx.28:50010
DataXceiver error processing unknown operation
Version Mismatch (Expected: 28, Received: 26738 )
其中 50010 是 Hadoop 2.x 中常见的 DataNode 数据传输端口,也就是 dfs.datanode.address 对应的端口。这个端口主要用于 HDFS 客户端和 DataNode 之间读写 block 数据。
但是 hdfs dfsadmin -reconfig datanode 不是读写 block 数据,它是一个管理命令,需要访问 DataNode 的 IPC/RPC 端口。
这两个端口不是一回事。
3. 原因分析
3.1 -reconfig 需要连接的是 IPC 端口
Hadoop 3.1.1 官方 HDFS Commands Guide 中对 -reconfig 的参数说明如下:
hdfs dfsadmin [-reconfig <namenode|datanode> <host:ipc_port> <start |status |properties>]
也就是说,第二个参数应该是:
host:ipc_port
这里明确写的是 ipc_port,不是 DataNode 的数据传输端口。
如果要对 DataNode 做动态配置,可以使用:
hdfs dfsadmin -reconfig datanode <datanode_host>:<datanode_ipc_port> properties
hdfs dfsadmin -reconfig datanode <datanode_host>:<datanode_ipc_port> start
hdfs dfsadmin -reconfig datanode <datanode_host>:<datanode_ipc_port> status
3.2 50010 是 DataNode 数据传输端口
在 Hadoop 2.x 或者一些兼容旧端口的发行版中,常见端口如下:
| 配置项 | 端口 | 作用 |
|---|---|---|
dfs.datanode.address |
50010 |
DataNode 数据传输端口,读写 block 使用 |
dfs.datanode.ipc.address |
50020 |
DataNode IPC/RPC 管理端口 |
dfs.datanode.http.address |
50075 |
DataNode Web 页面端口 |
而 Hadoop 3.x 默认端口已经调整,常见默认值如下:
| 配置项 | Hadoop 3.x 默认端口 | 作用 |
|---|---|---|
dfs.datanode.address |
9866 |
DataNode 数据传输端口 |
dfs.datanode.ipc.address |
9867 |
DataNode IPC/RPC 管理端口 |
dfs.datanode.http.address |
9864 |
DataNode Web 页面端口 |
所以在 Hadoop 3.1 中,如果没有保留旧端口配置,正确的 reconfig 端口一般应该是 9867。
如果集群为了兼容旧版本保留了旧端口,那么正确的 reconfig 端口一般是 50020,而不是 50010。
3.3 为什么会报 Version Mismatch
DataNode 的 50010 端口运行的是 HDFS DataTransferProtocol。这个协议用于处理 block 读写请求,DataXceiver 会按照数据传输协议读取客户端发来的内容。
但是 hdfs dfsadmin -reconfig 发出的请求是 Hadoop RPC 请求。
也就是说:
RPC 请求 -> 发到了 DataTransfer 端口
DataXceiver 收到后,会尝试按照 DataTransferProtocol 读取协议版本。它期望读取到的数据传输协议版本是 28,但实际读到的是 26738,于是报:
Version Mismatch (Expected: 28, Received: 26738 )
这个 26738 也很有意思。26738 转成十六进制是:
0x6872
而 0x68 0x72 对应 ASCII 字符是:
h r
Hadoop RPC 连接头通常以 hrpc 开始。也就是说,DataXceiver 在数据传输端口上读到了 RPC 请求头的前两个字节,于是把它当成 DataTransferProtocol 的版本号,最后就出现了这个看起来像“版本不匹配”的错误。
所以这个异常表面上是版本不匹配,本质上是协议不匹配。
4. 解决方式
4.1 查询当前 DataNode IPC 端口
不要直接使用 hdfs dfsadmin -report 中看到的 DataNode 地址作为 reconfig 地址,因为 report 中显示的 Name: host:port 通常是 DataNode 的数据传输地址。
更稳妥的方式是直接查看配置:
hdfs getconf -confKey dfs.datanode.ipc.address
如果输出类似:
0.0.0.0:9867
则说明 DataNode IPC 端口是 9867。
如果输出类似:
0.0.0.0:50020
则说明集群使用的是旧端口配置,DataNode IPC 端口是 50020。
也可以在 DataNode 节点上查看监听端口:
ss -lntp | grep -E '50010|50020|9866|9867'
正常情况下可以看到 DataNode 同时监听数据传输端口和 IPC 端口。
4.2 使用正确端口执行 reconfig
如果集群使用 Hadoop 3.x 默认端口:
hdfs dfsadmin -reconfig datanode xx.88:9867 properties
如果集群保留了 Hadoop 2.x 常见旧端口:
hdfs dfsadmin -reconfig datanode xx.88:50020 properties
如果要真正触发配置刷新,可以执行:
hdfs dfsadmin -reconfig datanode xx.88:50020 start
然后查看状态:
hdfs dfsadmin -reconfig datanode xx.88:50020 status
实际端口以当前集群的 dfs.datanode.ipc.address 为准。
4.3 先用 getDatanodeInfo 验证端口是否正确
在执行 reconfig 之前,可以先用下面的命令测试 DataNode IPC 端口是否可用:
hdfs dfsadmin -getDatanodeInfo xx.88:50020
如果端口正确,应该能返回 DataNode 信息。
如果仍然把端口写成 50010,就可能继续在 DataNode 日志中看到 DataXceiver 的协议解析异常。
5. 排查思路总结
这个问题可以按照下面的顺序排查:
- 先确认命令中使用的是不是 DataNode IPC 端口。
- 查看
dfs.datanode.ipc.address的实际配置。 - 区分
dfs.datanode.address和dfs.datanode.ipc.address。 - 不要把
dfsadmin -report里显示的 DataNode 数据传输端口直接拿来执行reconfig。 - 使用
getDatanodeInfo验证 IPC 端口可用后,再执行reconfig。
排查这类问题时,关键是先判断日志来自哪个服务端线程。
这次日志来自:
DataXceiver
而 DataXceiver 处理的是 DataNode 数据传输协议。如果一个管理命令触发了 DataXceiver 的 Version Mismatch,就应该优先怀疑命令连接到了错误端口,而不是优先怀疑 Hadoop jar 包版本不一致。
6. 总结
这次问题的根因是:
hdfs dfsadmin -reconfig datanode 使用了 DataNode 数据传输端口 50010,
但该命令要求使用 DataNode IPC/RPC 端口。
正确命令应该类似:
# Hadoop 3.x 默认端口
hdfs dfsadmin -reconfig datanode xx.88:9867 properties
# 如果集群保留旧端口配置
hdfs dfsadmin -reconfig datanode xx.88:50020 properties
Version Mismatch (Expected: 28, Received: 26738) 并不一定表示 Hadoop 版本真的不一致。在这个场景下,它表示 RPC 协议请求被发送到了 DataTransferProtocol 端口,DataNode 按错误协议解析了请求。
简单来说:
50010 / 9866 是 DataNode 数据传输端口
50020 / 9867 是 DataNode IPC 管理端口
reconfig 要使用 IPC 管理端口