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

2.18.1 Request
Exchange 层的 Request 和 Response 这两个类是 Exchange 层的核心对象,是对请求和响应的抽象。我们先来看 Request 类的核心字段:
Request 类是 Dubbo 框架中用于表示远程调用请求的核心数据结构。它封装了请求的各种属性,包括唯一标识符、版本号、通信模式等,并提供了操作这些属性的方法。
🚀 1. 基本字段
INVOKE_ID: 静态原子长整型,用于生成全局唯一的请求ID
mId: 请求的唯一标识符,类型为long
mVersion: 协议版本号,用于标识当前使用的协议版本
mTwoWay: 双向通信标志位,默认为true,表示需要响应
mEvent: 事件标志位,标识此请求是否为特殊事件(如心跳)
mBroken: 故障标志位,标识连接是否已损坏
mPayload: 负载大小,记录传输的数据量
mData: 实际传输的数据对象
🆚 2. 初始化机制
static {
long startID = ThreadLocalRandom.current().nextLong();
if (Boolean.parseBoolean(SystemPropertyConfigUtils.getSystemProperty(DUBBO_USE_SECURE_RANDOM_ID, "false"))) {
try {
SecureRandom rand = new SecureRandom(SecureRandom.getSeed(20));
startID = rand.nextLong();
} catch (Throwable ignore) {
}
}
INVOKE_ID = new AtomicLong(startID);
}
- 始化块负责设置初始ID值,支持安全随机数生成选项,可以通过系统属性 DUBBO_USE_SECURE_RANDOM_ID 控制是否使用更安全的随机数生成器
📆 3. 核心方法解析
- 构建方法
Request(): 默认构造函数,自动生成新的请求ID
Request(long id): 使用指定ID构造请求对象
- ID管理
newId(): 生成新的唯一ID,利用AtomicLong保证线程安全性
- 特殊功能方法
isHeartbeat(): 判断是否为心跳请求
setHeartbeat(): 设置心跳请求标志
safeToString(): 安全地将对象转换为字符串,防止toString()方法抛出异常影响程序执行
toString(): 提供友好的调试输出格式
📢 4. 设计特点
- 线程安全: 使用AtomicLong生成ID,确保多线程环境下的安全性
- 灵活配置: 支持通过系统属性控制随机数生成策略
- 容错设计: 在toString()方法中加入异常处理,提高程序健壮性
- 内存优化: 提供不带数据的复制方法,在某些场景下节省内存开销
- 扩展性好: 通过布尔标志位区分不同类型请求,便于后续扩展
2.18.2 Response
Response 类是 Dubbo 框架中与 Request 相对应的重要组件,用于封装服务调用的响应结果。它是 Dubbo 远程通信机制中的关键数据结构之一。
🔊 1. 核心字段
- 状态常量
OK: 正常响应状态码 (20)
SERIALIZATION_ERROR: 序列化错误 (25)
CLIENT_TIMEOUT: 客户端超时 (30)
SERVER_TIMEOUT: 服务端超时 (31)
CHANNEL_INACTIVE: 通道不活跃 (35)
BAD_REQUEST: 请求格式错误 (40)
BAD_RESPONSE: 响应格式错误 (50)
SERVICE_NOT_FOUND: 服务未找到 (60)
SERVICE_ERROR: 服务错误 (70)
SERVER_ERROR: 服务器内部错误 (80)
CLIENT_ERROR: 客户端错误 (90)
SERVER_THREADPOOL_EXHAUSTED_ERROR: 服务端线程池耗尽 (100)
- 实例字段
mId: 响应ID,与对应的 Request 的ID一致,用于匹配请求和响应
mVersion: 协议版本号
mStatus: 响应状态码,默认为 OK
mEvent: 是否为事件消息标识
mErrorMsg: 错误信息描述
mResult: 响应结果数据
- 构造方法
public Response() {}
public Response(long id) { mId = id; }
public Response(long id, String version) { mId = id; mVersion = version; }
- 核心方法
- ID管理
getId(): 获取响应ID
setId(long id): 设置响应ID
// 版本控制
getVersion(): 获取协议版本
setVersion(String version): 设置协议版本
// 状态管理
getStatus(): 获取响应状态码
setStatus(byte status): 设置响应状态码
// 事件处理
isEvent(): 判断是否为事件消息
setEvent(String event): 设置事件消息及内容
setEvent(boolean mEvent): 设置事件标识
isHeartbeat(): 判断是否为心跳事件
setHeartbeat(boolean isHeartbeat): 设置心跳标识(已废弃)
// 数据处理
getResult(): 获取响应结果
setResult(Object msg): 设置响应结果
getErrorMessage(): 获取错误信息
setErrorMessage(String msg): 设置错误信息
📢 2. 设计特点
- 状态码体系完善:定义了丰富的响应状态码,覆盖各种异常情况
- 与Request对应:通过相同的ID机制实现请求-响应的匹配
- 事件支持:继承了Dubbo的事件机制,支持心跳等特殊消息
- 错误处理完备:提供了专门的错误信息字段和多种错误状态码
- 向后兼容:保留了已废弃但仍在使用的方法
🔑 3. 工作原理
- Response 对象通常在以下场景中被创建和使用:
- 服务提供方处理完 Request 后创建 Response 并返回结果
- 网络通信层通过ID将 Response 与对应的 Request 进行匹配
- 客户端接收到 Response 后根据状态码判断调用是否成功
- 异常情况下通过 mErrorMsg 和状态码提供详细的错误信息

7724

被折叠的 条评论
为什么被折叠?



