为什么要rpc技术?



主要实现系统的分布式,将各种不同应用分布在不同的机器上,当某台机器要调用某应用时,只需要去访问远端的机器,就可以得到相对应的服务。



 



所以:远端服务器提供服务;而客户端就像调用本地类一样的使用远端服务;一个基本的rpc框架应该有的目标:



  1. 分布式;
  2. 可扩展性;


没有实际的工程经历,暂时只能想到上面的两条。



 



那要达到上述的两点,系统的基本设计:



  1. 系统分为客户端和服务端,每台机器同时可以成为客户端和服务端;
  2. 服务端通过开放端口和暴露服务接口的方式,来响应来自客户端的访问;客户端可指定服务器ip地址,开放端口和服务接口来调用服务器的服务;
  3. 客户端通过socket将要调用的服务名称和相关的参数发送给服务端,而服务端接收到客户端的服务请求后,完成对应的服务,并且再将结果写回客户端;
  4. 方便扩展性:服务端的服务以类的方式提供(也即每个服务对应一个类),但为了达到服务端和客户端对具体服务实现的解耦,将服务进行抽象,即抽象出服务接口;


 



服务端的user case:



Framework.export(端口名,服务类名);



 



而客户端的user case:



Service gotservice = Framework.refer(服务器地址,端口名,服务类名);



result = gotservice.act();



如上的用例有启发性:



  1. 调用rpc的过程,在形式上与调用本地服务无差异;
  2. 第一步:获得远端服务类的引用;第二步:调用服务类的方法;


第一步中的服务类名也很好理解:因为同一种服务也可以多种接口,可以将多种接口存放在服务类中;



 



问题1:服务器端Framework.export()所谓的暴露某个接口,所谓的暴露到底什么意思?



问题2:客户端调用的第一步在干嘛?返回的到底是什么?第二步又是在干嘛?调用一个方法到底是什么意思?



问题3:已知服务端和客户端是通过socket连接的?那么如何断开这样的链接呢?



问题4:在设计过程中是否使用到阻塞语句?如果有,如何使用NIO来改善性能?



 



对于问题1:



         所谓的暴露接口,代码中看就是如下的简单语句:



HelloService service = new HelloServiceImpl();  



RpcFramework.export(service, 1234); 



 



而export方法中主要使用反映技术,该技术中HelloService就只是作为一个object对象。具体使用过程中只有如下的代码:



Method method = service.getClass().getMethod(methodName, parameterTypes);



Object result = method.invoke(service, arguments);



上述代码需要注意其中并没有出现HelloService对象,这就意味着RpcFramework.export()中的代码不对服务类的具体实现依赖,这也就是reflect技术的优势。



 



问题2:客户端调用的第一步在干嘛?返回的到底是什么?第二步又是在干嘛?调用一个方法到底是什么意思?看看参考的客户端第一步调用:



HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 1234);    
 
 
for (int i = 0; i < Integer.MAX_VALUE; i ++) {
 
 
String hello = service.hello("World" + i); 
 
 
…
 
 
}



而此处的HelloService的定义如下:



public interface  HelloService {  
 
 
String hello(String name);  
 
 
}



客服端调用过程中,也采用解耦的技术:即HelloService也属于接口。



第一步做的事情:获得服务器端接口的一个“代理“对象;



而第二步做的事情: service.hello("World" + i); 



可以认为是对代理对象的一个操作,所有对代理对象的操作最终都会触发代理对象中的invoke方法,而invoke函数做的事情:将被调用的函数名,参数列表或者参数等信息发送到服务器,并且接收来自服务器端的结果。



注:此处发现自己对动态代理的理解还不够;感觉使用不纯熟;



问题3:已知服务端和客户端是通过socket连接的?那么如何断开这样的链接呢?



这个不是问题,客户端每次的invoke就是一次发送数据和接收处理后结果的过程,一次调用的结束,自然就会断开连接。



 



问题4:在设计过程中是否使用到阻塞语句?如果有,如何使用NIO来改善性能?



服务端的server.accept()属于阻塞语句,如何使用非阻塞技术来改进。



 



按照上述理解的原理:自己来写个简单的rpc框架。