配合源代码使用体验更佳
- Version 1.0
- 一、Provider模块
- 1.ProviderExample
- 2.UserServiceImpl
- pom.xml
- 二、Consumer模块
- 1.ConsumerExample
- 3.UserServiceProxy(静态代理)
- pom.xml
- 三、RPC模块
- Proxy包
- 1.ServiceProxy
- 2.ServiceProxyFactory
- Registry包
- LocalRegisty
- Serializer包
- 1.JDKSerializer
- 2.Serializer接口
- Server包(提供Web服务)
- 1.HttpServer
- 2.HttpServerHandler
- 3.VertxHttpServer
- pom.xml
- 四、Common模块
- 1.RpcRequest
- 2.RpcResponse
- 3.User
- pom.xml
- V1源代码
- 常见报错以及解决方法
- 1.NullPointException
- 2.EOFException
- 3.NotSerializabel
- 4.IDEA调式传参为java.lang.Object
- 5.编码过程中的一些问题
Version 1.0
一、Provider模块
1.ProviderExample
Main:
1.当我们启动ProviderExample main的时候,首先我们会注册我们的服务,传入以下参数:(Service.class.getName(),ServiceImpl.class)
className和Impl.class 将被传给注册中心LocalRegistry 。 注册中心会将 类路径 以及 类实现class 传入到 私有的不可变map中,这个map由ConcurrentHashMap实现了线程安全。
2.通过rpc提供的web服务接口new webserver,并且调用doStart(int port)方法(硬编码:8080)。
rpc提供的 VertixHttpServer 实现了 HttpServer接口 有doStart方法。这个方法首先会初始化vertx 然后初始化HttpServer
io.vertx.core.http.HttpServer server = vertx.createHttpServer();
3.然后启动server.requestHandler(new Handler()) 去处理请求并且持续监听端口。
2.UserServiceImpl
远程方法接口实例。
pom.xml
引入了 rpc common lombok hutool-all 四个依赖
二、Consumer模块
1.ConsumerExample
main方法获取目标服务
UserService userService = ServiceProxyFactory.getProxy(UserService.class)
消费者包装了一个:fqxiny用户,满足某个方法的变量格式,然后调用远程方法 getUser
打印用户信息并且返回用户信息。远程方法服务器能够接收到这个变量,消费者能够远程调用方法,获得返回值。
返回值传给消费者,方式是在远程调用而不是被拿过来了。远程方法也能够接收参数。
3.UserServiceProxy(静态代理)
rpc消费者代理:指定构造器,初始化请求,请求序列化,发送请求到目标地址(硬编码)
另一边:(目标地址接收请求,获取请求参数,查找服务,使用服务,获得结果,初始化响应,响应序列化,响应消费者)
然后消费者代理proxy,接收响应,并反序列化获得方法调用结果。
pom.xml
引入了 rpc common hutool-all lombok 依赖
三、RPC模块
Proxy包
1.ServiceProxy
动态服务代理实例,实现了InvocationHandler接口,重写了invoke方法。
invoke方法接收 proxy,method,args 三个形参。
方法区跟静态代理是一样的,但是这里的目标地址不符合动态代理思想,应该修改为一个全局配置,这也是第二版的内容。
指定序列化器-请求初始化(封装消息)-序列化-发送-响应-接收响应-反序列化-getData
2.ServiceProxyFactory
public class ServiceProxyFactory {public static <T> T getProxy(Class<T> serviceClass) {return (T) Proxy.newProxyInstance(serviceClass.getClassLoader(),new Class[]{serviceClass},new ServiceProxy());}
}
这是一个工厂模式
Registry包
LocalRegisty
上文提及,是一个注册中心,其中有注册服务和获取服务两个方法,服务全限定名 和 实现类class 以 entry的形式存储在一个private final static ConcurrentHashMap中
Serializer包
1.JDKSerializer
实现了Serializer接口,通过Java中的转换流实现序列化和反序列化
2.Serializer接口
序列化接口,提供序列化和反序列化方法
Server包(提供Web服务)
1.HttpServer
server方法 开启端口
2.HttpServerHandler
核心方法-处理请求
初始化序列化器 ,记录日志,异步处理HTTP请求,构造响应结果对象,判断请求值,通过请求参数获得服务class,通过反射调用服务,封装返回结果。
3.VertxHttpServer
实现server 并且使用了vertix开启端口和监听请求
pom.xml
引入了 hutool-all vert.x lombok
四、Common模块
1.RpcRequest
请求格式
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RpcRequest implements Serializable {/*服务名称*/private String serviceName;/*方法名称*/private String methodName;/*参数类型*/private Class<?>[] parameterTypes;/*参数值*/private Object[] args;}
2.RpcResponse
响应格式
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RpcResponse implements Serializable {/*响应数据*/private Object data;/*响应状态*/private Class<?> dataType;/*响应信息*/private String message;/*异常信息*/private Exception exception;
}
3.User
DTO
pom.xml
引入了RPC和Lombok依赖
V1源代码
https://github.com/fqxiny/-0-1-RPC-
常见报错以及解决方法
1.NullPointException
经常出现在请求响应 method.invoke() 出的classImpl为null的情况。
说明你的类路径或者是class 注册错了,可以在map.get方法中尝试打印
2.EOFException
可以增加流的关闭方法
3.NotSerializabel
请求 或者 响应 没有实现序列化
4.IDEA调式传参为java.lang.Object
转为run 看看报错,或者退出IDEA多试几次
5.编码过程中的一些问题
- Maven依赖配置错误
- 导包错误
- 编码错误