RPC 的全称是 Remote Procedure Call 是一种进程间通信方式。 它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。
RPC的简单实现原理
服务端暴露服务,绑定一个端口,利用Socket轮询,等待接受客户端的请求。客户端引用服务,利用动态代理,隐藏掉每个接口方法的实际调用。客户端将方法名、参数类型、方法所需参数传给服务端,服务端接受到客户端传过来的方法名、参数类型、方法所需参数之后,利用反射,执行具体的接口方法,然后将执行结果返回给客户端
- 定义接口:
package com.xyy.rpc.service;
public interface HelloService {
public String sayHello(String name);
}
2.接口实现
package com.xyy.rpc.service.impl;
import com.xyy.rpc.service.HelloService;
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "hello " + name;
}
}
3、rpc登场
package com.xyy.rpc.server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RpcServer {
private ExecutorService threadPool;
private static final int DEFAULT_THREAD_NUM = 10;
public RpcServer(){
threadPool = Executors.newFixedThreadPool(DEFAULT_THREAD_NUM);
}
public void register(Object service, int port){
try {
System.out.println("server starts...");
ServerSocket server = new ServerSocket(port);
Socket socket = null;
while((socket = server.accept()) != null){
System.out.println("client connected...");
threadPool.execute(new Processor(socket, service));
}
} catch (IOException e) {
e.printStackTrace();
}
}
class Processor implements Runnable{
Socket socket;
Object service;
public Processor(Socket socket, Object service){
this.socket = socket;
this.service = service;
}
public void process(){
}
@Override
public void run() {
try {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
String methodName = in.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) in.readObject();
Object[] parameters = (Object[]) in.readObject();
Method method = service.getClass().getMethod(methodName, parameterTypes);
try {
Object result = method.invoke(service, parameters);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(result);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
}
}
4、发布服务
package com.xyy.rpc.main;
import com.xyy.rpc.server.RpcServer;
import com.xyy.rpc.service.HelloService;
import com.xyy.rpc.service.impl.HelloServiceImpl;
public class ServerMain {
public static void main(String[] args) {
HelloService helloService = new HelloServiceImpl();
RpcServer server = new RpcServer();
server.register(service, port);(helloService, 50001);
}
}
5、客户端调用
package com.xyy.rpc.client;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.xyy.rpc.service.HelloService;
public class RpcClient {
public static void main(String args[]){
HelloService helloService = getClient(HelloService.class, "127.0.0.1", 50001);
System.out.println(helloService.sayHello("liyao1"));
}
@SuppressWarnings("unchecked")
public static <T> T getClient(Class<T> clazz, String ip, int port){
return (T) Proxy.newProxyInstance(RpcClient.class.getClassLoader(), new Class<?>[]{clazz}, new InvocationHandler() {
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
Socket socket = new Socket(ip, port);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeUTF(arg1.getName());
out.writeObject(arg1.getParameterTypes());
out.writeObject(arg2);
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
return in.readObject();
}
});
}
}
参考:https://www.jianshu.com/p/bb9beca7f7bc