一. RPC調用過程
- 服務客戶端(Client)調用以本地調用方式調用服務
- Client stub接收到調用後負責將方法、參數等組裝成能夠進行網路傳輸的消息,并將消息發送到服務伺服端(物件序列化)
- Server stub收到消息後進行解碼(物件反序列化)
- Server stub根據解碼結果調用本地的服務
- 本地服務執行並將結果返回給Server stub
- Server stub將返回結果打包成消息并發送至服務客戶端
- Client stub接收到消息,並進行解碼
- 服務客戶端得到最終結果
二. 範例代碼
基於Java的Socket API實現一個簡單的RPC調用範例。範例中包括服務的介面、介面的實作、服務的伺服端和服務的客戶端。
服務介面 SayHelloService.java
public interface SayHelloService { public String sayHello(String msg); }服務介面實作 SayHelloServiceImpl.java
public class SayHelloServiceImpl implements SayHelloService { @Override public String sayHello(String msg) { if("hello".equals(msg)) { return "hello client"; } else { return "bye bye"; } } }服務伺服端 Provider.java
import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Method; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; public class Provider { public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(1234); Map services = new HashMap(); services.put(SayHelloService.class, new SayHelloServiceImpl()); while(true){ System.out.println("服務伺服端啟動,等待客戶端調用…………"); Socket socket = serverSocket.accept(); //收到消息後進行解碼 ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream()); String interfaceName = objectInputStream.readUTF(); System.out.println("interfaceName:"+interfaceName); String methodName = objectInputStream.readUTF(); System.out.println("methodName:"+methodName); Class[] paramterTypes = (Class[])objectInputStream.readObject(); Object[] argments = (Object[])objectInputStream.readObject(); System.out.println("客戶端調用服務端接口"+interfaceName+"的"+ methodName+"方法"); //根據解碼結果調用本地的服務 Class serviceClass = Class.forName(interfaceName); Object serivce = services.get(serviceClass); Method method = serviceClass.getMethod(methodName, paramterTypes); Object result = method.invoke(serivce, argments); //服務伺服端發送結果給服務客戶端 ObjectOutputStream stream = new ObjectOutputStream(socket.getOutputStream()); stream.writeObject(result); System.out.println("服務伺服端返回結果為"+result); } } }服務客戶端 Consumer.java
import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Method; import java.net.Socket; public class Consumer { public static void main(String[] args) throws Exception { String interfaceName = SayHelloService.class.getName(); Method method = SayHelloService.class.getMethod("sayHello", java.lang.String.class); Object[] argments = {"hello"}; Socket socket = new Socket("127.0.0.1", 1234); ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream()); outputStream.writeUTF(interfaceName); outputStream.writeUTF(method.getName()); outputStream.writeObject(method.getParameterTypes()); outputStream.writeObject(argments); System.out.println("發送信息到服務伺服端,發送的信息為:"+argments[0]); ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream()); Object object = inputStream.readObject(); System.out.println("服務伺服端返回的結果為" + object); } }程式碼放在Github卜,請到(https://github.com/vvtitana/RPCDemo)下載。
鏈結到這頁!
