Hadoop源码分析8: IPC流程(3)客户端的clients、connections、calls复用

1. RPCClientCache 中的 clients

publicclass  RPCClientCache {


   private  Map<SocketFactory,Client>  clients = new  HashMap<SocketFactory,Client>();
   
    synchronizedClient  getClient(Configuration conf,
      SocketFactory factory) {
     // Construct & cacheclient.  The configuration is only used fortimeout,
     // and Clients haveconnection pools.  So we can either (a) losesome
     // connection pooling andleak sockets, or (b) use the same timeout for all
     // configurations. Since the IPC is usually intended globally,not
     // per-job, we choose(a).
     Client client=  clients.get(factory);
     if (client == null) {
       client =new Client(ObjectWritable.class, conf, factory);
       clients.put(factory,client);
     } else {
      client.incCount();
     }
     return client;
   }

      
   void  stopClient(Clientclient) {
     synchronized (this) {
      client.decCount();
       if(client.isZeroReference()) {
         clients.remove(client.getSocketFactory());
       }
     }
     if (client.isZeroReference()){
      client.stop();
     }
   }
}

以上方法在下列代码中调用:

publicclass  RPCInvoker implements  InvocationHandler{

    privateClientConnectionId remoteId;
    private Clientclient;
    private boolean isClosed= false;

   public  RPCInvoker(Class<? extendsVersionedProtocol> protocol,
       InetSocketAddress address, UserGroupInformationticket,
       Configuration conf, SocketFactory factory,
       int rpcTimeout) throws IOException {
     this.remoteId = ClientConnectionId.getConnectionId(address,protocol,
         ticket, rpcTimeout,conf);
     this.client = RPC.CLIENTS. getClient(conf, factory);
    }  

  
    synchronizedvoid  close() {
      if(!isClosed) {
       isClosed = true;
        RPC.CLIENTS.stopClient(client);
     }
   } 
}

publicclass  RPC {

  public staticRPCClientCache  CLIENTS=newRPCClientCache();

   //for unit testing only
  staticClient  getClient(Configuration conf){
  return  CLIENTS.getClient(conf);
 } 

 
  public staticObject[]  call(Method method, Object[][]params,
                         InetSocketAddress[]addrs, 
                         UserGroupInformation ticket,Configuration conf)
   throws IOException, InterruptedException {

   RPCInvocation[] invocations = newRPCInvocation[params.length];
   for (int i = 0; i < params.length; i++)
     invocations[i] = newRPCInvocation(method, params[i]);
   Client client=  CLIENTS.getClient(conf);
   try {
   Writable[] wrappedValues= 
     client.call(invocations,addrs, method.getDeclaringClass(), ticket, conf);
   
   if (method.getReturnType() == Void.TYPE) {
     return null;
   }

   Object[] values =
    (Object[])Array.newInstance(method.getReturnType(),wrappedValues.length);
   for (int i = 0; i < values.length; i++)
     if (wrappedValues[i] !=null)
       values[i]= ((ObjectWritable)wrappedValues[i]).get();
   
   return values;
   } finally {
     CLIENTS.stopClient(client);
   }
  }

 
  public staticVersionedProtocol  getProxy(
     Class<? extendsVersionedProtocol> protocol,
     long clientVersion,InetSocketAddress addr, UserGroupInformation ticket,
     Configuration conf,SocketFactory factory, int rpcTimeout) throws IOException {

   if (UserGroupInformation.isSecurityEnabled()){
    SaslRpcServer.init(conf);
   }
   VersionedProtocol proxy =
      (VersionedProtocol) Proxy.newProxyInstance(
          protocol.getClassLoader(),new Class[] { protocol },
           newRPCInvoker(protocol, addr, ticket, conf, factory,rpcTimeout));
   long serverVersion =proxy.getProtocolVersion(protocol.getName(), 
                                         clientVersion);
   if (serverVersion == clientVersion) {
     return proxy;
   } else {
     throw newRPCVersionMismatch(protocol.getName(),clientVersion, 
                          serverVersion);
   }
  }

}
2. Client 的connections

publicclass  Client {
  
  public  HashtableClientConnectionIdClientConnection>  connections =new Hashtable<ClientConnectionId, ClientConnection>();

  public void  stop() { 
 ..............
   // wake up all connections
   synchronized ( connections) {
     for (ClientConnection conn:  connections.values()) {
      conn.interrupt();
     }
   }
   
   // wait until all connections are closed
   while (! connections.isEmpty()) {
     try {
      Thread.sleep(100);
     } catch (InterruptedExceptione) {
     }
   }
  ....................
  }

    //for unit testing only
 Set<ClientConnectionId>  getConnectionIds(){
   synchronized ( connections) {
    return  connections.keySet();
   }
  }

    
  privateClientConnection  getConnection(ClientConnectionIdremoteId,
                             ClientCall call)
                             throws IOException,InterruptedException {
   if (!running.get()) {
     // the client isstopped
     throw new IOException("Theclient is stopped");
   }
   ClientConnection connection;
  
   do {
     synchronized( connections) {
       connection=  connections.get(remoteId);
       if(connection == null) {
        connection = newClientConnection(remoteId,this);
         connections.put(remoteId,connection);
       }
     }
   } while (!connection.addCall(call));
   
   //we don't invoke the method below inside"synchronized (connections)"
   //block above. The reason for that is if theserver happens to be slow,
   //it will take longer to establish a connectionand that will slow the
   //entire system down.
   connection.setupIOstreams();
   return connection;
  }
}

publicclass  ClientConnection extends  Thread {
  
  
   private synchronizedvoid  close() {
     if(!shouldCloseConnection.get()) {
       return;
     }

     // release theresources
     // first thing to do;take theconnection out of the connection list
     synchronized(client. connections) {
       if( client.connections.get(remoteId) == this){
       client.connections.remove(remoteId);
       }
     }
  。。。。。。
  } 
}


3. ClientConnection 的calls

publicclass  ClientConnection extends  Thread {

   private  Hashtable<Integer,ClientCall> calls = new Hashtable<Integer,ClientCall>();
   
   public synchronizedboolean  addCall(ClientCall call) {
     if(shouldCloseConnection.get())
       returnfalse;
     calls.put(call.id,call);
     notify();
     return true;
   }
  
      
   private synchronizedboolean  waitForWork() {
     if ( calls.isEmpty()&& !shouldCloseConnection.get() && client.running.get()) {
       longtimeout = maxIdleTime-
           (System.currentTimeMillis()-lastActivity.get());
       if(timeout>0) {
        try {
          wait(timeout);
        } catch (InterruptedException e) {}
       }
     }
     
     if (! calls.isEmpty()&& !shouldCloseConnection.get() &&client.running.get()) {
       returntrue;
     } else if(shouldCloseConnection.get()) {
       returnfalse;
     } else if( calls.isEmpty()) { // idle connection closed orstopped
      markClosed(null);
       returnfalse;
     } else { // get stopped butthere are still pending requests 
      markClosed((IOException)new IOException().initCause(
          newInterruptedException()));
       returnfalse;
     }
   }

    privatevoid  receiveResponse() {
     if(shouldCloseConnection.get()) {
      return;
     }
     touch();
     
     try {
       int id =in.readInt();                 // try to read an id      

       ClientCallcall =  calls.get(id);

       int state= in.readInt();     // read callstatus
       if (state== Status.SUCCESS.state) {
        Writable value =ReflectionUtils.newInstance(client.valueClass, client.conf);
        value.readFields(in);              // read value
        call.setValue(value);
         calls.remove(id);
       } else if(state == Status.ERROR.state) {
        call.setException(newRemoteException(WritableUtils.readString(in),
                                       WritableUtils.readString(in)));
         calls.remove(id);
       } else if(state == Status.FATAL.state) {
        // Close the connection
        markClosed(newRemoteException(WritableUtils.readString(in), 
                                 WritableUtils.readString(in)));
       }
     } catch (IOException e){
      markClosed(e);
     }
   } 
  
    
   private synchronizedvoid  close() {
     if(!shouldCloseConnection.get()) {
       return;
     }

     // release theresources
     // first thing to do;take theconnection out of the connection list
     synchronized(client.connections) {
       if(client.connections.get(remoteId) == this) {
      client.connections.remove(remoteId);
       }
     }

     // close the streams andtherefore the socket
    IOUtils.closeStream(out);
    IOUtils.closeStream(in);
     disposeSasl();

     // clean up all calls
     if (closeException == null){
       if(! calls.isEmpty()) {
       

        // clean up calls anyway
        closeException = new IOException("Unexpectedclosed connection");
        cleanupCalls();
       }
     } else {
       // log theinfo
      

       // cleanupcalls
      cleanupCalls();
     } 
   }
   

    
   privatevoid  cleanupCalls() {
     Iterator<Entry<Integer,ClientCall>> itor=  calls.entrySet().iterator() ;
     while (itor.hasNext()){
       ClientCallc = itor.next().getValue(); 
      c.setException(closeException); // local exception
      itor.remove();        
     }
   }
  
 
}


4.并发执行以下代码

public class MyClient {
    public static void main(String[] args) throws Exception {

      final InetSocketAddress addr =new InetSocketAddress("localhost",
MyServer.IPC_PORT);
      final Query query = (Query)RPC.getProxy(Query.class, MyServer.IPC_VER,
addr, new Configuration());

       new Thread() {

          @Override
          public void run() {
             FileStatusfileStatus1 = query.getFileStatus("/tmp/testIPC");
             System.out.println(fileStatus1);

              FileStatusfileStatus2 = query.getFileStatus("/tmp/testIPC2");
              System.out.println(fileStatus2);

           }

       } .start();

        new Thread() {

         @Override
          public void run() {
              CPUStatus cpuStatus1 =query.getCPUStatus("Intel");
             System.out.println(cpuStatus1);

              CPUStatus cpuStatus2 =query.getCPUStatus("AMD");
             System.out.println(cpuStatus2);
          }

       } .start();

        new Thread() {

        @Override
         public void run() {

         try {
               Queryquery2 = (Query) RPC.getProxy(Query.class,
              MyServer.IPC_VER, addr, newConfiguration());

               FileStatusfileStatus1 = query2.getFileStatus("/tmp/testIPC");
              System.out.println(fileStatus1);

               FileStatusfileStatus2 = query2.getFileStatus("/tmp/testIPC2");
              System.out.println(fileStatus2);
              RPC.stopProxy(query2);
           } catch(IOException e) {
               e.printStackTrace();
           }

       }

     } .start();

      RPC.stopProxy(query);
  } 
}


以上三个线程可以共用同一个  Client对象、ClientConnection线程 、ClientConnectionId对象,将ClientCall放在同一个calls中

转载于:https://www.cnblogs.com/leeeee/p/7276530.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值