sofastack/sofa-rpc
在 GitHub 查看Dubbo ProtocolConfig doesn't use server's virtualHost at all
Open
#1,119 创建于 2021年11月2日
SOFA-8th-Challengeeasygood first issueremind
描述
问题描述
背景
ServerConfig 提供了以下地址相关配置:
| 字段 | 用途 | 示例场景 |
|---|---|---|
host |
实际监听 IP 或注册地址 | 0.0.0.0、192.168.1.1 |
virtualHost |
镜像 IP,注册到注册中心时使用 | NAT 环境、容器环境、负载均衡 |
virtualPort |
镜像端口,注册到注册中心时使用 | 端口映射场景 |
典型使用场景:
服务监听: 0.0.0.0:12200 (内网地址)
注册地址: 10.0.0.1:80 (公网地址/负载均衡地址)
问题所在
在 DubboProviderBootstrap.copyServerFields() 方法中,只使用了 host 和 port,完全忽略了 virtualHost 和 virtualPort 配置:
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.javacore/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 协议的正确实现)