RPC 实现技术主要是通过数据的序列化跟反序列话实现的,通过序列化将数据编程二进制流,将数据传送到指定的位置后需要将数据进行反序列化,反序列化
后得到数据。所以这个DEMO主要实现技术是通过SOCKET-ServerSock + ObjectOutputStream实现PRC功能。这里主要有两个技术点,1是使用TCP连接保证连接的
稳定,另外一个是序列化的效率问题。目前流行的两个序列化工具是 Google的Protocal Buffers 效率高,代码侵入性较强,Hessian效率稍低,但是其对各
种编程语言有着良好的支持。且稳定性好。这里的Socket是阻塞式的,可以使用类似于Netty这种非阻塞式的框架用来实现RPC的调用。调用流程如下:1、
消费者通过获取SOcket连接,获取数据传输的线路,然后将数据序列化到服务提供者,服务提供者拿到数据后进行对应的服务调用,然后通过Socket进行数据
的返回。这样就能实现JAVA的RPC
public class Consumer {//消费者
public static void main(String[] args) throws Exception{
String interfaceName = UserService.class.getName();
//需要远程执行的方法
Method method = UserService.class.getMethod("getUserName", java.lang.String.class);
//RPC参数
Object[] arguments = {"441622"};
//Socket数据通道
Socket socket = new Socket("172.29.224.87",1234);
//序列化RPC调用参数
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
output.writeUTF(interfaceName);
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(arguments);
//获取RPC返回结果
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
Object result = input.readObject();
System.out.println((String)result);
}
}
public class Provider {//服务提供者
private static Map<String, Object> servicesPool = new HashMap<>();
public static void main(String[] args) throws Exception{
init();
System.out.println("RPC Server 启动");
@SuppressWarnings("resource")
ServerSocket server = new ServerSocket(1234);
while (true) {
try {
//开启SocketServer用于传输数据
Socket socket = server.accept();
//反序列化RPC调用数据包括,接口名称,方法名,参数类型,参数i
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
//接口名称
String interfacename = input.readUTF();
//方法名
String methodName = input.readUTF();
//参数类型
Class<?>[] paramterType = (Class<?>[])input.readObject();
//参数
Object[] params = (Object[]) input.readObject();
//将类加载到内存中
Class<?> serviceInterfaceclass = Class.forName(interfacename);
//获取对象,线程安全的方法所以可以预先加载类,可以节省每次创建对内存处理器的消耗
Object service = servicesPool.get(interfacename);
//根据方法名跟参数类型确认一个方法
Method method = serviceInterfaceclass.getMethod(methodName, paramterType);
//调用方法
Object result = method.invoke(service, params);
//根据socket通道返回RPC调用数据
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
output.writeObject(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void init(){
servicesPool.put("org.rpc.UserService", new UserServiceImpl());
}
}
public interface UserService {//服务接口
/**
* 获取身份证获取用户姓名
* @param helloArg 参数
* @return
*/
public String getUserName(String idCard);
}
public class UserServiceImpl implements UserService{//服务实现
Map<String, String> userPool = new HashMap<String, String>();
public UserServiceImpl() {
userPool.put("441621", "小张");
userPool.put("441622", "小王");
userPool.put("441623", "小刘");
}
@Override
public String getUserName(String idCard) {
if(idCard == null){
return "参数异常";
}
String userName = userPool.get(idCard);
if(userName != null){
return userName;
}else{
return "用户不存在";
}
}
}