RPC框架的实现过程
1.注册中心
a.本地注册,需要的参数是 接口名,ip和端口
b.开启ServerSocket 服务端,注册服务
c.开启线程,返回 服务注册信息
2.服务端
a.接口 实现类注册
b.开启服务端,等待客户端请求,返回结果
3.客户端
a.动态代理处理服务端请求 需要的参数是 接口名,方法名,方法参数列表,方法参数
b.结果返回
简易RPC框架(无注册中心)
服务端
package com.hikktn.center;
/**
* @ClassName App
* @Description TODO
* @Author lisonglin
* @Date 2021/3/23 21:16
* @Version 1.0
*/
public class App {
public static void main(String[] args){
HelloService helloService = new HelloServiceImpl();
RegisterCenter registerCenter=new RegisterCenter();
registerCenter.start(helloService,8888);
}
}
package com.hikktn.center;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @ClassName RegisterCenter
* @Description TODO
* @Author lisonglin
* @Date 2021/3/22 17:57
* @Version 1.0
*/
public class RegisterCenter {
// 线程池准备
private static ExecutorService executor = Executors.newFixedThreadPool(1);
// 准备一个服务端
private ServerSocket serverSocket = null;
public RegisterCenter(){
}
// 开启一个线程
public void start(Object service,int port){
// 开启服务端
try {
System.out.println("服务端开启");
serverSocket = new ServerSocket(port);
// 等待线程唤醒
while(true){
// 接收客户端发送的各种数据
executor.execute(new ProcessorHandler(serverSocket.accept(),service));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.hikktn.center;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
/**
* @ClassName ProcessorHandler
* @Description TODO
* @Author lisonglin
* @Date 2021/3/23 20:50
* @Version 1.0
*/
public class ProcessorHandler implements Runnable {
Socket socket;
Object service;
public ProcessorHandler(Socket socket, Object service) {
this.socket = socket;
this.service = service;
}
public ProcessorHandler() {
}
@Override
public void run() {
ObjectInputStream is = null;
ObjectOutputStream os = null;
try {
is = new ObjectInputStream(socket.getInputStream());
RpcRequest request =(RpcRequest) is.readObject();
// 只是调用接口执行
Object result = invoke(request);
System.out.println("服务端的结果"+result);
os = new ObjectOutputStream(socket.getOutputStream());
os.writeObject(result);
os.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private Object invoke(RpcRequest request) {
// 获取方法中的参数类型
Class<?>[] parameterTypes = request.getParameterTypes();
// 获取执行方法传入的参数
Object[] parameters = request.getParameters();
try {
// 接口类根据执行方法名和参数类型,返回一个方法类
Method method = service.getClass().getMethod(request.getMethodName(), parameterTypes);
// 调用接口实现类和参数值返回结果
Object invoke = method.invoke(service, parameters);
return invoke;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
package com.hikktn.center;
import java.io.Serializable;
import java.util.Arrays;
/**
* @ClassName RpcRequest
* @Description 提供服务
* @Author lisonglin
* @Date 2021/3/19 0:59
* @Version 1.0
*/
public class RpcRequest implements Serializable {
private static final long serialVersionUID = -4403913516658154989L;
private String className; //类名称,全包路径
private String methodName; //执行方法名
private Class<?>[] parameterTypes; //方法中的参数类型
private Object[] parameters; //执行方法传入的参数
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Class<?>[] getParameterTypes() {
return parameterTypes;
}
public void setParameterTypes(Class<?>[] parameterTypes) {
this.parameterTypes = parameterTypes;
}
public Object[] getParameters() {
return parameters;
}
public void setParameters(Object[] parameters) {
this.parameters = parameters;
}
@Override
public String toString() {
return "RpcRequest{" + "className='" + className + '\'' + ", methodName='" + methodName + '\'' + ", parameterTypes=" + Arrays.toString(parameterTypes) + ", parameters=" + Arrays.toString(parameters) + '}';
}
}
客户端
package com.hikktn.center;
/**
* @ClassName App
* @Description TODO
* @Author lisonglin
* @Date 2021/3/23 20:59
* @Version 1.0
*/
public class App {
public static void main(String[] args){
RpcClientProxy rpcClientProxy = new RpcClientProxy();
HelloService helloService = rpcClientProxy.clientProxy(HelloService.class, "localhost", 8888);
String sayHello = helloService.sayHello(1, 2);
System.out.println(sayHello);
}
}
package com.hikktn.center;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @ClassName RpcClientProxy
* @Description TODO
* @Author lisonglin
* @Date 2021/3/23 21:01
* @Version 1.0
*/
public class RpcClientProxy {
public <T> T clientProxy(Class<T> interfaceCls,String host,int port){
return (T) Proxy.newProxyInstance(interfaceCls.getClassLoader(), new Class<?>[]{interfaceCls},new Handler(host,port));
}
}
package com.hikktn.center;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.Socket;
/**
* @ClassName Handler
* @Description TODO
* @Author lisonglin
* @Date 2021/3/23 21:05
* @Version 1.0
*/
public class Handler implements InvocationHandler {
String host;
int post;
public Handler(String host, int post) {
this.host = host;
this.post = post;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
RpcRequest request = new RpcRequest();
// 类名称,全包路径
request.setClassName(method.getDeclaringClass().getName());
// 执行方法名
request.setMethodName(method.getName());
// 方法中的参数类型
request.setParameterTypes(method.getParameterTypes());
// 执行方法传入的参数
request.setParameters(args);
Socket socket = null;
ObjectInputStream objectInputStream = null;
ObjectOutputStream objectOutputStream = null;
Object result =null;
try {
socket =new Socket(host,post);
objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(request);
objectOutputStream.flush();
objectInputStream =new ObjectInputStream(socket.getInputStream());
result = objectInputStream.readObject();
}catch (IOException e){
e.printStackTrace();
}finally {
objectInputStream.close();
objectOutputStream.close();
}
return result;
}
}
复杂版
原视频地址
https://www.bilibili.com/video/BV1yE411b7PA?p=8
分析
客户端
1.读取配置
a.扫描存放接口实现类的包----consumer.xml
b.注入远程调用@Reference的类----LinkConsumerProcess.java
A. 初始化之前进行的业务实现--postProcessBeforeInitialization()
B. 初始化之后进行的业务实现--postProcessAfterInitialization()
a. 获取@Reference属性 【private】 【com.hikktn.service.AddService】 【com.hikktn.service.impl.ConsumerServiceImpl.addService】,循环Field属性
b.修改安全访问属性
c.获取存在Reference注解的接口
d.如果Reference注解存在
1.1 获取该接口类型
1.2 动态代理返回bean
注册中心
服务端
1.读取配置-----ClassMateApp.java
a.扫描存放接口实现类的包-----provider.xml
b.注入Spring包扫描机制-----LinkProviderContext.java
A.通过ApplicationContextAware扫描到接口和接口实现类--setApplicationContext()
a.扫描@Servier注解生成bean
b.根据bean的数量循环
1.1 获取接口名,包括包的路径
1.2 设置服务地址
B.加载初始化--afterPropertiesSet()
a.获取服务地址------ServerRegeisterZkImpl.regeister()
1.1 服务注册-----------ZKUtil.writeServiceNode()
A.连接zookeeper实现注册
a.如果节点存在的场合
1.1.1 创建持久化节点
b.反之
1.1.2 创建临时节点
b.开启线程池,监听客户端请求
1.1 开启服务端套接字,端口8888----ProviderServerSocketImpl.listener(port)
1.2 始终等待客户端消息
1.3 当客户端发送请求,获取客户端请求源--invoker()
A. 获取客户端输入流--getData()
B. 将客户端输入流反序列化为对象,对象存储着【类名称】、【执行方法名】、【方法中的参数列表】、【执行方法传入的参数】
C. 获取类名称
D. 获取执行方法名
F. 获取方法中的参数类型
E. 获取执行方法传入的参数
G. 接收客户端的结果----LocalMethodHandler.invoker()
1.1.1 执行动态代理代理
a. 根据类名创建接口class对象
b. 获取接口的实现类-----LinkProviderContext.applicationContext.getBean(interfaceClass)
c. 根据接口对象的方法名,方法里面的参数类型,获取一个方法对象
d. 根据该方法对象代理接口实现类,将参数进行动态代理运行,得到结果
1.1.2 设置返回响应
a. 将结果返回
b. 序列化返回客户端结果
2.启动服务
3.设置输入源,等待请求
源码:
项目地址
链接:https://pan.baidu.com/s/1GSqbpvtqlxgaLJQb56TJLQ
提取码:16xj