万字图文详解Dubbo 3.x RPC调用核心流程
万字图文详解Dubbo 3.x RPC调用核心流程
本文深入解析Dubbo 3.x版本的RPC调用核心流程,从服务提供者暴露到消费者引用,再到参数封装、ClusterFilter过滤、集群调用逻辑决策、路由策略、负载均衡、Filter过滤、通信协议、序列化协议等多个关键环节,通过图文结合的方式,帮助读者全面理解Dubbo的内部工作机制。
一个简单的Demo
为了保证文章的完整性和连贯性,这里快速讲解一个Dubbo的简单示例。如果你已经熟悉Dubbo,可以直接跳过本节。
在Dubbo中,RPC调用主要涉及两个角色:
- 服务提供者:提供一个接口供消费者远程调用
- 服务消费者:调用生产者提供的接口
一个简单的Dubbo示例工程结构如下:
- 接口层:提供者和消费者都需要依赖,服务提供者实现,服务消费者调用
- 服务提供者:单独一个工程,实现
DemoService
接口,通过@DubboService
注解表明提供DemoService
服务 - 服务消费者:单独一个工程,使用单元测试,通过
@DubboReference
注解表明消费DemoService
服务接口
启动服务提供者,运行消费者单元测试,结果如下:
成功实现远程服务调用。
服务提供者暴露
服务提供者暴露主要包含两件事:
- 根据使用的协议和端口启动服务。默认使用Dubbo协议,端口为20880。
- 将接口的详细信息(包括全限定名、方法名称、参数、服务器IP、端口等)存储到元数据中心和服务提供者本地缓存中。
消费者引用
消费者引用主要包含两件事:
- 创建接口的动态代理。Dubbo支持JDK动态代理和Javassist动态生成字节码两种方式,默认使用Javassist。
- 获取服务提供者的接口详细信息,从元数据中心或服务提供者本地缓存中获取。
参数封装
当调用消费者动态代理时,最终会走到InvokerInvocationHandler
的invoke
方法。首先将RPC调用的接口、方法名、参数封装到RpcInvocation
中,然后调用invoker.invoke(rpcInvocation)
触发后续流程。
ClusterFilter过滤
ClusterFilter是一种责任链模式,用于对请求进行预处理。Dubbo默认提供了多种实现,如MonitorClusterFilter用于统计调用信息,Sentinel等框架也通过这个扩展点与Dubbo整合。
集群调用逻辑决策
在实际生产环境中,服务通常以集群方式部署。Dubbo提供了多种集群调用策略:
- 广播(broadcast)
- 可用性检查(available)
- 重试(failback)
- 快速失败(failfast)
- 故障转移(failover)
- 安全失败(failsafe)
- 并行调用(forking)
- 结果合并(mergeable)
默认使用的是failover
策略。
路由策略
路由策略用于选择允许调用的服务实例。例如,在灰度发布场景中,可以使用tag
路由策略来区分灰度环境和正式环境的服务。
负载均衡
负载均衡策略用于选择具体的服务实例。Dubbo支持多种算法:
- 随机(random)
- 轮询(roundrobin)
- 最少活跃优先(leastactive)
- 最短响应优先(shortestresponse)
- 一致性Hash(consistenthash)
默认使用随机(random)算法。
Filter过滤
Filter是Dubbo预留的扩展点,可以在发送请求前对整个请求进行自定义扩展。与ClusterFilter不同,Filter在调用每个服务实例前都会重新调用。
通信协议
Dubbo支持多种通信协议:
- Dubbo协议(默认)
- Rest(HTTP协议)
- gRPC
- Triple(兼容gRPC,支持HTTP/1和HTTP/2)
序列化协议
序列化协议用于将数据转换为字节序列。Dubbo支持多种序列化协议:
- Java原生
- Hessian2
- Fastjson2
Dubbo 3.2.0版本之前默认使用Hessian2,之后默认使用Fastjson2。
服务提供者处理请求
服务提供者接收到请求后,会解析字节序列,获取调用的接口、方法和参数,通过反射调用接口实现,并将结果序列化返回给消费者。
总结
Dubbo的RPC调用流程涉及多个关键环节,每个环节都提供了丰富的扩展点。从服务暴露到请求处理,Dubbo的设计充分考虑了灵活性和可扩展性,使其能够适应各种复杂的微服务场景。