【050】Dubbo3从0到1系列之HeaderExchangeServer

2.22 HeaderExchangeServer

HeaderExchangeServer 是 Apache Dubbo 中用于服务端通信的核心实现类,负责管理服务器端的连接、消息交换和资源控制。

在这里插入图片描述

HeaderExchangeServer 是 RemotingServer 的装饰器,实现自 RemotingServer 接口的大部分方法都委托给了所修饰的 RemotingServer 对象。

  • 核心职责
    • 封装底层服务器: 包装 RemotingServer 实例,提供统一的服务端接口
    • 连接管理: 管理客户端连接,监控连接状态
    • 空闲检测: 实现连接空闲超时机制
    • 优雅关闭: 支持带超时的服务器关闭流程

2.22.1 重要特性详解

private void startIdleCheckTask(URL url) {
    if (!server.canHandleIdle()) {
        AbstractTimerTask.ChannelProvider cp =
                () -> unmodifiableCollection(HeaderExchangeServer.this.getChannels());
        int closeTimeout = getCloseTimeout(url);
        long closeTimeoutTick = calculateLeastDuration(closeTimeout);
        this.closeTimer = new CloseTimerTask(cp, IDLE_CHECK_TIMER.get(), closeTimeoutTick, closeTimeout);
    }
}
  • 使用全局共享的 HashedWheelTimer 定时器进行空闲检测
  • 当底层服务器无法自行处理空闲连接时,启动 CloseTimerTask
  • 定期检查连接是否超时,自动关闭空闲连接

2.22.2 优雅关闭机制

✔️ 1. 基本关闭流程

@Override
public void close() {
    if (!closed.compareAndSet(false, true)) {
        return;
    }
    doClose();
    server.close();
}

🚀 2. 带超时的关闭流程:

@Override
public void close(final int timeout) {
    if (!closed.compareAndSet(false, true)) {
        return;
    }
    startClose();
    if (timeout > 0) {
        final long start = System.currentTimeMillis();
        if (getUrl().getParameter(Constants.CHANNEL_SEND_READONLYEVENT_KEY, true)) {
            sendChannelReadOnlyEvent();
        }
        while (HeaderExchangeServer.this.isRunning() && System.currentTimeMillis() - start < (long) timeout) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                logger.warn(TRANSPORT_FAILED_CLOSE, "", "", e.getMessage(), e);
            }
        }
    }
    doClose();
    server.close(timeout);
}

关键步骤:

  • 设置关闭状态标志
  • 发送只读事件通知客户端
  • 等待现有连接处理完成或超时
  • 执行资源清理
  • 关闭底层服务器

2.22.3 只读事件通知

private void sendChannelReadOnlyEvent() {
    Request request = new Request();
    request.setEvent(READONLY_EVENT);
    request.setTwoWay(false);
    request.setVersion(Version.getProtocolVersion());

    Collection<Channel> channels = getChannels();
    for (Channel channel : channels) {
        try {
            if (channel.isConnected()) {
                channel.send(request, getUrl().getParameter(Constants.CHANNEL_READONLYEVENT_SENT_KEY, true));
            }
        } catch (RemotingException e) {
            if (closed.get() && e.getCause() instanceof ClosedChannelException) {
                // ignore ClosedChannelException which means the connection has been closed.
                continue;
            }
            logger.warn(TRANSPORT_FAILED_RESPONSE, "", "", "send cannot write message error.", e);
        }
    }
}

在服务器关闭前向所有连接的客户端发送只读事件,通知客户端服务器即将关闭,不再接受新请求。

2.22.4 连接管理

@Override
public Collection<ExchangeChannel> getExchangeChannels() {
    Collection<ExchangeChannel> exchangeChannels = new ArrayList<>();
    Collection<Channel> channels = server.getChannels();
    if (CollectionUtils.isNotEmpty(channels)) {
        for (Channel channel : channels) {
            exchangeChannels.add(HeaderExchangeChannel.getOrAddChannel(channel));
        }
    }
    return exchangeChannels;
}

  • 统一管理所有客户端连接
  • 为每个底层 Channel 创建或获取对应的 HeaderExchangeChannel
  • 提供对所有连接的访问接口

2.22.5 核心设计要点

  • 资源复用: 使用 GlobalResourceInitializer 确保定时器等资源在整个JVM中唯一
  • 线程安全: 使用 AtomicBoolean 控制关闭状态,防止重复关闭
  • 异常处理: 合理处理连接关闭过程中的各种异常情况
  • 配置驱动: 通过URL参数灵活控制各种行为(如是否发送只读事件等)
  • 平滑过渡: 在关闭过程中给客户端足够时间处理完正在进行的请求

HeaderExchangeServer 是Dubbo服务端通信的重要组件,通过封装底层服务器实现,提供了完善的连接管理、空闲检测和优雅关闭机制,确保服务端能够稳定可靠地运行和服务客户端请求。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值