learn-tech/专栏/Dubbo源码解读与实战-完/21Exchange层剖析:彻底搞懂Request-Response模型(上).md
2024-10-16 00:01:16 +08:00

17 KiB
Raw Blame History

                        因收到Google相关通知网站将会择期关闭。相关通知内容
                        
                        
                        21  Exchange 层剖析:彻底搞懂 Request-Response 模型(上)
                        在前面的课程中,我们深入介绍了 Dubbo Remoting 中的 Transport 层,了解了 Dubbo 抽象出来的端到端的统一传输层接口,并分析了以 Netty 为基础的相关实现。当然,其他 NIO 框架的接入也是类似的,本课程就不再展开赘述了。

在本课时中,我们将介绍 Transport 层的上一层,也是 Dubbo Remoting 层中的最顶层—— Exchange 层。Dubbo 将信息交换行为抽象成 Exchange 层,官方文档对这一层的说明是:封装了请求-响应的语义,即关注一问一答的交互模式,实现了同步转异步。在 Exchange 这一层,以 Request 和 Response 为中心,针对 Channel、ChannelHandler、Client、RemotingServer 等接口进行实现。

下面我们从 Request 和 Response 这一对基础类开始,依次介绍 Exchange 层中 ExchangeChannel、HeaderExchangeHandler 的核心实现。

Request 和 Response

Exchange 层的 Request 和 Response 这两个类是 Exchange 层的核心对象是对请求和响应的抽象。我们先来看Request 类的核心字段:

public class Request {

// 用于生成请求的自增ID当递增到Long.MAX_VALUE之后会溢出到Long.MIN_VALUE我们可以继续使用该负数作为消息ID

private static final AtomicLong INVOKE_ID = new AtomicLong(0);

private final long mId; // 请求的ID

private String mVersion; // 请求版本号

// 请求的双向标识如果该字段设置为true则Server端在收到请求后

// 需要给Client返回一个响应

private boolean mTwoWay = true; 

// 事件标识,例如心跳请求、只读请求等,都会带有这个标识

private boolean mEvent = false; 

// 请求发送到Server之后由Decoder将二进制数据解码成Request对象

// 如果解码环节遇到异常则会设置该标识然后交由其他ChannelHandler根据

// 该标识做进一步处理

private boolean mBroken = false;

// 请求体可以是任何Java类型的对象,也可以是null

private Object mData; 

}

接下来是 Response 的核心字段:

public class Response {

// 响应ID与相应请求的ID一致

private long mId = 0;

// 当前协议的版本号,与请求消息的版本号一致

private String mVersion;

// 响应状态码有OK、CLIENT_TIMEOUT、SERVER_TIMEOUT等10多个可选值

private byte mStatus = OK; 

private boolean mEvent = false;

private String mErrorMsg; // 可读的错误响应消息

private Object mResult; // 响应体

}

ExchangeChannel & DefaultFuture

在前面的课时中,我们介绍了 Channel 接口的功能以及 Transport 层对 Channel 接口的实现。在 Exchange 层中定义了 ExchangeChannel 接口,它在 Channel 接口之上抽象了 Exchange 层的网络连接。ExchangeChannel 接口的定义如下:

ExchangeChannel 接口

其中request() 方法负责发送请求,从图中可以看到这里有两个重载,其中一个重载可以指定请求的超时时间,返回值都是 Future 对象。

HeaderExchangeChannel 继承关系图

从上图中可以看出HeaderExchangeChannel 是 ExchangeChannel 的实现,它本身是 Channel 的装饰器,封装了一个 Channel 对象,其 send() 方法和 request() 方法的实现都是依赖底层修饰的这个 Channel 对象实现的。

public void send(Object message, boolean sent) throws RemotingException {

if (message instanceof Request || message instanceof Response

        || message instanceof String) {

    channel.send(message, sent);

} else {

    Request request = new Request();

    request.setVersion(Version.getProtocolVersion());

    request.setTwoWay(false);

    request.setData(message);

    channel.send(request, sent);

}

}

public CompletableFuture