haoop rpc服务端读取数据包源码解析注释

来源:互联网 发布:2007版数据透视表教程 编辑:程序博客网 时间:2024/06/03 05:40

RPC包格式:


这图是从别人那拿过来的 留着自己看,主要是对如下这段代码的理解有帮助:

    /**     * 请求报文:4字节hrpc + 1字节Current_version + 1字节authMethod     * 4字节Header_len + connection_header     * 4字节Data_len + call.id + writable     *      * connection_header长度不定  call.id + writable长度不等     *      * 返回报文:call.id + status.state + writable     * errorClass + error     * @return     * @throws IOException     * @throws InterruptedException     */    public int readAndProcess() throws IOException, InterruptedException {      while (true) {        /* Read at most one RPC. If the header is not read completely yet         * then iterate until we read first RPC or until there is no data left.         */            int count = -1;        //读取hrpc信息        if (dataLengthBuffer.remaining() > 0) {          count = channelRead(channel, dataLengthBuffer);                 if (count < 0 || dataLengthBuffer.remaining() > 0)             return count;        }              if (!rpcHeaderRead) {//一次连接 只会读一次          //Every connection is expected to send the header.          if (rpcHeaderBuffer == null) {            rpcHeaderBuffer = ByteBuffer.allocate(2);          }          count = channelRead(channel, rpcHeaderBuffer);          if (count < 0 || rpcHeaderBuffer.remaining() > 0) {            return count;          }          //读取current_version信息          int version = rpcHeaderBuffer.get(0);          //读取authMethod(认证方法)信息          byte[] method = new byte[] {rpcHeaderBuffer.get(1)};          authMethod = AuthMethod.read(new DataInputStream(new ByteArrayInputStream(method)));          dataLengthBuffer.flip();                    if (!HEADER.equals(dataLengthBuffer) || version != CURRENT_VERSION) {            //Warning is ok since this is not supposed to happen.            LOG.warn("Incorrect header or version mismatch from " + hostAddress + ":" + remotePort +                     " got version " + version + " expected version " + CURRENT_VERSION);            return -1;          }          dataLengthBuffer.clear();          if (authMethod == null) {            throw new IOException("Unable to read authentication method");          }          if (isSecurityEnabled && authMethod == AuthMethod.SIMPLE) {            AccessControlException ae = new AccessControlException("Authentication is required");            setupResponse(authFailedResponse, authFailedCall, Status.FATAL, null, ae.getClass().getName(), ae.getMessage());            responder.doRespond(authFailedCall);            throw ae;          }          if (!isSecurityEnabled && authMethod != AuthMethod.SIMPLE) {            doSaslReply(SaslStatus.SUCCESS, new IntWritable(SaslRpcServer.SWITCH_TO_SIMPLE_AUTH), null, null);            authMethod = AuthMethod.SIMPLE;            // client has already sent the initial Sasl message and we            // should ignore it. Both client and server should fall back            // to simple auth from now on.            skipInitialSaslHandshake = true;          }          if (authMethod != AuthMethod.SIMPLE) {            useSasl = true;          }                    rpcHeaderBuffer = null;          rpcHeaderRead = true;          continue;        }        //读取connection连接信息及真正的Data信息        if (data == null) {          dataLengthBuffer.flip();          dataLength = dataLengthBuffer.getInt();                 if (dataLength == Client.PING_CALL_ID) {//如果此RPC调用为ping则 直接返回            if(!useWrap) { //covers the !useSasl too              dataLengthBuffer.clear();              return 0;  //ping message            }          }          if (dataLength < 0) {            LOG.warn("Unexpected data length " + dataLength + "!! from " + getHostAddress());          }          data = ByteBuffer.allocate(dataLength);        }                count = channelRead(channel, data);        //当data没有空位置时 说明已经读完        if (data.remaining() == 0) {          dataLengthBuffer.clear();          data.flip();          if (skipInitialSaslHandshake) {            data = null;            skipInitialSaslHandshake = false;            continue;          }          boolean isHeaderRead = headerRead;          if (useSasl) {            saslReadAndProcess(data.array());          } else {//此处具体处理Data信息及Header信息            processOneRpc(data.array());          }          data = null;          if (!isHeaderRead) {//如果只读取了Header信息  继续循环读取Data信息            continue;          }        }        return count;      }    }

    private void processOneRpc(byte[] buf) throws IOException, InterruptedException {      if (headerRead) {//读取Data信息        processData(buf);      } else {//读取Header信息        processHeader(buf);        headerRead = true;        if (!authorizeConnection()) {          throw new AccessControlException("Connection from " + this              + " for protocol " + header.getProtocol()              + " is unauthorized for user " + user);        }      }    }

    private void processData(byte[] buf) throws  IOException, InterruptedException {      DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buf));      int id = dis.readInt();                    // try to read an id              if (LOG.isDebugEnabled())        LOG.debug(" got #" + id);      Writable param = ReflectionUtils.newInstance(paramClass, conf);//read param      param.readFields(dis);                      Call call = new Call(id, param, this);      callQueue.put(call);              // queue the call; maybe blocked here      incRpcCount();  // Increment the rpc count    }

    /// Reads the connection header following version    private void processHeader(byte[] buf) throws IOException {      DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf));      header.readFields(in);      try {        String protocolClassName = header.getProtocol();        if (protocolClassName != null) {          protocol = getProtocolClass(header.getProtocol(), conf);        }      } catch (ClassNotFoundException cnfe) {        throw new IOException("Unknown protocol: " + header.getProtocol());      }            UserGroupInformation protocolUser = header.getUgi();      if (!useSasl) {        user = protocolUser;        if (user != null) {          user.setAuthenticationMethod(AuthMethod.SIMPLE.authenticationMethod);        }      } else {        // user is authenticated        user.setAuthenticationMethod(authMethod.authenticationMethod);        //Now we check if this is a proxy user case. If the protocol user is        //different from the 'user', it is a proxy user scenario. However,         //this is not allowed if user authenticated with DIGEST.        if ((protocolUser != null)            && (!protocolUser.getUserName().equals(user.getUserName()))) {          if (authMethod == AuthMethod.DIGEST) {            // Not allowed to doAs if token authentication is used            throw new AccessControlException("Authenticated user (" + user                + ") doesn't match what the client claims to be ("                + protocolUser + ")");          } else {            // Effective user can be different from authenticated user            // for simple auth or kerberos auth            // The user is the real user. Now we create a proxy user            UserGroupInformation realUser = user;            user = UserGroupInformation.createProxyUser(protocolUser                .getUserName(), realUser);            // Now the user is a proxy user, set Authentication method Proxy.            user.setAuthenticationMethod(AuthenticationMethod.PROXY);          }        }      }    }

 具体查看链接:http://fengshenwu.com/blog/2012/11/13/hadoop-rpc_develop/

我的hadoop源码(有一些我看代码时留下的注释):https://github.com/heipacker/hadoop-1.0.3-linux

原创粉丝点击