RPC概述
RPC(Remote Proceduce Call 遠程過程調(diào)用) 一般用來實現(xiàn)部署在不同機器上的系統(tǒng)之間的方法調(diào)用,使程序能夠像訪問本地系統(tǒng)資源一樣轮蜕,通過網(wǎng)絡(luò)傳輸過去訪問遠端系統(tǒng)資源昨悼。
RPC 調(diào)用過程
- Client 客戶端調(diào)用方法實現(xiàn),負責發(fā)起RPC調(diào)用跃洛。
- ClientStub/SereverStub 可以看作一個代理對象率触,屏蔽RPC調(diào)用過程中復雜的網(wǎng)絡(luò)處理邏輯,使RPC透明化汇竭,使得調(diào)用遠程方法想調(diào)用本地方法一樣葱蝗。
- Server 服務(wù)端提供遠程服務(wù)穴张。
Stub 主要作用
- 序列化:負責數(shù)據(jù)的序列化發(fā)序列化。
- 網(wǎng)絡(luò)傳輸:數(shù)據(jù)發(fā)送與接收两曼。
注:ServerStub又叫Skeleton皂甘。
RPC 實現(xiàn)
1. 遠程服務(wù)接口
public interface IHello {
public String sayHello(String info);
}
2. 遠程服務(wù)接口實現(xiàn)類(Server)
public class HelloService implements IHello {
public String sayHello(String info) {
String result = "hello : " + info;
System.out.println(result);
return result;
}
}
提供服務(wù)實現(xiàn)的類。
3.服務(wù)器代理實現(xiàn)(Skeleton)
public class RpcProxyServer {
private IHello hello = new HelloService();
public void publisherServer(int port) {
try (ServerSocket ss = new ServerSocket(port)) {
while (true) {
try (Socket socket = ss.accept()) {
try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
String method = ois.readUTF();
Object[] objs = (Object[]) ois.readObject();
Class<?>[] types = new Class[objs.length];
for (int i = 0; i < types.length; i++) {
types[i] = objs[i].getClass();
}
Method m = HelloService.class.getMethod(method, types);
Object obj = m.invoke(hello, objs);
try (ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
oos.writeObject(obj);
oos.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 構(gòu)建一個ServerSocket服務(wù)監(jiān)聽來自客戶端的請求悼凑。
- 接收請求的數(shù)據(jù)偿枕。(方法名和參數(shù))
- 根據(jù)請求的數(shù)據(jù)(方法名和參數(shù)),使用反射調(diào)用相應(yīng)的服務(wù)户辫。
- 輸出服務(wù)的響應(yīng)數(shù)據(jù)渐夸。
4. RPC 客戶端代理實現(xiàn)(ClientStub)
public class RpcProxyClient<T> {
public T proxyClient(Class<T> clazz) {
return (T) clazz.cast(Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (Socket socket = new Socket("localhost", 8000)) {
try (ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
oos.writeUTF(method.getName());
oos.writeObject(args);
oos.flush();
try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
return ois.readObject();
}
}
}
}
}));
}
}
- 構(gòu)建一個Socket,連接遠程服務(wù)寸莫。
- 向遠程服務(wù)發(fā)送數(shù)據(jù)捺萌。(方法名和方法參數(shù))
- 接收遠程服務(wù)響應(yīng)的數(shù)據(jù)。
5.服務(wù)端發(fā)布服務(wù)
public class RpcServer {
//發(fā)布服務(wù)
public static void main(String[] args) {
RpcProxyServer server = new RpcProxyServer();
server.publisherServer(8000);
}
}
6.客戶端調(diào)用(Client)
public class RpcClient {
// 調(diào)用服務(wù)
public static void main(String[] args) {
RpcProxyClient<HelloService> rpcClient = new RpcProxyClient<>();
IHello hello = rpcClient.proxyClient(HelloService.class);
String s = hello.sayHello("dd");
System.out.println(s);
}
}
想了解更多精彩內(nèi)容請關(guān)注我的公眾號