本文跟着MY-RPC-FRamework的代码,根据自己的理解做的笔记,先理解,再学习。
RPC原理
客户端和服务端都可以访问到通用的接口,但是只有服务端有这个接口的实现类,客户端调用这个接口的方式,是通过网络传输,告诉服务端我要调用这个接口,服务端收到之后找到这个接口的实现类,并且执行,将执行的结果返回给客户端,作为客户端调用接口方法的返回值。
简单实现
1. 通用接口
这个接口就是客户端需要调用的接口,也是服务端需要实现的接口,这里只定义了一个接口 hello。
public interface HelloService {
String hello(HelloObject object);
}
@Data
@AllArgsConstructor
public class HelloObject implements Serializable {
private Integer id;
private String message;
}
注意这个HelloObject 对象需要实现Serializable接口,因为它需要在调用过程中从客户端传递给服务端。实现序列化的方式很多,这里使用了JDK自带的序列化方式,后期可以改进。
有了这个公共接口,就可以先在服务端将其实现
public class HelloServiceImpl implements HelloService {
private static final Logger logger = LoggerFactory.getLogger(HelloServiceImpl.class);
@Override
public String hello(HelloObject object) {
logger.info("接收到:{}", object.getMessage());
return "这是掉用的返回值,id=" + object.getId();
}
}
传输协议
现在,思考客户端需要传输哪些信息给服务端,服务端才能知道调用哪个接口的哪个方法呢?
- 接口的名字
- 方法的名字
- 方法的参数
- 每个参数的类型
服务端知道以上四个条件,就可以找到这个方法并且调用了。我们把这四个条件写到一个对象里,到时候传输时传输这个对象就行了
@Data
@Builder
public class RpcRequest implements Serializable {
/**
* 待调用接口名称
*/
private String interfaceName;
/**
* 待调用方法名称
*/
private String methodName;
/**
* 调用方法的参数
*/
private Object[] parameters;
/**
* 调用方法的参数类型
*/
private Class<?>[] paramTypes;
}
服务器调用完这个方法后,需要给客户端返回哪些信息呢?如果调用成功的话,显然需要返回值,如果调用失败了,就需要失败的信息,这里封装成一个RpcResponse对象:
@Data
public class RpcResponse<T> implements Serializable {
/**
* 响应状态码
*/
private Integer statusCode;
/**
* 响应状态补充信息
*/
private String message;
/**
* 响应数据
*/
private T data;
public static <T> RpcResponse<T> success(T data) {
RpcResponse<T> response = new RpcResponse<>();
response.setStatusCode(ResponseCode.SUCCESS.getCode());
response.setData(data