一。什么是RPC
RPC(Remote Procedure Call Protocol)远程过程调用协议
RPC是协议:既然是协议就只是一套规范,那么就需要有人遵循这套规范来进行实现。
目前典型的RPC实现包括:Dubbo、Thrift、GRPC、Hetty等
二。RPC由四部分组成
通信模型(网络通信框架)
服务定位:使用给定的通信方式,与确定IP与端口及方法名称确定具体的过程或方法
远程代理对象
序列化协议
其中2.3两项可以概括为“调用控制协议”
Netty只是网络通信框架,目的是让你用最少的代码构建出足够支撑网络通信的功能,它是基于JAVA的NIO进行封装后的产品。
三。手写实现千万架构必备RPC框架及原理分析
(客户端调用服务端类里面的method)
思路(步骤):
1.客户端和服务端通信
2.客户端通过outputstream传递 包名 + 类名 + 方法名 + 方法参数
3.服务端通过Inputstream接收 包名 + 类名 + 方法名 + 方法参数,利用反射技术执行
1。两个进程通信
服务端(提供ip+端口让别人连接)
public static void publishServer() throws Exception {
ServerSocket serverSocket = new ServerSocket(6666);
while (true) {
serverSocket.accept();
}
}
客户端
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",6666);
}
}
2.客户端传递信息
public static void main(String[] args) throws IOException {
//1。连接服务端
Socket socket = new Socket("127.0.0.1",6666);
//2.封装要传递的信息 包名 类名 方法名 参数名称
RpcInfo rpcInfo = new RpcInfo();
rpcInfo.setPackageName("com.test.web.dao");
rpcInfo.setClazzName("OrderDao");
rpcInfo.setMethodName("server");
Object[] params = new Object[]{"华安"};
rpcInfo.setArgs(params);
//3传递 objectOutputStream.writeObject(rpcInfo);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(rpcInfo);
objectOutputStream.flush();
objectOutputStream.close();
}
3.服务端接收信息并利用反射技术执行方法
public class Server {
public static void main(String[] args) throws Exception {
publishServer();
}
/*创建服务端并接受连接请求*/
public static void publishServer() throws Exception {
ServerSocket serverSocket = new ServerSocket(6666);
ExecutorService executorService = Executors.newFixedThreadPool(5); //并发编程执行器
while (true) {
System.out.println("服务端等待连接......");
Socket accept = serverSocket.accept();
System.out.println("服务端连接成功......");
executorService.execute(new ServerHandler(accept)); //并发编程执行器 执行线程
}
}
}
public class ServerHandler implements Runnable {
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
/*调用 OrderDao.serve*/
@Override
public void run() {
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
RpcInfo rpcInfo = (RpcInfo) objectInputStream.readObject();
Class<?> clazz = Class.forName(rpcInfo.getPackageName() + "." + rpcInfo.getClazzName()); //利用反射创建类:UserDao
Class[] classes = new Class[rpcInfo.getArgs().length]; //classes是serve这个方法所有的参数类型(从客户端传过来)
for (int i = 0 ;i<classes.length;i++){
classes[i] = rpcInfo.getArgs()[i].getClass();
}
Method method = clazz.getMethod(rpcInfo.getMethodName(), classes);
method.invoke(clazz.newInstance(),rpcInfo.getArgs());
} catch (Exception e) {
e.printStackTrace();
}
}
}
四。服务暴露问题的优化(相当于做一个eureka)
将服务端的类和方法选择性地展示在页面上给客户端调用
思路:
1.确定包下的业务类
2.解析类是否需要被发布
3.解析方法是否需要被发布