RPC
RPC
Remote Procedure Call,远程过程调用。比如 Dubbo,Java 自带的是 RMI 框架。
调用远程计算机上的服务,就像调用本地服务一样。需要服务注册中心。
制作 RPC 框架
- 服务端定义接口和服务实现类并且注册服务
- 客户端查询出服务
- 客户端使用动态代理调用服务
- 客户端代理把调用对象、方法、参数序列化成数据
- 客户端与服务端通过 Socket 通讯传输数据
- 服务端反序列化数据成对象、方法、参数
- 服务端代理拿到这些对象和参数后通过反射的机制调用服务的实例
服务
public interface OrderInterface {
String order(String id);
}
public class OrderImpl implements OrderInterface {
@Override
public String order(String id) {
return "调用成功:" + id;
}
}
客户端
@Log4j
public class RPCClientFrame {
public static <T> T getRemoteProxyObj(final Class<T> serviceInterface) {
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8888);
return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(),
new Class<?>[]{serviceInterface},
new DynProxy(serviceInterface, address));
}
private static class DynProxy implements InvocationHandler {
private final Class<?> serviceInterface;
private final InetSocketAddress address;
public DynProxy(Class<?> serviceInterface, InetSocketAddress address) {
this.serviceInterface = serviceInterface;
this.address = address;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (Socket socket = new Socket()) {
socket.connect(address);
try (ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream())) {
outputStream.writeUTF(serviceInterface.getName());
outputStream.writeUTF(method.getName());
outputStream.writeObject(method.getParameterTypes());
outputStream.writeObject(args);
outputStream.flush();
log.info("远程调用已发送");
return inputStream.readObject();
}
}
}
}
}
服务端(包括注册中心)
@Log4j
public class RegisterCenter {
private static final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
private static final Map<String, Class<?>> serviceRegistry = new HashMap<>();
private static boolean isRunning = false;
@Setter
private int port;
public RegisterCenter(int port) {
this.port = port;
}
public void register(@NotNull Class<?> serviceInterface, Class<?> impl) {
serviceRegistry.put(serviceInterface.getName(), impl);
}
public void start() {
try (ServerSocket socket = new ServerSocket()) {
socket.bind(new InetSocketAddress(port));
log.info("注册中心启动完毕");
isRunning = true;
while (!Thread.interrupted() && isRunning) {
executor.execute(new ServiceTask(socket.accept()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop() {
isRunning = false;
}
private static class ServiceTask implements Runnable {
private final Socket client;
public ServiceTask(Socket client) {
this.client = client;
}
@Override
public void run() {
try (ObjectInputStream inputStream = new ObjectInputStream(client.getInputStream());
ObjectOutputStream outputStream = new ObjectOutputStream(client.getOutputStream())) {
String serviceName = inputStream.readUTF();
String methodName = inputStream.readUTF();
Class<?>[] paramTypes = (Class<?>[]) inputStream.readObject();
Object[] arguments = (Object[]) inputStream.readObject();
Class<?> serviceClass = serviceRegistry.get(serviceName);
Method method = serviceClass.getMethod(methodName, paramTypes);
Object result = method.invoke(serviceClass.getConstructor().newInstance(), arguments);
outputStream.writeObject(result);
client.close();
} catch (IOException | ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
服务端及注册中心启动
RegisterCenter registerCenter = new RegisterCenter(8888);
registerCenter.register(OrderInterface.class, OrderImpl.class);
registerCenter.start();
客户端远程调用
OrderInterface order = RPCClientFrame.getRemoteProxyObj(OrderInterface.class);
log.info(order.order("123"));
相关文章:
RMI

浙公网安备 33010602011771号