问题及现象
consumer订阅多组provider,即consumer的group为*或者,分隔的多组。
provider下面两种配置会有不同表现!
<dubbo:provider group="${dubbo.provider.group}"/>
<dubbo:service interface="com.tc.dubbo.api.Provider1"
ref="provider1Impl"
/>
上面有问题, 会导致consumer找不到provider!
下面的这种没问题!
<dubbo:service interface="com.tc.dubbo.api.Provider1"
ref="provider1Impl"
group="${dubbo.provider.group}"
/>
原因
provider服务上线notify consumer的时有一个merge provider参数的过程如下
RegistryDirectory.java
merge的时候有bug
即provider显式的配置group时merge完之后的provider url就是正确的。如果不显式的配置group, merge完了之后provider group就是consumer的group(*或者,分隔),会导致consumer端找不到provider!
解决方案
simple but stupid
约定provider必须显式的配置group!
provider端解决
SPI扩展一个AbstractConfigurator
将默认的group,动态修改为显式的group. 这样merge之后就不会有问题了。
public class XxDubboConfigurator extends AbstractConfigurator {
private static final Logger LOGGER = LoggerFactory.getLogger(XxDubboConfigurator.class);
public XxDubboConfigurator(URL url) {
super(url);
}
@Override
public URL doConfigure(URL currentUrl, URL configUrl) {
if (!Constants.DUBBO_VERSION_KEY.equals(currentUrl.getProtocol())) {
return currentUrl;
}
String side = currentUrl.getParameter(Constants.SIDE_KEY);
if (Constants.PROVIDER.equals(side)) {
String defaultGroupKey = Constants.DEFAULT_KEY_PREFIX + Constants.GROUP_KEY;
String defaultGroup = currentUrl.getParameter(defaultGroupKey);
if (!currentUrl.getParameters().containsKey(Constants.GROUP_KEY) && defaultGroup != null) {
currentUrl = currentUrl.addParameterAndEncoded(Constants.GROUP_KEY, defaultGroup);
LOGGER.info("provider修改后的group:{} full url:{}", defaultGroup, currentUrl.toFullString());
}
return currentUrl;
}
return currentUrl;
}
}
consumer端解决
SPI扩展一个FailbackRegistry
consumer notify时动态修改provider url, 也可以解决后续merge url的bug!
private List<URL> toUrlsWithoutEmpty(URL consumer, List<String> providers) {
List<URL> urls = new ArrayList<URL>();
if (providers != null && providers.size() > 0) {
for (String provider : providers) {
provider = URL.decode(provider);
if (provider.contains("://")) {
URL url = URL.valueOf(provider);
if (UrlUtils.isMatch(consumer, url)) {
urls.add(providerGroupEnhance(url));
}
}
}
}
return urls;
}
private URL providerGroupEnhance(URL url) {
if (!Constants.DUBBO_VERSION_KEY.equals(url.getProtocol())) {
return url;
}
String defaultGroupKey = Constants.DEFAULT_KEY_PREFIX + Constants.GROUP_KEY;
String defaultGroup = url.getParameter(defaultGroupKey);
if (!url.getParameters().containsKey(Constants.GROUP_KEY) && defaultGroup != null) {
url = url.addParameterAndEncoded(Constants.GROUP_KEY, defaultGroup);
logger.info("provider修改后的group:{} full url:{}", defaultGroup, url.toFullString());
}
return url;
}