Dubbo服务调用过程

服务调用过程

由于 Invoker 是 Dubbo 领域模型中非常重要的一个概念,很多设计思路都是向它靠拢。这就使得 Invoker 渗透在整个实现代码里,对于刚开始接触 Dubbo 的人,确实容易给搞混了。 下面我们用一个精简的图来说明最重要的两种 Invoker——服务提供 Invoker 和服务消费 Invoker:

img

贴一张服务调用的整体过程图

img

这张图可以看出大致的整理流程,然而一些集群,重试,负载均衡等步骤会专门抽出一节来讲。本章更注重服务端和消费端具体的通信细节,线程模型等。

img

客户端调用

客户端调用涉及的细节,比如集群等单独抽出一章来分析,可以先上一张图预览全貌

img

Dubbo 支持同步和异步两种调用方式,其中异步调用还可细分为“有返回值”的异步调用和“无返回值”的异步调用。所谓“无返回值”异步调用是指服务消费方只管调用,但不关心调用结果,此时 Dubbo 会直接返回一个空的 RpcResult。若要使用异步特性,需要服务消费方手动进行配置。默认情况下,Dubbo 使用同步调用方式。

// 异步无返回值
if (isOneway) {
    boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
    // 发送请求
    currentClient.send(inv, isSent);
    // 设置上下文中的 future 字段为 null
    RpcContext.getContext().setFuture(null);
    // 返回一个空的 RpcResult
    return new RpcResult();
}
// 异步有返回值
else if (isAsync) {
    // 发送请求,并得到一个 ResponseFuture 实例
    ResponseFuture future = currentClient.request(inv, timeout);
    // 设置 future 到上下文中
    RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
    // 暂时返回一个空结果
    return new RpcResult();
}
// 同步调用
else {
    RpcContext.getContext().setFuture(null);
    // 发送请求,得到一个 ResponseFuture 实例,并调用该实例的 get 方法进行等待
    return (Result) currentClient.request(inv, timeout).get();
}

调用生成ResponseFuture后,会根据唯一请求id和future对象进入一个map池子中,然后等待回调的触发。回调可能是远程的通信,也可能是超时线程检查到超时的打断。

远程通信

从前面出现过的架构图中可以看到,远程通信模块共分为三层,从上到下分别是 Exchange 信息交换层,Transport 网络传输层以及 Serialize 序列化层,每一层都有其特定的作用。

从最底层的 Serialize 层说起,这一层的作用就是负责序列化/反序列化,它对多种序列化方式进行了抽象,如 JDK 序列化,Hessian 序列化,JSON 序列化等。

往上则是 Transport 层,这一层负责的单向的消息传输,强调的是一种 Message 的语义,不体现交互的概念。同时这一层也对各种 NIO 框架进行了抽象,例如 NettyMina 等等。

再往上就是 Exhange 层,和 Transport 层不同,这一层负责的是请求/响应的交互,强调的一种 Request Reponse 的语义,也正是由于请求响应的存在,才会有 Client Server 的区分。

img

服务端处理

服务端都是通过IO线程接受请求,此时会决定是否在IO线程上进行逻辑处理。如果逻辑都在IO线程上很有可能会堵塞其他的请求,所以dubbo有五种不同的派发策略。

img

如上图,红框中的 Dispatcher 就是线程派发器。需要说明的是,Dispatcher 真实的职责创建具有线程派发能力的 ChannelHandler,比如 AllChannelHandler、MessageOnlyChannelHandler 和 ExecutionChannelHandler 等,其本身并不具备线程派发能力。Dubbo 支持 5 种不同的线程派发策略,下面通过一个表格列举一下。

策略用途
all所有消息都派发到线程池,包括请求,响应,连接事件,断开事件等
direct所有消息都不派发到线程池,全部在 IO 线程上直接执行
message只有请求响应消息派发到线程池,其它消息均在 IO 线程上执行
execution只有请求消息派发到线程池,不含响应。其它消息均在 IO 线程上执行
connection在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池

服务端收到消息,解码后。会根据invocation解析出之前暴露的对应的Exporter,然后调用invoker执行实现类中的方法,并返回处理结果。

最后附上一张官网的图:

img

源码阅读

调用过程架构概念梳理

官网服务调用过程源码

深度解析dubbo服务调用invoke流程(调用者端)

深度解析dubbo服务invoke响应处理流程(调用者端)

深度解析dubbo服务调用请求处理流程(提供者端)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值