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源码深度解析概览
下一章节:服务注册与发现
返回目录:源码阅读