Skip to content

RPC原理深度解析 ​

深入分析Dubbo RPC调用的完整流程,理解协议设计和远程调用的实现机制,掌握Invoker抽象、代理机制、远程调用的发送和接收流程。

📋 RPC调用概览 ​

RPC(Remote Procedure Call,远程过程调用)是Dubbo的核心功能,允许客户端像调用本地方法一样调用远程服务。

🎯 一、RPC调用流程 ​

1.1 调用流程图 ​

1.2 核心组件 ​

代理对象(Proxy):客户端调用的入口,动态代理生成

Invoker:调用抽象,封装了调用的逻辑

Protocol:协议抽象,定义了通信协议

Transport:传输层,负责网络通信

🎯 二、Invoker抽象 ​

2.1 Invoker接口 ​

Invoker是Dubbo的核心抽象,代表一个可调用的服务:

java
public interface Invoker<T> extends Node {
    Class<T> getInterface();
    Result invoke(Invocation invocation) throws RpcException;
}

核心方法:

  • getInterface:获取服务接口类型
  • invoke:执行调用,返回Result

2.2 Invoker类型 ​

本地Invoker:调用本地服务的Invoker

远程Invoker:调用远程服务的Invoker

协议Invoker:协议层封装的Invoker

集群Invoker:集群层封装的Invoker,包含负载均衡和容错逻辑

2.3 Invoker链 ​

Dubbo通过Invoker链实现功能的叠加:

ClusterInvoker -> LoadBalanceInvoker -> FailoverInvoker -> ProtocolInvoker -> RemoteInvoker

每一层的作用:

  • ClusterInvoker:集群容错
  • LoadBalanceInvoker:负载均衡
  • ProtocolInvoker:协议封装
  • RemoteInvoker:远程调用

🎯 三、协议设计 ​

3.1 Protocol接口 ​

Protocol定义了服务暴露和引用的协议:

java
public interface Protocol {
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
    void destroy();
}

3.2 Dubbo协议 ​

Dubbo协议是默认的RPC协议,基于TCP长连接:

协议格式:

+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|  Magic | Flag   | Status |    Id (Request/Response Id)                         |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|                                                                                  |
|                              Data Length (Variable)                              |
|                                                                                  |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|                                                                                  |
|                               Variable Data                                      |
|                                                                                  |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+

协议特点:

  • 单连接:一个客户端与一个服务端只建立一个连接
  • 多路复用:多个请求共享一个连接
  • 序列化:支持多种序列化方式

3.3 其他协议 ​

HTTP协议:基于HTTP/HTTPS的RPC协议

REST协议:RESTful风格的RPC协议

gRPC协议:基于gRPC的RPC协议

🎯 四、代理机制 ​

4.1 动态代理 ​

Dubbo使用动态代理生成服务接口的代理对象:

JDK动态代理:

java
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
    return (T) Proxy.newProxyInstance(
            Thread.currentThread().getContextClassLoader(),
            interfaces,
            new InvokerInvocationHandler(invoker));
}

Javassist代理:

java
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
    return (T) Proxy.getProxy(interfaces).newInstance(
            new InvokerInvocationHandler(invoker));
}

4.2 InvokerInvocationHandler ​

InvokerInvocationHandler是代理对象的调用处理器:

java
public class InvokerInvocationHandler implements InvocationHandler {
    private final Invoker<?> invoker;
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) 
            throws Throwable {
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        
        // 处理Object方法
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        
        // 处理toString、equals、hashCode方法
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
            return invoker.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
            return invoker.equals(args[0]);
        }
        
        // 创建Invocation
        RpcInvocation invocation = new RpcInvocation(method, invoker.getInterface().getName(), args);
        invocation.setAttachment("path", invoker.getUrl().getPath());
        invocation.setAttachment("group", invoker.getUrl().getParameter("group"));
        invocation.setAttachment("version", invoker.getUrl().getParameter("version"));
        
        // 调用Invoker
        Result result = invoker.invoke(invocation);
        return result.recreate();
    }
}

🎯 五、远程调用 ​

5.1 请求发送 ​

NettyClient发送请求:

java
@Override
public Response request(Request request, int timeout) throws RemotingException {
    Channel channel = getChannel();
    if (channel == null || !channel.isConnected()) {
        throw new RemotingException(this, "message can not send, because channel is closed.");
    }
    
    ResponseFuture responseFuture = new DefaultResponseFuture(channel, request, timeout);
    channel.send(request);
    return responseFuture;
}

5.2 请求接收 ​

NettyServerHandler接收请求:

java
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
    try {
        handler.received(channel, msg);
    } finally {
        NettyChannel.removeChannelIfDisconnected(ctx.channel());
    }
}

5.3 响应处理 ​

AllChannelHandler处理响应:

java
@Override
public void received(Channel channel, Object message) throws RemotingException {
    ExecutorService executor = getExecutorService();
    try {
        executor.execute(new ChannelEventRunnable(channel, handler, 
                ChannelState.RECEIVED, message));
    } catch (Throwable t) {
        throw new ExecutionException("...");
    }
}

📖 学习资源 ​

视频教程 ​

书籍推荐 ​

  • 《深度剖析Apache Dubbo核心技术内幕》 - 华仔
  • 《分布式服务框架原理与实践》 - 李林锋

网站资源 ​

✅ 学习检查清单 ​

  • [ ] 已理解RPC调用完整流程
  • [ ] 已理解Invoker抽象
  • [ ] 已理解协议设计
  • [ ] 已理解代理机制
  • [ ] 已理解远程调用实现
  • [ ] 已绘制RPC调用时序图
  • [ ] 已总结核心知识点

上一章节:Dubbo源码深度解析概览
下一章节:服务注册与发现
返回目录:源码阅读