全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-11 8 分钟 ✍️ juanwangdev

Java RPC原理

RPC(Remote Procedure Call)让远程服务调用像本地调用一样简单。

RPC核心概念

RPC是一种技术思想,允许程序调用另一台计算机上的方法,如同调用本地方法。

本地调用 vs RPC

Java
// 本地调用
UserService userService = new UserService();
User user = userService.getUser(1);

// RPC调用(看起来一样)
UserService userService = rpcClient.getService(UserService.class);
User user = userService.getUser(1);

RPC核心组件

组件作用
客户端发起调用,组装请求
客户端代理生成代理对象,封装调用细节
序列化对象转换为字节流
网络传输发送请求/接收响应
服务端接收请求,执行方法
反射根据请求调用实际方法
反序列化字节流还原为对象

RPC调用流程

Java
客户端                          服务端
   |                               |
   |── 1.调用代理对象方法 ──────────|
   |                               |
   |── 2.序列化请求参数 ────────────|
   |                               |
   |── 3.网络发送请求 ─────────────→| 4.接收请求
   |                               |
   |                               |── 5.反序列化
   |                               |── 6.反射调用
   |                               |── 7.序列化结果
   |                               |
   |←── 8.网络返回响应 ─────────────|
   |                               |
   |── 9.反序列化结果 ──────────────|
   |                               |

动态代理实现

Java
public class RpcProxy implements InvocationHandler {
    private String host;
    private int port;

    public RpcProxy(String host, int port) {
        this.host = host;
        this.port = port;
    }

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> clazz) {
        return (T) Proxy.newProxyInstance(
            clazz.getClassLoader(),
            new Class<?>[]{clazz},
            this
        );
    }

    @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.setParamTypes(method.getParameterTypes());
        request.setParams(args);

        // 发送请求
        RpcResponse response = sendRequest(request);

        // 返回结果
        if (response.getError() != null) {
            throw response.getError();
        }
        return response.getResult();
    }

    private RpcResponse sendRequest(RpcRequest request) throws Exception {
        Socket socket = new Socket(host, port);

        // 序列化并发送
        ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
        out.writeObject(request);

        // 接收并反序列化
        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        RpcResponse response = (RpcResponse) in.readObject();

        socket.close();
        return response;
    }
}

// 使用代理
UserService userService = new RpcProxy("localhost", 8888)
    .getProxy(UserService.class);
User user = userService.getUser(1);

服务端实现

Java
public class RpcServer {
    private int port;

    public RpcServer(int port) {
        this.port = port;
    }

    public void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(port);

        while (true) {
            Socket socket = serverSocket.accept();
            new Thread(() -> handle(socket)).start();
        }
    }

    private void handle(Socket socket) {
        try {
            ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
            RpcRequest request = (RpcRequest) in.readObject();

            // 反射调用
            Object result = invoke(request);

            // 返回响应
            ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
            RpcResponse response = new RpcResponse(result);
            out.writeObject(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Object invoke(RpcRequest request) throws Exception {
        Class<?> clazz = Class.forName(request.getClassName());
        Object instance = clazz.getDeclaredConstructor().newInstance();
        Method method = clazz.getMethod(request.getMethodName(), request.getParamTypes());
        return method.invoke(instance, request.getParams());
    }
}

序列化技术

序列化方式优点缺点
Java原生简单效率低、体积大
JSON通用、可读效率中等
Protobuf高效、体积小需定义IDL
Hessian跨语言、效率高不支持所有类型
Kryo高效、体积小仅Java

注册中心

服务发现是RPC的关键组件:

text
// 服务注册
registry.register("UserService", "192.168.1.1:8888");

// 服务发现
List<String> addresses = registry.discover("UserService");

主流注册中心:Zookeeper、Nacos、Consul、Eureka

主流RPC框架

框架特点
Dubbo阿里开源,功能完善
gRPCGoogle开源,基于Protobuf
ThriftFacebook开源,跨语言
Hessian轻量级,跨语言
Spring CloudHTTP协议,生态丰富

Dubbo架构

text
Consumer → Registry(注册中心) → Provider
    ↓            ↓              ↓
  Monitor ←──────────────────────

核心角色:

  • Provider:服务提供者
  • Consumer:服务消费者
  • Registry:注册中心
  • Monitor:监控中心

注意事项

序列化要考虑跨语言兼容性

网络超时设置很重要,避免无限等待

服务注册与发现是集群部署的关键

负载均衡策略影响服务性能

异步调用提高并发性能

要点总结

  1. RPC让远程调用像本地调用一样简单
  2. 核心组件:代理、序列化、网络传输、反射
  3. 动态代理封装调用细节,用户无感知
  4. 序列化决定传输效率和跨语言能力
  5. 注册中心实现服务发现与负载均衡

📝 发现内容有误?点击此处直接编辑

← 上一篇 Java HTTP协议
下一篇 → Java Socket编程
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库