文章目录
2.14 AbstractEndpoint 抽象类
public abstract class AbstractEndpoint extends AbstractPeer implements Resetable {
// ...
}

AbstractEndpoint 是 Dubbo 通信层的一个核心抽象类,继承自 AbstractPeer 并实现了 Resetable 接口,为具体的网络端点(如客户端和服务端)提供了通用的功能实现。
2.14.1 继承结构
- 继承 AbstractPeer: 获得基本的端点功能和通道处理器管理能力
- 实现 Resetable: 支持运行时动态重置配置参数
📌 关键属性
- codec: 编解码器,负责数据在网络传输格式和业务对象之间的转换
- connectTimeout: 连接超时时间,控制建立连接的最大等待时间
- logger: 日志记录器,用于输出错误和调试信息
➡️ 构造函数与初始化
public AbstractEndpoint(URL url, ChannelHandler handler) {
super(url, handler);
this.codec = getChannelCodec(url);
this.connectTimeout = url.getPositiveParameter(
Constants.CONNECT_TIMEOUT_KEY,
Constants.DEFAULT_CONNECT_TIMEOUT
);
}
2.14.2 核心功能详解
📌 1. Codec 管理 (getChannelCodec)
- 优先级查找策略:
- 首先尝试从 URL 参数获取指定编解码器名称
- 如果未指定,则默认使用协议名称作为编解码器名称
- 双重兼容机制:
- 优先查找 Codec2 扩展实现(新版本接口)
- 若不存在,则回退到传统 Codec 接口并通过适配器包装
- 默认兜底机制:
- 当找不到匹配的编解码器时,使用名为"default"的默认实现
// 之前Codec2 接口提到它是一个 SPI 扩展点,这里的 AbstractEndpoint.getChannelCodec() 方法就是基于 Dubbo SPI 选择其扩展实现的
protected static Codec2 getChannelCodec(URL url) {
String codecName = url.getParameter(Constants.CODEC_KEY);
if (StringUtils.isEmpty(codecName)) {
codecName = url.getProtocol(); // 默认使用协议名
}
FrameworkModel frameworkModel = getFrameworkModel(url.getScopeModel());
// 新版Codec2优先
if (frameworkModel.getExtensionLoader(Codec2.class).hasExtension(codecName)) {
return frameworkModel.getExtensionLoader(Codec2.class).getExtension(codecName);
}
// 兼容旧版Codec
else if (frameworkModel.getExtensionLoader(Codec.class).hasExtension(codecName)) {
return new CodecAdapter(frameworkModel.getExtensionLoader(Codec.class).getExtension(codecName));
}
// 默认实现兜底
else {
return frameworkModel.getExtensionLoader(Codec2.class).getExtension("default");
}
}
➡️ 2. 动态配置重置
允许在运行时更新部分关键配置:
- 安全检查:禁止对已关闭的端点执行重置操作
- 参数验证:只接受有效的正数作为连接超时值
- 增量更新:仅当URL中包含相应参数时才进行更新
@Override
public void reset(URL url) {
if (isClosed()) {
throw new IllegalStateException("Failed to reset parameters " + url + ", cause: Channel closed.");
}
// 更新连接超时时间
if (url.hasParameter(Constants.CONNECT_TIMEOUT_KEY)) {
int t = url.getParameter(Constants.CONNECT_TIMEOUT_KEY, 0);
if (t > 0) {
this.connectTimeout = t;
}
}
// 更新编解码器
if (url.hasParameter(Constants.CODEC_KEY)) {
this.codec = getChannelCodec(url);
}
}
2.14.3 设计亮点
- 可扩展性设计
- 基于 SPI 机制加载编解码器,支持插件化扩展
- 向下兼容老版本 Codec 接口,保证平滑升级
- 容错与健壮性
- 多层次 fallback 机制确保系统稳定运行
- 异常捕获保护防止因单个配置项失败影响整体功能
- 运维友好
- 支持热更新关键参数,无需重启服务即可调整行为
- 完善的日志记录便于问题诊断
2.14.4 应用场景
此类通常被以下具体端点类继承:
- AbstractClient: 抽象客户端实现
- AbstractServer: 抽象服务端实现
- 它们都依赖于 AbstractEndpoint 提供的基础通信能力和配置管理功能,形成完整的分层架构。
2.15 Server继承路线分析
AbstractServer 和 AbstractClient 都实现了 AbstractEndpoint 抽象类,我们先来看 AbstractServer 的实现。AbstractServer 在继承了 AbstractEndpoint 的同时,还实现了 RemotingServer 接口

AbstractServer 是对服务端的抽象,实现了服务端的公共逻辑
AbstractServer 是 Dubbo 通信层中服务器端的核心抽象基类,继承自 AbstractEndpoint 并实现了 RemotingServer 接口。
2.15.1 核心字段
- executors: 线程池集合,用于管理服务器使用的线程资源
- localAddress: 本地地址,表示服务器对外暴露的服务地址
- bindAddress: 绑定地址,表示服务器实际监听的网络接口地址
- accepts: 最大连接数限制,默认值来自 DEFAULT_ACCEPTS
- executorRepository: 线程池仓库,用于创建和管理线程池实例
2.15.2 核心方法
- 构造方法
public AbstractServer(URL url, ChannelHandler handler) throws RemotingException
- 初始化基础配置并调用 doOpen() 启动服务器
- 解析绑定IP和端口,处理任意主机地址的情况
- 创建初始线程池并添加到 executors 集合中
2.15.3 生命周期管理
- doOpen(): 抽象方法,由具体子类实现服务器开启逻辑
- doClose(): 抽象方法,由具体子类实现服务器关闭逻辑
- close(): 关闭服务器,包括关闭所有线程池和调用 doClose()
- close(int timeout): 带超时的优雅关闭方法
2.15.4 连接控制
-
connected(Channel ch): 处理客户端连接请求,检查服务器状态和连接数限制
-
disconnected(Channel ch): 处理客户端断开连接,记录相关信息
-
配置重置
@Override
public void reset(URL url)
- 动态更新最大连接数配置
- 更新线程池配置并重新设置URL参数
2.15.5 消息广播
@Override
public void send(Object message, boolean sent) throws RemotingException
向所有已经连接的客户端发送消息
2.15.6 在Dubbo中的作用
- 通信基础设施
- 作为服务器端的基础实现,为各种协议(如 dubbo、tri 等)提供统一的服务发布和连接管理能力。
- 资源管理
- 集中管理服务器的网络资源(端口绑定)和计算资源(线程池),确保资源的有效利用和正确释放。
- 连接控制
- 实现连接数限制、拒绝新连接等保护机制,防止服务器过载。
- 扩展支撑
- 通过模板方法模式(doOpen, doClose 等),为不同网络库(Netty、Mina等)的具体实现提供统一接口。
AbstractServer 是 Dubbo 服务暴露过程中的关键组件,负责处理客户端连接和服务通信,是整个远程调用体系的重要基石。

2259

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



