RPC远程过程调用框架实现

本文详细描述了使用Java实现的RPC服务器,通过配置文件管理方法映射,客户端通过Socket进行远程调用。同时介绍了客户端如何模拟调用HelloWorld和Call接口。强调了同步调用和并发优化的重要性。
摘要由CSDN通过智能技术生成

RPCServer

这是一个RPC(远程过程调用)服务器的实现,主要功能是根据客户端发送的方法名和参数,调用对应的服务端实现,并将结果返回给客户端。

  • 导入相关的类和接口:

import com.rpc.server.lib.RpcInterface;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
  • 定义Server类并实现main方法:

public class Server {
    public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
    }
}
  • 初始化方法映射表 methodMap,用于存储方法名和对应的实现类实例:

HashMap<String, RpcInterface> methodMap = new HashMap<>();
  • 通过读取配置文件 methods.txt,解析其中的方法名和类名,并通过反射实例化类对象,将方法名和实例的映射存储到 methodMap 中:

File file = new File("C:\\Users\\18384\\IdeaProjects\\_sjjg_\\src\\RPC\\RPCServer\\config\\methods.txt");
        FileReader fileReader = new FileReader(file);
        BufferedReader br = new BufferedReader(fileReader);
        String listStr = null;
        while ((listStr = br.readLine()) != null) {
            System.out.println(listStr);
            // 解析单行数据 方法名 类名
            String[] methodMsg = listStr.split(" ");
            String methodName = methodMsg[0];
            String className = methodMsg[1];
            // 反射获取类对象1
            Class<?> aClass = Class.forName(className);
            // 加载类实例
            Object object = aClass.newInstance();// 实例化
            // 存储方法名-类实例
            methodMap.put(methodName, (RpcInterface) object);
            //System.out.println(listStr);
        }
  • 启动服务端Socket,监听端口 12345

ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Server started");
  • 进入无限循环,等待客户端连接:

while (true) {
}
  • 使用 try-with-resources 语句创建 Socket 连接,并获取输入输出流:

try (Socket socket = serverSocket.accept();
     ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
     ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream())) {
}
  • 从客户端读取方法名,并检查是否存在于 methodMap 中:

String methodName = input.readUTF();
if (methodMap.containsKey(methodName)) {
}
  • 如果存在,获取对应的实例对象,并通过反射获取该类的所有方法:

// 根据方法名 获取实例
RpcInterface rpcInterface = methodMap.get(methodName);
// 反射类
Class rpcClass = rpcInterface.getClass();
// 加载方法
Method[] methods = rpcClass.getMethods();
  • 从客户端读取参数,并调用方法:

// 读第二句话 参数
String name = input.readUTF();
// 调用方法 获取返回结果
Object obj = methods[0].invoke(rpcInterface, name);
  • 将结果发送给客户端:

// 发送给调用者结果
output.writeUTF(obj.toString());
output.flush();
  • 处理异常:
catch (IOException e) {
  e.printStackTrace();
} catch (InvocationTargetException e) {
  throw new RuntimeException(e);
} catch (IllegalAccessException e) {
  throw new RuntimeException(e);
}

这段代码实现了一个简单的RPC服务器,通过配置文件指定可调用的方法,并在客户端请求时动态调用相应的方法。需要注意的是,这里只处理了一种方法,即调用类的第一个方法,实际的应用场景可能需要更复杂的处理逻辑。同时,由于没有处理并发,可能在多客户端同时连接时存在问题。

RPClient

这是一个RPC客户端的实现,主要功能是模拟向服务器发起远程方法调用。

  • 定义Client类并实现main方法:

public class Client {
    public static void main(String[] args) {
    }
}
  • 使用一个循环模拟多次客户端调用:

for (int i = 0; i < 50; i++) {
}
  • 在每次循环中,通过 Thread.sleep(1000) 模拟间隔1秒的延迟:

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}
  • 创建一个 HelloWorldImp 实例,并调用其 sayHello 方法,传入参数 "AJava":

new HelloWorldImp().sayHello("AJava");
  • 创建一个 CallImp 实例,并调用其 call 方法,传入参数 "张伟":

String res = new CallImp().call("张伟");
  • 在每次循环中,都模拟向服务器发起一次 HelloWorldImp 的调用和一次 CallImp 的调用

这段代码主要用于模拟客户端向服务器发起RPC调用。需要注意的是,该代码中创建了多个实例对象,而实际使用中可能会考虑复用连接或者采用连接池的方式,以提高效率。此外,对于 HelloWorldImpCallImp ,这些实现类应该是RPC服务器端提供的具体服务实现类。在真实的RPC场景中,通常会使用代理对象来进行远程调用,而不是直接调用服务实现类的方法。

HelloWorldImp

这是一个HelloWorld接口的客户端实现HelloWorldImp,用于在客户端发起对RPC服务器上HelloWorld接口的sayHello方法的调用。

  • 导入相关的类和接口:

import com.rpc.clinet.lib.HelloWorld;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
  • 定义HelloWorldImp类并实现HelloWorld接口:

public class HelloWorldImp implements HelloWorld {
}
  • 实现HelloWorld接口的sayHello方法:

public String sayHello(String name) {
}
  • sayHello方法中,创建一个Socket对象,连接到RPC服务器的地址(localhost)和端口(12345):

String response = null;
try (Socket socket = new Socket("localhost", 12345);
     ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
     ObjectInputStream input = new ObjectInputStream(socket.getInputStream())) {
}
  • 通过ObjectOutputStream向服务器发送两个字符串,第一个字符串是方法名 "sayHello",第二个字符串是参数 name

output.writeUTF("sayHello");
output.writeUTF(name);
output.flush();
  • 通过ObjectInputStream从服务器接收返回结果:

response = input.readUTF();
  • 打印服务器返回的结果:

System.out.println(response);
  • 处理异常:

  catch (IOException e) {
    e.printStackTrace();
}
  • 返回服务器返回的结果:

return response;

这段代码的作用是通过Socket与RPC服务器建立连接,将方法名和参数发送给服务器,然后接收并返回服务器的处理结果。需要注意的是,这里的实现是简单的同步调用方式,即客户端在调用sayHello方法时会阻塞等待服务器的响应。在实际应用中,可能会使用异步调用、回调等方式来提高系统的并发性能。

CallImp

这是一个Call接口的客户端实现CallImp,用于在客户端发起对RPC服务器上Call接口的call方法的调用。

  • 导入相关的类和接口:

import com.rpc.clinet.lib.Call;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
  • 定义CallImp类并实现Call接口:

public class CallImp implements Call {
}
  • 实现Call接口的call方法:

public String call(String name) {
}
  • call方法中,创建一个Socket对象,连接到RPC服务器的地址(localhost)和端口(12345):

tring response = null;
try (Socket socket = new Socket("localhost", 12345);
     ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
     ObjectInputStream input = new ObjectInputStream(socket.getInputStream())) {
}
  • 通过ObjectOutputStream向服务器发送两个字符串,第一个字符串是方法名 "call",第二个字符串是参数 name

output.writeUTF("call");
output.writeUTF(name);
output.flush();
  • 通过ObjectInputStream从服务器接收返回结果:

 response = input.readUTF();
  • 打印服务器返回的结果:

System.out.println(response);
  • 处理异常:

  catch (IOException e) {
    e.printStackTrace();
}
  • 返回服务器返回的结果:

return response;

这段代码的作用是通过Socket与RPC服务器建立连接,将方法名和参数发送给服务器,然后接收并返回服务器的处理结果。同样地,这里的实现是简单的同步调用方式。在实际应用中,可能会使用异步调用、回调等方式来提高系统的并发性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值