RPC框架简单实践
创建一个简单示例,原理如下: 运行一个RPC服务器,服务器中使用ConcurrentHashMap<String, Class>存储服务实现类的类名和实例 服务提供者Provider将自己的实现类加入该Map中去,实现服务注册 服务消费者Consumer发送HTTP的服务请求,其中包含服务类名、方法名、参数类型、参数列表四个参数 RPC服务器接收到服务请求,根据解析的请求内容到Map中取相对应的实例,通过反射执行对应方法 RPC服务器将执行方法后的结果封装到响应中返回Consumer 关于Consumer发送请求如果每次都手动构造请求体就太麻烦了,有两个实现: 编写静态的代理类,也实现了服务接口,实现内部是构造相应的请求体发送给RPC服务器,获取响应后反序列化结果返回 不过这个静态代理类需要针对每个服务接口方法硬编码请求体,比如.methodName(“getUser”)这种都要手动设置 编写动态代理类,可以基于JDK动态代理实现,这样就不用手动实现每个服务接口,invoke()方法会获取到各种调用参数信息,将这些信息封装好发送就行 共享接口 RPC服务器、服务提供者、服务消费者都需要得到服务接口信息,如此才能实例化或实现功能 用户User: public class User implements Serializable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } 用户服务接口UserService: public interface UserService { /** * 获取用户 * * @param user * @return */ User getUser(User user); } RPC服务器 核心Handler中,先反序列化请求对象,从中取出请求的服务信息,从注册中心Map获取实现类实例后,通过反射执行方法,然后将执行结果封装为响应返回: public class HttpServerHandler implements Handler<HttpServerRequest> { @Override public void handle(HttpServerRequest request) { // 创建序列化器 final Serializer serializer = new JdkSerializer(); // 记录日志 System.out.println("Received request: " + request.method() + " " + request.uri()); // 异步处理请求 request.bodyHandler(body -> { byte[] bytes = body.getBytes(); RpcRequest rpcRequest = null; try { // 反序列化请求参数为RpcRequest对象 rpcRequest = serializer.deserialize(bytes, RpcRequest.class); } catch (Exception e) { e.printStackTrace(); } RpcResponse rpcResponse = new RpcResponse(); // 如果请求为空则返回错误信息 if (rpcRequest == null) { rpcResponse.setMessage("Invalid request, request is null"); doResponse(request, rpcResponse, serializer); return; } try { // 从请求取服务名,然后从注册中心获取服务实现类 Class<?> implClass = LocalRegistry.get(rpcRequest.getServiceName()); // 获取服务实现类的方法并执行 Method method = implClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes()); Object result = method.invoke(implClass.newInstance(), rpcRequest.getArgs()); // 封装响应结果 rpcResponse.setData(result); rpcResponse.setDataType(method.getReturnType()); rpcResponse.setMessage("ok"); } catch (Exception e) { e.printStackTrace(); rpcResponse.setMessage(e.getMessage()); rpcResponse.setException(e); } doResponse(request, rpcResponse, serializer); }); } private void doResponse(HttpServerRequest request, RpcResponse rpcResponse, Serializer serializer) { HttpServerResponse httpServerResponse = request.response().putHeader("content-type", "application/json"); try { // 序列化响应结果为字节数组 byte[] bytes = serializer.serialize(rpcResponse); // 发送响应 httpServerResponse.end(Buffer.buffer(bytes)); } catch (IOException e) { e.printStackTrace(); httpServerResponse.end(Buffer.buffer()); } } } 关于注册中心,维护该Map即可: ...