1.       客户端RPC调用过程
 
图1 使用java动态代理
2.       客户端调用动态代理过程
图2 客户端调用RPC动态代理
说明:
1)       客户端程序调用getProxy()方法,然后Proxy.newProxyInstance()创建代理。
2)       在构造函数里面使用CLIENTS.getClient(conf, factory)获取客户端
3)       在InvocationHandler接口的实现方法invoke()
4)       在invoke()方法里面,就是调用具体的方法,我们创建new Invocation()对象,用于封装客户端调用的方法和参数
5)       然后调用client.call(param,addr)函数,这是创建call的最关键的。在Client.call里面:
Call call = new Call(param);//创建CALL
Connection connection = getConnection(addr, protocol, ticket, call);//创建链接
connection.sendParam(call); //发送参数
3.       客户端响应结果
值得注意的是,我们的响应有两种机制,因为我们创建Call的时候,也是有两种机制的,一种就是单独的一个call,而另外一种就是多个call一起创建
1)       单独的call
源码:
Call call = new Call(param);//创建CALL
Connection connection = getConnection(addr, protocol, ticket, call);//创建链接
connection.sendParam(call); //发送参数
一个call的创建之后,被加入connection中,然后在connection线程中等待response响应结果处理过程如下:
图3 单个call处理结果
说明:接收每一个call的都是在connectin线程中处理的,在receiveResponse()函数中处理结果,然后通过call对象中的setValue()方法将结果放入Call对象中去,然后再调用callComplate方法表示结果已经接收到,通过notify函数告知caller,已经完成。
2)       多call创建与响应
说明:
多call的创建比单个的call要复杂很多,首先,我们会调用call方法的重载函数,是专门用来创建多个call的方法。
private class ParallelCall extends Call {}//该类专门用来创建多个call,是继承call(用于创建单个call)
在创建ParallelCall对象的同时,我们还需要创建两外一个对象private static class ParallelResults {},该类专门用来存放各个call的一系列数据。
源码分析:
ParallelResults results = new ParallelResults(params.length);//用于存放各个call的数据
synchronized (results) {
for (int i = 0; i < params.length; i++) {
ParallelCall call = new ParallelCall(params[i], results, i);//创建很多的用于duocall的对象
     try {
          Connection connection =
          getConnection(addresses[i], protocol, ticket, call);
          connection.sendParam(call);             // send each parameter
        } catch (IOException e) {
          // log errors
          LOG.info("Calling "+addresses[i]+" caught: " +
                   e.getMessage(),e);
          results.size--;                         // wait for one fewer result
        }
      }
 while (results.count != results.size) {
   try {
       results.wait();                    // wait for all results
      } catch (InterruptedException e) {}
    }
 return results.values;//最后返回整个结果
    }
这里,有一点特别需要注意,各个call可能到来的response时间是不一样的。在connection线程中,检测到一个value值,就马上调用setvale()函数,然后找到ParallelCall对象的callComplete()方法,然后该callComplete()方法再次调用results.callComplete(this);
其中results是class ParallelResults {}实例对象,用于存放各个call的响应数据。按照call中的index参数,一次将结果放入列表中。如果数据已经存满的话,则通知caller,告诉它已经全部获得了数据。