开发一个简易的RPC框架

一、基础的概念

  • 负载均衡:将大量用户请求分摊到不同的服务器上处理,以提高系统整体的并发处理能力以及可靠性。
  • 容错机制:(如果服务器接口调用失败,该如何处理)为保证分布式系统的高可用,会给服务器的调用机制增加容错机制。如失败重试,降级调用其他接口等。

开发一个简易的RPC框架

项目初始化
  1. common:公共模块(会同时被消费者和提供者引用)

    基础的数据模型和服务相关的接口。

  2. provider:服务提供者模块(需要暴露接口,等待消费者调用)

  3. consumer:消费者模块(需要引入rpc和common依赖)

  4. easy-rpc:简易rpc框架

    ①请求处理器

java 复制代码
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * HTTP 请求处理器处理请求
 */
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());

        // 异步处理 HTTP 请求
        request.bodyHandler(body -> {
            byte[] bytes = body.getBytes();
            RpcRequest rpcRequest = null;
            try {
                // 对请求反序列化,消费者发送的数据是byte字节数组需要转为Java对象
                rpcRequest = serializer.deserialize(bytes, RpcRequest.class);
            } catch (Exception e) {
                e.printStackTrace();
            }

            // 构造响应结果对象
            RpcResponse rpcResponse = new RpcResponse();
            // 如果请求为 null,直接返回
            if (rpcRequest == null) {
                rpcResponse.setMessage("rpcRequest 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);
        });
    }

    /**
     * 响应
     *
     * @param request
     * @param rpcResponse
     * @param serializer
     */
    void doResponse(HttpServerRequest request, RpcResponse rpcResponse, Serializer serializer) {
        HttpServerResponse httpServerResponse = request.response()
                .putHeader("content-type", "application/json");
        try {
            // 序列化
            byte[] serialized = serializer.serialize(rpcResponse);
            httpServerResponse.end(Buffer.buffer(serialized));
        } catch (IOException e) {
            e.printStackTrace();
            httpServerResponse.end(Buffer.buffer());
        }
    }
}

②请求类&响应类

java 复制代码
import java.io.Serializable;

/**
 * RPC 请求
 */
public class RpcRequest implements Serializable {

    /**
     * 服务名称
     */
    private String serviceName;

    /**
     * 方法名称
     */
    private String methodName;

    /**
     * 参数类型列表
     */
    private Class<?>[] parameterTypes;

    /**
     * 参数列表
     */
    private Object[] args;

    public String getServiceName() {
        return serviceName;
    }

    public RpcRequest(String serviceName, String methodName, Class<?>[] parameterTypes, Object[] args) {
        this.serviceName = serviceName;
        this.methodName = methodName;
        this.parameterTypes = parameterTypes;
        this.args = args;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    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[] getArgs() {
        return args;
    }

    public void setArgs(Object[] args) {
        this.args = args;
    }
}

响应类

java 复制代码
import java.io.Serializable;

/**
 * RPC 响应
 */
public class RpcResponse implements Serializable {

    /**
     * 响应数据
     */
    private Object data;

    /**
     * 响应数据类型(预留)
     */
    private Class<?> dataType;

    /**
     * 响应信息
     */
    private String message;

    /**
     * 异常信息
     */
    private Exception exception;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Class<?> getDataType() {
        return dataType;
    }

    public void setDataType(Class<?> dataType) {
        this.dataType = dataType;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Exception getException() {
        return exception;
    }

    public void setException(Exception exception) {
        this.exception = exception;
    }
}

③服务注册类

java 复制代码
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static java.util.Objects.nonNull;

/**
 * 本地注册器(理解为注册中心的作用)
 */
public class LocalRegistry {
    /**
     * 注册中心
     */
    private static final Map<String, Class<?>> registryMap = new ConcurrentHashMap<>();

    /**
     * 注册
     */
    public static void registry(String serviceName, Class<?> clazz) {
        registryMap.put(serviceName, clazz);
    }

    /**
     * 删除
     */
    public static void remove(String serviceName, Class<?> clazz) {
        registryMap.remove(serviceName);
    }

    /**
     * 获取
     */
    public static Class<?> get(String serviceName) {
        Class<?> aClass = registryMap.get(serviceName);
        if (nonNull(aClass)) {
            return aClass;
        }
        throw new RuntimeException("当前请求接口不存在:" + serviceName);
    }
}

④消费者的请求代理

java 复制代码
/**
 * 静态代理 调用服务提供者
 */
public class UserServiceProxy implements UserService {
    @Override
    public User getUser() {
        RpcRequest rpcRequest = new RpcRequest(UserService.class.getName(), "getUser", new Class[]{}, new Object[]{});
        Serializer serializer = new JdkSerializer();
        try {
            byte[] bytes = serializer.serialize(rpcRequest);
            HttpResponse response = HttpRequest.post("http://localhost:8099/").body(bytes).execute();
            RpcResponse rpcResponse = serializer.deserialize(response.bodyBytes(), RpcResponse.class);
            return (User) rpcResponse.getData();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
相关推荐
网络研究院2 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展
酣大智2 天前
ARP代理--工作原理
运维·网络·arp·arp代理
treesforest2 天前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
shushangyun_2 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
2601_961845152 天前
粉笔行测题库|系统班|刷题
网络·百度·微信·微信公众平台·facebook·新浪微博
程序员mine2 天前
HTTPS-TLS加密与证书完全指南(中)
网络协议·https·ssl
程序猿阿伟2 天前
《Chrome离线扩展安装的底层逻辑与场景落地指南》
服务器·网络·chrome
之歆2 天前
现代 HTTP 客户端深度解析:Fetch 与 Axios
chrome·网络协议·http
InHand云飞小白2 天前
无人值守站点网络困境?工业级路由器IR315破解连接难题
网络·物联网·4g·工业路由器·4g路由器·iiot·蜂窝路由器
小胖xiaopangss2 天前
BRpc使用
c++·rpc