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