sofastack/sofa-rpc

Dubbo ProtocolConfig doesn't use server's virtualHost at all

Open

#1,119 建立於 2021年11月2日

在 GitHub 查看
 (2 留言) (0 反應) (0 負責人)Java (3,749 star) (1,151 fork)batch import
SOFA-8th-Challengeeasygood first issueremind

描述

问题描述

背景

ServerConfig 提供了以下地址相关配置:

字段 用途 示例场景
host 实际监听 IP 或注册地址 0.0.0.0192.168.1.1
virtualHost 镜像 IP,注册到注册中心时使用 NAT 环境、容器环境、负载均衡
virtualPort 镜像端口,注册到注册中心时使用 端口映射场景

典型使用场景

服务监听: 0.0.0.0:12200 (内网地址)
注册地址: 10.0.0.1:80 (公网地址/负载均衡地址)

问题所在

DubboProviderBootstrap.copyServerFields() 方法中,只使用了 hostport,完全忽略了 virtualHostvirtualPort 配置:

private void copyServerFields(ServerConfig serverConfig, ProtocolConfig protocolConfig) {
    // ...
    protocolConfig.setHost(serverConfig.getHost());  // ❌ 只使用了 host
    protocolConfig.setPort(serverConfig.getPort());  // ❌ 只使用了 port
    // ...
}

影响范围

当使用 Dubbo 协议在以下场景时,服务无法被正确消费:

  • 容器环境(Docker/Kubernetes)
  • NAT 网络环境
  • 负载均衡后端服务
  • 需要端口映射的场景

复现步骤

ServerConfig serverConfig = new ServerConfig()
    .setProtocol("dubbo")
    .setHost("0.0.0.0")
    .setPort(12200)
    .setVirtualHost("10.0.0.1")   // 期望注册到注册中心的 IP
    .setVirtualPort(80);          // 期望注册到注册中心的端口

ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>()
    .setInterfaceId(HelloService.class.getName())
    .setRef(new HelloServiceImpl())
    .setServer(serverConfig)
    .setRegistry(registryConfig);

providerConfig.export();
// 问题:注册到注册中心的地址是 0.0.0.0:12200,而不是 10.0.0.1:80

期望行为

当配置了 virtualHost/virtualPort 时,Dubbo 协议应该将虚拟地址注册到注册中心,与 Bolt 协议行为一致。

修复方案

修改 DubboProviderBootstrap.copyServerFields() 方法,优先使用 virtualHost/virtualPort

private void copyServerFields(ServerConfig serverConfig, ProtocolConfig protocolConfig) {
    // ... 其他字段 ...
    
    // 优先使用 virtualHost/virtualPort
    String host = StringUtils.isNotBlank(serverConfig.getVirtualHost()) 
        ? serverConfig.getVirtualHost() 
        : serverConfig.getHost();
    Integer port = serverConfig.getVirtualPort() != null 
        ? serverConfig.getVirtualPort() 
        : serverConfig.getPort();
    
    protocolConfig.setHost(host);
    protocolConfig.setPort(port);
}

相关代码

  • bootstrap/bootstrap-dubbo/src/main/java/com/alipay/sofa/rpc/bootstrap/dubbo/DubboProviderBootstrap.java
  • core/api/src/main/java/com/alipay/sofa/rpc/config/ServerConfig.java
  • 参考:registry/registry-nacos/src/test/java/com/alipay/sofa/rpc/registry/nacos/NacosRegistryTest.java (Bolt 协议的正确实现)

貢獻者指南