Receiver在Datanode的服务器是DataXceiverServer,它通过创建daemon线程DataXceiver来实现读写数据。
级联的写数据。
DataXceiver.writeBlock()
啥时候是Datanode发起的?
@Override
public void writeBlock(final ExtendedBlock block,
final StorageType storageType,
final Token blockToken,
final String clientname,
final DatanodeInfo[] targets, //所有的datanode信息
final StorageType[] targetStorageTypes,
final DatanodeInfo srcDataNode,
final BlockConstructionStage stage,
final int pipelineSize,
final long minBytesRcvd,
final long maxBytesRcvd,
final long latestGenerationStamp,
DataChecksum requestedChecksum,
CachingStrategy cachingStrategy,
boolean allowLazyPersist,
final boolean pinning,
final boolean[] targetPinnings,
final String storageId,
final String[] targetStorageIds) throws IOException
构造连接
mirrorNode = targets[0].getXferAddr();
mirrorTarget = NetUtils.createSocketAddr(mirrorNode);
mirrorSocket = datanode.newSocket();
//向下游发送写请求
new Sender(mirrorOut)
//接收下游的ack请求
connectAck = BlockOpResponseProto.parseFrom(XX(mirrorIn))
mirrorInStatus = connectAck.getStatus();
firstBadLink = connectAck.getFirstBadLink();
连接是否成功
ACK状态成功说明创建成功,出现异常说明连接创建失败
失败处理逻辑
关闭下游节点的socket,输入流和输出流,向reployOut汇报情况
BlockOpResponseProto.newBuilder()
.writeDelimitedTo(replyOut);
blockReceiver.receiverBlock();
blockReceiver负责接收上游的数据块
数据切分成packet,客户端切分吗?
BlockReceiver从下游接收数据包的ACK,然后传给上游。packetResponser独立线程实现。
BlockReceiver.finalizeBlock()结束接收
调用datanode.closeBlock()
最终调用BlockPoolOfferService.notifyNamenodeReceivedBloce()通知NM
client提交
首先构造pipeline
然后发送数据块
receivepacket处理具体的落盘和转发
packetresponser处理ack
结束后上报nn